diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 184ee0df0bdb..6151c9569df1 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -66,7 +66,12 @@ jobs: strategy: fail-fast: false matrix: - sim: [ethereum/rpc, smoke/genesis, smoke/network, ethereum/sync] + # TODO: enable etherem/sync once resolved: + # https://github.com/paradigmxyz/reth/issues/8579 + # TODO: enable ethereum/rpc once resolved: + # https://github.com/ethereum/hive/pull/1117 + # sim: [ethereum/rpc, smoke/genesis, smoke/network, ethereum/sync] + sim: [smoke/genesis, smoke/network] include: - sim: devp2p limit: discv4 @@ -93,17 +98,26 @@ jobs: - TestBlobViolations - sim: ethereum/engine limit: engine-exchange-capabilities - - sim: ethereum/engine - limit: engine-withdrawals + # TODO: enable engine-withdrawals once resolved: + # https://github.com/paradigmxyz/reth/issues/8732 + # - sim: ethereum/engine + # limit: engine-withdrawals - sim: ethereum/engine limit: engine-auth - sim: ethereum/engine limit: engine-transition - - sim: ethereum/engine - limit: engine-api - - sim: ethereum/engine - limit: cancun - # eth_ rpc methods + # TODO: enable engine-api once resolved: + # https://github.com/paradigmxyz/reth/issues/6217 + # https://github.com/paradigmxyz/reth/issues/8305 + # - sim: ethereum/engine + # limit: engine-api + # TODO: enable cancun once resolved: + # https://github.com/paradigmxyz/reth/issues/6217 + # https://github.com/paradigmxyz/reth/issues/8306 + # https://github.com/paradigmxyz/reth/issues/7144 + # - sim: ethereum/engine + # limit: cancun + # eth_ rpc methods - sim: ethereum/rpc-compat include: - eth_blockNumber @@ -123,9 +137,12 @@ jobs: - eth_getTransactionReceipt - eth_sendRawTransaction - eth_syncing - # debug_ rpc methods - - sim: ethereum/rpc-compat - include: [debug_] + # TODO: enable debug_ rpc-compat once resolved: + # https://github.com/paradigmxyz/reth/issues/7015 + # https://github.com/paradigmxyz/reth/issues/6332 + # debug_ rpc methods + # - sim: ethereum/rpc-compat + # include: [debug_] # Pyspec cancun jobs - sim: pyspec include: [cancun/eip4844] diff --git a/Cargo.lock b/Cargo.lock index f9600585a2c8..6b5a686a98a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,12 +124,12 @@ dependencies = [ [[package]] name = "alloy-consensus" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "arbitrary", "c-kzg", "proptest", @@ -140,7 +140,7 @@ dependencies = [ [[package]] name = "alloy-consensus" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#a4bb5f0be3eec5c8679bdab93c1482df38ba8509" +source = "git+https://github.com/alloy-rs/alloy#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-primitives", @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd2404399cb1b50572758e66e9b4bf088e5a3df9007be7126456c7e50af935f" +checksum = "cb6e6436a9530f25010d13653e206fab4c9feddacf21a54de8d7311b275bc56b" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -171,11 +171,11 @@ dependencies = [ [[package]] name = "alloy-eips" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "arbitrary", "c-kzg", "derive_more", @@ -189,7 +189,7 @@ dependencies = [ [[package]] name = "alloy-eips" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#a4bb5f0be3eec5c8679bdab93c1482df38ba8509" +source = "git+https://github.com/alloy-rs/alloy#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -203,10 +203,10 @@ dependencies = [ [[package]] name = "alloy-genesis" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", - "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "serde", "serde_json", ] @@ -214,7 +214,7 @@ dependencies = [ [[package]] name = "alloy-genesis" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#a4bb5f0be3eec5c8679bdab93c1482df38ba8509" +source = "git+https://github.com/alloy-rs/alloy#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", @@ -224,9 +224,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3abf6446a292e19853aaca43590eeb48bf435dfd2c74200259e8f4872f6ce3" +checksum = "aaeaccd50238126e3a0ff9387c7c568837726ad4f4e399b528ca88104d6c25ef" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -237,7 +237,7 @@ dependencies = [ [[package]] name = "alloy-json-rpc" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", "serde", @@ -249,13 +249,13 @@ dependencies = [ [[package]] name = "alloy-network" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-json-rpc", "alloy-primitives", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types-eth 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-signer", "alloy-sol-types", "async-trait", @@ -267,9 +267,9 @@ dependencies = [ [[package]] name = "alloy-node-bindings" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-primitives", "k256", "serde_json", @@ -281,9 +281,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5277af0cbcc483ee6ad2c1e818090b5928d27f04fd6580680f31c1cf8068bcc2" +checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad" dependencies = [ "alloy-rlp", "arbitrary", @@ -309,17 +309,17 @@ dependencies = [ [[package]] name = "alloy-provider" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-chains", - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-json-rpc", "alloy-network", "alloy-primitives", "alloy-pubsub", "alloy-rpc-client", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types-eth 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-rpc-types-trace", "alloy-transport", "alloy-transport-http", @@ -332,7 +332,7 @@ dependencies = [ "futures-utils-wasm", "lru", "pin-project", - "reqwest 0.12.4", + "reqwest", "serde", "serde_json", "tokio", @@ -343,7 +343,7 @@ dependencies = [ [[package]] name = "alloy-pubsub" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -383,7 +383,7 @@ dependencies = [ [[package]] name = "alloy-rpc-client" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -393,7 +393,7 @@ dependencies = [ "alloy-transport-ws", "futures", "pin-project", - "reqwest 0.12.4", + "reqwest", "serde", "serde_json", "tokio", @@ -406,59 +406,38 @@ dependencies = [ [[package]] name = "alloy-rpc-types" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-sol-types", - "arbitrary", - "itertools 0.12.1", - "jsonrpsee-types", - "proptest", - "proptest-derive", - "serde", - "serde_json", - "thiserror", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", ] [[package]] name = "alloy-rpc-types" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#a4bb5f0be3eec5c8679bdab93c1482df38ba8509" +source = "git+https://github.com/alloy-rs/alloy#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", - "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy)", - "alloy-primitives", - "alloy-rlp", + "alloy-rpc-types-eth 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", - "alloy-sol-types", - "itertools 0.12.1", - "serde", - "serde_json", - "thiserror", ] [[package]] name = "alloy-rpc-types-anvil" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", - "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "serde", ] [[package]] name = "alloy-rpc-types-beacon" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-primitives", "alloy-rpc-types-engine", "serde", @@ -469,14 +448,14 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types-eth 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "jsonrpsee-types", "jsonwebtoken 9.3.0", "rand 0.8.5", @@ -484,14 +463,54 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-rpc-types-eth" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-sol-types", + "arbitrary", + "itertools 0.13.0", + "jsonrpsee-types", + "proptest", + "proptest-derive", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#14ed25d8ab485fc0d313fd1e055862c9d20ef273" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-sol-types", + "itertools 0.13.0", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "alloy-rpc-types-trace" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types-eth 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "serde", "serde_json", ] @@ -499,7 +518,7 @@ dependencies = [ [[package]] name = "alloy-serde" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", "serde", @@ -509,7 +528,7 @@ dependencies = [ [[package]] name = "alloy-serde" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#a4bb5f0be3eec5c8679bdab93c1482df38ba8509" +source = "git+https://github.com/alloy-rs/alloy#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", "serde", @@ -519,7 +538,7 @@ dependencies = [ [[package]] name = "alloy-signer" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-primitives", "async-trait", @@ -532,9 +551,9 @@ dependencies = [ [[package]] name = "alloy-signer-wallet" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-network", "alloy-primitives", "alloy-signer", @@ -548,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30708a79919b082f2692423c8cc72fc250477e4a2ecb0d4a7244cd3cdb299965" +checksum = "4bad41a7c19498e3f6079f7744656328699f8ea3e783bdd10d85788cd439f572" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -562,9 +581,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a679ac01774ab7e00a567a918d4231ae692c5c8cedaf4e16956c3116d7896" +checksum = "fd9899da7d011b4fe4c406a524ed3e3f963797dbc93b45479d60341d3a27b252" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -581,9 +600,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356da0c2228aa6675a5faaa08a3e4061b967f924753983d72b9a18d9a3fad44e" +checksum = "d32d595768fdc61331a132b6f65db41afae41b9b97d36c21eb1b955c422a7e60" dependencies = [ "alloy-json-abi", "const-hex", @@ -598,18 +617,18 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fd4783b0a5840479013e9ce960d2eb7b3be381f722e0fe3d1f7c3bb6bd4ebd" +checksum = "baa2fbd22d353d8685bd9fee11ba2d8b5c3b1d11e56adb3265fcf1f32bfdf404" dependencies = [ "winnow 0.6.13", ] [[package]] name = "alloy-sol-types" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eb5e6234c0b62514992589fe1578f64d418dbc8ef5cd1ab2d7f2f568f599698" +checksum = "a49042c6d3b66a9fe6b2b5a8bf0d39fc2ae1ee0310a2a26ffedd79fb097878dd" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -621,7 +640,7 @@ dependencies = [ [[package]] name = "alloy-transport" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -633,17 +652,16 @@ dependencies = [ "tokio", "tower", "url", - "wasm-bindgen-futures", ] [[package]] name = "alloy-transport-http" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-json-rpc", "alloy-transport", - "reqwest 0.12.4", + "reqwest", "serde_json", "tower", "tracing", @@ -653,12 +671,12 @@ dependencies = [ [[package]] name = "alloy-transport-ws" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=cc68b93#cc68b93605f4521c2b0bce1a7efaeff2046cf07c" +source = "git+https://github.com/alloy-rs/alloy?rev=14ed25d#14ed25d8ab485fc0d313fd1e055862c9d20ef273" dependencies = [ "alloy-pubsub", "alloy-transport", "futures", - "http 0.2.12", + "http 1.1.0", "serde_json", "tokio", "tokio-tungstenite", @@ -1140,7 +1158,7 @@ dependencies = [ "clap", "eyre", "futures-util", - "reqwest 0.12.4", + "reqwest", "reth", "reth-node-ethereum", "serde", @@ -1641,6 +1659,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -1730,9 +1754,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.6" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -1740,9 +1764,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.6" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -1770,9 +1794,9 @@ checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "coins-bip32" -version = "0.8.7" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" +checksum = "66c43ff7fd9ff522219058808a259e61423335767b1071d5b346de60d9219657" dependencies = [ "bs58", "coins-core", @@ -1786,9 +1810,9 @@ dependencies = [ [[package]] name = "coins-bip39" -version = "0.8.7" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" +checksum = "4c4587c0b4064da887ed39a6522f577267d57e58bdd583178cd877d721b56a2e" dependencies = [ "bitvec", "coins-bip32", @@ -1802,19 +1826,18 @@ dependencies = [ [[package]] name = "coins-core" -version = "0.8.7" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" +checksum = "6b3aeeec621f4daec552e9d28befd58020a78cfc364827d06a753e8bc13c6c4b" dependencies = [ "base64 0.21.7", "bech32", "bs58", + "const-hex", "digest 0.10.7", "generic-array", - "hex", "ripemd", "serde", - "serde_derive", "sha2 0.10.8", "sha3", "thiserror", @@ -1826,6 +1849,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "comfy-table" version = "7.1.1" @@ -2692,15 +2725,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - [[package]] name = "endian-type" version = "0.1.2" @@ -2851,9 +2875,12 @@ dependencies = [ "eyre", "reth", "reth-exex", + "reth-exex-test-utils", "reth-node-api", "reth-node-ethereum", + "reth-testing-utils", "reth-tracing", + "tokio", ] [[package]] @@ -2897,7 +2924,7 @@ dependencies = [ name = "exex-rollup" version = "0.0.0" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-rlp", "alloy-sol-types", "eyre", @@ -3060,7 +3087,7 @@ dependencies = [ "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", "chrono", - "reqwest 0.12.4", + "reqwest", "serde", ] @@ -3323,16 +3350,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", - "http 0.2.12", + "http 1.1.0", "indexmap 2.2.6", "slab", "tokio", @@ -3521,17 +3548,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.0" @@ -3544,22 +3560,22 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body", "pin-project-lite", ] [[package]] name = "http-range-header" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "http-types" @@ -3583,9 +3599,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "9f3935c160d00ac752e09787e6e6bfc26494c2183cc922f1bc678a60d4733bc2" [[package]] name = "httpdate" @@ -3615,30 +3631,6 @@ dependencies = [ "serde", ] -[[package]] -name = "hyper" -version = "0.14.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.7", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.3.1" @@ -3648,9 +3640,11 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2", "http 1.1.0", - "http-body 1.0.0", + "http-body", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -3660,34 +3654,36 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 0.2.12", - "hyper 0.14.29", - "log", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", + "http 1.1.0", + "hyper", + "hyper-util", + "rustls 0.22.4", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls 0.25.0", + "tower-service", ] [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.3.1", + "hyper", "hyper-util", - "rustls 0.22.4", + "log", + "rustls 0.23.9", "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tower-service", ] @@ -3701,8 +3697,8 @@ dependencies = [ "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", + "http-body", + "hyper", "pin-project-lite", "socket2 0.5.7", "tokio", @@ -3905,12 +3901,14 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -4140,12 +4138,41 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.31" @@ -4166,9 +4193,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdb12a2381ea5b2e68c3469ec604a007b367778cdb14d09612c8069ebd616ad" +checksum = "95a130d27083a4001b7b2d72a19f08786299550f76c9bd5307498dce2c2b20fa" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -4184,40 +4211,44 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4978087a58c3ab02efc5b07c5e5e2803024536106fd5506f558db172c889b3aa" +checksum = "039db9fe25cd63b7221c3f8788c1ef4ea07987d40ec25a1e7d7a3c3e3e3fd130" dependencies = [ + "base64 0.22.1", "futures-channel", "futures-util", "gloo-net", - "http 0.2.12", + "http 1.1.0", "jsonrpsee-core", "pin-project", - "rustls-native-certs 0.7.0", + "rustls 0.23.9", "rustls-pki-types", + "rustls-platform-verifier", "soketto", "thiserror", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tokio-util", "tracing", "url", - "webpki-roots 0.26.2", ] [[package]] name = "jsonrpsee-core" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b257e1ec385e07b0255dde0b933f948b5c8b8c28d42afda9587c3a967b896d" +checksum = "21545a9445fbd582840ff5160a9a3e12b8e6da582151cdb07bde9a1970ba3a24" dependencies = [ "anyhow", "async-trait", "beef", + "bytes", "futures-timer", "futures-util", - "hyper 0.14.29", + "http 1.1.0", + "http-body", + "http-body-util", "jsonrpsee-types", "parking_lot 0.12.3", "pin-project", @@ -4234,15 +4265,20 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ccf93fc4a0bfe05d851d37d7c32b7f370fe94336b52a2f0efc5f1981895c2e5" +checksum = "fb25cab482c8512c4f3323a5c90b95a3b8f7c90681a87bf7a68b942d52f08933" dependencies = [ "async-trait", - "hyper 0.14.29", - "hyper-rustls 0.24.2", + "base64 0.22.1", + "http-body", + "hyper", + "hyper-rustls 0.27.2", + "hyper-util", "jsonrpsee-core", "jsonrpsee-types", + "rustls 0.23.9", + "rustls-platform-verifier", "serde", "serde_json", "thiserror", @@ -4254,11 +4290,11 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d0bb047e79a143b32ea03974a6bf59b62c2a4c5f5d42a381c907a8bbb3f75c0" +checksum = "c18184cd09b386feb18085609e8bf77bdc942482bdd82777b433b8d015edf561" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro-crate", "proc-macro2", "quote", @@ -4267,13 +4303,17 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12d8b6a9674422a8572e0b0abb12feeb3f2aeda86528c80d0350c2bd0923ab41" +checksum = "810f63eff0f78fa8d413d678c0e55b702e2ea61d4587774c0db4ea2fc554ef92" dependencies = [ + "anyhow", "futures-util", - "http 0.2.12", - "hyper 0.14.29", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", + "hyper-util", "jsonrpsee-core", "jsonrpsee-types", "pin-project", @@ -4291,12 +4331,12 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "150d6168405890a7a3231a3c74843f58b8959471f6df76078db2619ddee1d07d" +checksum = "f511b714bca46f9a3e97c0e0eb21d2c112e83e444d2db535b5ec7093f5836d73" dependencies = [ - "anyhow", "beef", + "http 1.1.0", "serde", "serde_json", "thiserror", @@ -4304,9 +4344,9 @@ dependencies = [ [[package]] name = "jsonrpsee-wasm-client" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f448d8eacd945cc17b6c0b42c361531ca36a962ee186342a97cdb8fca679cd77" +checksum = "8c8a6dfa0c35c8549fa8e003ce0bbcf37b051ab7ef85fce587e8f0ed7881c84d" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -4315,11 +4355,11 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.22.5" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b9db2dfd5bb1194b0ce921504df9ceae210a345bc2f6c5a61432089bbab070" +checksum = "786c100eb67df2f2d863d231c2c6978bcf80ff4bf606ffc40e7e68ef562da7bf" dependencies = [ - "http 0.2.12", + "http 1.1.0", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", @@ -4409,25 +4449,6 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "libffi" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2" -dependencies = [ - "libc", - "libffi-sys", -] - -[[package]] -name = "libffi-sys" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" -dependencies = [ - "cc", -] - [[package]] name = "libloading" version = "0.8.3" @@ -4842,9 +4863,9 @@ dependencies = [ [[package]] name = "mev-share-sse" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae69b99298d095098be0e6a3159545aa7232e5b62e2c170d5a53f6b690000f3" +checksum = "20cbf228751922258c86a8492b39f987bb22338bef0b09426c106853be0c9fc7" dependencies = [ "alloy-primitives", "async-sse", @@ -4852,7 +4873,7 @@ dependencies = [ "futures-util", "http-types", "pin-project-lite", - "reqwest 0.11.27", + "reqwest", "serde", "serde_json", "thiserror", @@ -5836,7 +5857,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", "rusty-fork", "tempfile", "unarray", @@ -6077,14 +6098,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -6098,13 +6119,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -6115,9 +6136,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "regress" @@ -6129,44 +6150,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "winreg 0.50.0", -] - [[package]] name = "reqwest" version = "0.12.4" @@ -6178,9 +6161,9 @@ dependencies = [ "futures-core", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body", "http-body-util", - "hyper 1.3.1", + "hyper", "hyper-rustls 0.26.0", "hyper-util", "ipnet", @@ -6191,8 +6174,8 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls 0.22.4", - "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.2", + "rustls-native-certs", + "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", @@ -6200,12 +6183,14 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-rustls 0.25.0", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", - "webpki-roots 0.26.2", + "webpki-roots", "winreg 0.52.0", ] @@ -6453,9 +6438,9 @@ dependencies = [ name = "reth-codecs" version = "0.2.0-beta.9" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-primitives", "arbitrary", "bytes", @@ -6516,13 +6501,13 @@ dependencies = [ name = "reth-consensus-debug-client" version = "0.2.0-beta.9" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-provider", "auto_impl", "eyre", "futures", - "reqwest 0.12.4", + "reqwest", "reth-node-api", "reth-node-core", "reth-rpc-api", @@ -6558,6 +6543,7 @@ dependencies = [ "reth-nippy-jar", "reth-primitives", "reth-prune-types", + "reth-stages-types", "reth-storage-errors", "reth-tracing", "reth-trie-types", @@ -6592,6 +6578,7 @@ dependencies = [ "reth-codecs", "reth-primitives", "reth-prune-types", + "reth-stages-types", "reth-storage-errors", "reth-trie-types", "serde", @@ -6611,6 +6598,7 @@ dependencies = [ "reth-etl", "reth-primitives", "reth-provider", + "reth-stages-types", "reth-trie", "serde", "serde_json", @@ -6729,9 +6717,9 @@ dependencies = [ name = "reth-e2e-test-utils" version = "0.2.0-beta.9" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-network", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-signer", "alloy-signer-wallet", "eyre", @@ -6745,6 +6733,7 @@ dependencies = [ "reth-provider", "reth-rpc", "reth-rpc-layer", + "reth-stages-types", "reth-tokio-util", "reth-tracing", "serde_json", @@ -6950,7 +6939,7 @@ dependencies = [ name = "reth-evm-ethereum" version = "0.2.0-beta.9" dependencies = [ - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-sol-types", "reth-ethereum-consensus", "reth-evm", @@ -6997,6 +6986,8 @@ dependencies = [ name = "reth-execution-types" version = "0.2.0-beta.9" dependencies = [ + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-primitives", "reth-execution-errors", "reth-primitives", "reth-trie", @@ -7099,7 +7090,6 @@ dependencies = [ "derive_more", "indexmap 2.2.6", "libc", - "libffi", "parking_lot 0.12.3", "pprof", "rand 0.8.5", @@ -7157,7 +7147,7 @@ name = "reth-net-nat" version = "0.2.0-beta.9" dependencies = [ "futures-util", - "reqwest 0.12.4", + "reqwest", "reth-tracing", "serde_with", "thiserror", @@ -7337,6 +7327,7 @@ dependencies = [ "reth-provider", "reth-prune", "reth-rpc", + "reth-rpc-builder", "reth-rpc-engine-api", "reth-rpc-layer", "reth-rpc-types", @@ -7362,8 +7353,9 @@ dependencies = [ "dirs-next", "eyre", "futures", + "http 1.1.0", "humantime", - "hyper 0.14.29", + "jsonrpsee", "metrics", "metrics-exporter-prometheus", "metrics-process", @@ -7392,10 +7384,10 @@ dependencies = [ "reth-prune-types", "reth-rpc", "reth-rpc-api", - "reth-rpc-builder", "reth-rpc-server-types", "reth-rpc-types", "reth-rpc-types-compat", + "reth-stages-types", "reth-storage-errors", "reth-tasks", "reth-tracing", @@ -7408,6 +7400,7 @@ dependencies = [ "tikv-jemalloc-ctl", "tokio", "tokio-util", + "tower", "tracing", "vergen", ] @@ -7469,14 +7462,14 @@ dependencies = [ "async-trait", "clap", "eyre", - "hyper 0.14.29", "jsonrpsee", "parking_lot 0.12.3", - "reqwest 0.12.4", + "reqwest", "reth", "reth-basic-payload-builder", "reth-beacon-consensus", "reth-db", + "reth-discv5", "reth-e2e-test-utils", "reth-evm", "reth-evm-optimism", @@ -7587,12 +7580,12 @@ name = "reth-primitives" version = "0.2.0-beta.9" dependencies = [ "alloy-chains", - "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", - "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-trie", "arbitrary", "assert_matches", @@ -7660,6 +7653,7 @@ dependencies = [ "reth-nippy-jar", "reth-primitives", "reth-prune-types", + "reth-stages-types", "reth-storage-api", "reth-storage-errors", "reth-testing-utils", @@ -7723,7 +7717,7 @@ dependencies = [ name = "reth-revm" version = "0.2.0-beta.9" dependencies = [ - "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-rlp", "reth-consensus-common", "reth-execution-errors", @@ -7749,9 +7743,9 @@ dependencies = [ "derive_more", "dyn-clone", "futures", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "http 1.1.0", + "http-body", + "hyper", "jsonrpsee", "jsonwebtoken 8.3.0", "metrics", @@ -7824,7 +7818,8 @@ dependencies = [ name = "reth-rpc-builder" version = "0.2.0-beta.9" dependencies = [ - "hyper 0.14.29", + "clap", + "http 1.1.0", "jsonrpsee", "metrics", "pin-project", @@ -7836,6 +7831,7 @@ dependencies = [ "reth-ipc", "reth-metrics", "reth-network-api", + "reth-node-core", "reth-payload-builder", "reth-primitives", "reth-provider", @@ -7852,7 +7848,6 @@ dependencies = [ "reth-transaction-pool", "serde", "serde_json", - "strum", "thiserror", "tokio", "tower", @@ -7898,11 +7893,11 @@ version = "0.2.0-beta.9" dependencies = [ "alloy-rpc-types-engine", "assert_matches", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "http 1.1.0", "jsonrpsee", + "jsonrpsee-http-client", "pin-project", + "reqwest", "tempfile", "tokio", "tower", @@ -7914,6 +7909,8 @@ name = "reth-rpc-server-types" version = "0.2.0-beta.9" dependencies = [ "alloy-primitives", + "serde", + "strum", ] [[package]] @@ -7921,7 +7918,7 @@ name = "reth-rpc-types" version = "0.2.0-beta.9" dependencies = [ "alloy-primitives", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-rpc-types-anvil", "alloy-rpc-types-beacon", "alloy-rpc-types-engine", @@ -7942,7 +7939,7 @@ name = "reth-rpc-types-compat" version = "0.2.0-beta.9" dependencies = [ "alloy-rlp", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "reth-primitives", "reth-rpc-types", "serde_json", @@ -8008,6 +8005,7 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-prune", + "reth-stages-types", "reth-static-file", "reth-testing-utils", "reth-tokio-util", @@ -8017,6 +8015,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "reth-stages-types" +version = "0.2.0-beta.9" +dependencies = [ + "alloy-primitives", + "arbitrary", + "bytes", + "modular-bitfield", + "proptest", + "proptest-derive", + "rand 0.8.5", + "reth-codecs", + "reth-trie-types", + "serde", + "test-fuzz", +] + [[package]] name = "reth-static-file" version = "0.2.0-beta.9" @@ -8058,6 +8073,7 @@ dependencies = [ "reth-execution-types", "reth-primitives", "reth-prune-types", + "reth-stages-types", "reth-storage-errors", "reth-trie", "revm", @@ -8092,7 +8108,7 @@ dependencies = [ name = "reth-testing-utils" version = "0.2.0-beta.9" dependencies = [ - "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "rand 0.8.5", "reth-primitives", "secp256k1 0.28.2", @@ -8176,6 +8192,7 @@ dependencies = [ "reth-metrics", "reth-primitives", "reth-provider", + "reth-stages-types", "reth-storage-errors", "reth-trie-types", "revm", @@ -8250,10 +8267,10 @@ dependencies = [ [[package]] name = "revm-inspectors" version = "0.1.0" -source = "git+https://github.com/paradigmxyz/evm-inspectors?rev=53aa2b2#53aa2b2add84298e9eb0d4a080d41314c85695ab" +source = "git+https://github.com/paradigmxyz/revm-inspectors?rev=5e3058a#5e3058a87caa24df748e090083ef76518d082c10" dependencies = [ "alloy-primitives", - "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cc68b93)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", "alloy-rpc-types-trace", "alloy-sol-types", "anstyle", @@ -8530,42 +8547,33 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.12" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", "ring 0.17.8", - "rustls-webpki 0.101.7", - "sct", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", ] [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +checksum = "a218f0f6d05669de4eabfb24f31ce802035c952429d037507b4a4a39f0e60c5b" dependencies = [ "log", + "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework", -] - [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -8573,21 +8581,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.2", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -8605,15 +8604,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] -name = "rustls-webpki" -version = "0.101.7" +name = "rustls-platform-verifier" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "b5f0d26fa1ce3c790f9590868f0109289a044acb954525f933e2aa3b871c157d" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.9", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-roots", + "winapi", ] +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e217e7fdc8466b5b35d30f8c0a30febd29173df4a3a0c2115d306b9c4117ad" + [[package]] name = "rustls-webpki" version = "0.102.4" @@ -8710,16 +8726,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", -] - [[package]] name = "sdd" version = "0.2.0" @@ -8789,6 +8795,7 @@ dependencies = [ "core-foundation", "core-foundation-sys", "libc", + "num-bigint", "security-framework-sys", ] @@ -8969,19 +8976,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha1" version = "0.10.6" @@ -9192,18 +9186,18 @@ dependencies = [ [[package]] name = "soketto" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +checksum = "37468c595637c10857701c990f93a40ce0e357cedb0953d1c26c8d8027f9bb53" dependencies = [ - "base64 0.13.1", + "base64 0.22.1", "bytes", "futures", - "http 0.2.12", + "http 1.1.0", "httparse", "log", "rand 0.8.5", - "sha-1", + "sha1", ] [[package]] @@ -9375,9 +9369,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6fe08d08d84f2c0a77f1e7c46518789d745c2e87a2721791ed7c3c9bc78df28" +checksum = "8d71e19bca02c807c9faa67b5a47673ff231b6e7449b251695188522f1dc44b2" dependencies = [ "paste", "proc-macro2", @@ -9417,27 +9411,6 @@ dependencies = [ "windows 0.52.0", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tap" version = "1.0.1" @@ -9714,21 +9687,22 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.21.12", + "rustls 0.22.4", + "rustls-pki-types", "tokio", ] [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.22.4", + "rustls 0.23.9", "rustls-pki-types", "tokio", ] @@ -9747,17 +9721,18 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "becd34a233e7e31a3dbf7c7241b38320f57393dcae8e7324b0167d21b8e320b0" dependencies = [ "futures-util", "log", - "rustls 0.21.12", + "rustls 0.23.9", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls 0.26.0", "tungstenite", - "webpki-roots 0.25.4", + "webpki-roots", ] [[package]] @@ -9843,9 +9818,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "async-compression", "base64 0.21.7", @@ -9853,8 +9828,9 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http 0.2.12", - "http-body 0.4.6", + "http 1.1.0", + "http-body", + "http-body-util", "http-range-header", "httpdate", "iri-string", @@ -10081,21 +10057,21 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" dependencies = [ "byteorder", "bytes", "data-encoding", - "http 0.2.12", + "http 1.1.0", "httparse", "log", "rand 0.8.5", - "rustls 0.21.12", + "rustls 0.23.9", + "rustls-pki-types", "sha1", "thiserror", - "url", "utf-8", ] @@ -10228,12 +10204,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.0", "percent-encoding", "serde", ] @@ -10444,12 +10420,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "webpki-roots" version = "0.26.2" diff --git a/Cargo.toml b/Cargo.toml index 6ebb09c2835b..26b48055ad50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ members = [ "crates/rpc/rpc/", "crates/stages/api/", "crates/stages/stages/", + "crates/stages/types/", "crates/static-file/types/", "crates/static-file/static-file", "crates/storage/codecs/", @@ -119,7 +120,7 @@ members = [ "examples/rpc-db/", "examples/txpool-tracing/", "testing/ef-tests/", - "testing/testing-utils" + "testing/testing-utils", ] default-members = ["bin/reth"] @@ -316,6 +317,7 @@ reth-rpc-types = { path = "crates/rpc/rpc-types" } reth-rpc-types-compat = { path = "crates/rpc/rpc-types-compat" } reth-stages = { path = "crates/stages/stages" } reth-stages-api = { path = "crates/stages/api" } +reth-stages-types = { path = "crates/stages/types" } reth-static-file = { path = "crates/static-file/static-file" } reth-static-file-types = { path = "crates/static-file/types" } reth-storage-api = { path = "crates/storage/storage-api" } @@ -330,9 +332,15 @@ reth-trie-parallel = { path = "crates/trie/parallel" } reth-trie-types = { path = "crates/trie/types" } # revm -revm = { version = "9.0.0", features = [ "std", "secp256k1", "blst", ], default-features = false } -revm-primitives = { version = "4.0.0", features = [ "std", ], default-features = false } -revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors", rev = "53aa2b2" } +revm = { version = "9.0.0", features = [ + "std", + "secp256k1", + "blst", +], default-features = false } +revm-primitives = { version = "4.0.0", features = [ + "std", +], default-features = false } +revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors", rev = "5e3058a" } # eth alloy-chains = "0.1.15" @@ -341,21 +349,21 @@ alloy-dyn-abi = "0.7.2" alloy-sol-types = "0.7.2" alloy-rlp = "0.3.4" alloy-trie = "0.4" -alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-rpc-types-anvil = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-rpc-types-trace = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-rpc-types-engine = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-rpc-types-beacon = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-genesis = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93", default-features = false, features = [ +alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-rpc-types-anvil = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-rpc-types-trace = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-rpc-types-engine = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-rpc-types-beacon = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-genesis = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d", default-features = false, features = [ "reqwest", ] } -alloy-eips = { git = "https://github.com/alloy-rs/alloy", default-features = false, rev = "cc68b93" } -alloy-signer = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-signer-wallet = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-network = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } -alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "cc68b93" } +alloy-eips = { git = "https://github.com/alloy-rs/alloy", default-features = false, rev = "14ed25d" } +alloy-signer = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-signer-wallet = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-network = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } +alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "14ed25d" } # misc auto_impl = "1" @@ -415,21 +423,25 @@ async-trait = "0.1.68" futures = "0.3.26" pin-project = "1.0.12" futures-util = "0.3.25" -hyper = "0.14.25" +hyper = "1.3" +hyper-util = "0.1.5" reqwest = { version = "0.12", default-features = false } tower = "0.4" -tower-http = "0.4" -http = "0.2.8" -http-body = "0.4.5" +tower-http = "0.5" # p2p discv5 = "0.6.0" igd-next = "0.14.3" # rpc -jsonrpsee = "0.22" -jsonrpsee-core = "0.22" -jsonrpsee-types = "0.22" +jsonrpsee = "0.23" +jsonrpsee-core = "0.23" +jsonrpsee-types = "0.23" +jsonrpsee-http-client = "0.23" + +# http +http = "1.0" +http-body = "1.0" # crypto secp256k1 = { version = "0.28", default-features = false, features = [ diff --git a/README.md b/README.md index 646e492d2d29..7862ac03f403 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ **Modular, contributor-friendly and blazing-fast implementation of the Ethereum protocol** -![](./assets/reth-beta.png) +![](./assets/reth-prod.png) **[Install](https://paradigmxyz.github.io/reth/installation/installation.html)** | [User Book](https://reth.rs) @@ -38,27 +38,21 @@ More concretely, our goals are: ## Status -Reth is performant, feature-complete, [Cancun-ready](https://paradigmxyz.github.io/reth/run/run-a-node.html), and OP Stack Ecotone compatible via the [OP Reth binary](https://paradigmxyz.github.io/reth/run/optimism.html?highlight=optimism#running-on-optimism). - -We actively recommend professional node operators to switch to Reth in production for performance and cost reasons in use cases where high performance with great margins is required such as RPC, MEV, Indexing, Simulations, and P2P activities. - -While we are aware of parties running Reth staking nodes in production, we do *not* encourage usage in production staking environments by non-professionals until our audits are done, and the 1.0 version of Reth is released, but we are available to support without warranty or liability. +Reth is production ready, and suitable for usage in mission-critical environments such as staking or high-uptime services. We also actively recommend professional node operators to switch to Reth in production for performance and cost reasons in use cases where high performance with great margins is required such as RPC, MEV, Indexing, Simulations, and P2P activities. More historical context below: -* We are releasing 1.0 "production-ready" stable Reth once our Reth & Revm audits are done. ETA ~May 2024. - * Reth is currently undergoing an audit with [Sigma Prime](https://sigmaprime.io/), the developers of [Lighthouse](https://github.com/sigp/lighthouse), the Rust Consensus Layer implementation. - * Revm (the EVM used in Reth) is undergoing an audit with [Guido Vranken](https://twitter.com/guidovranken) (#1 [Ethereum Bug Bounty](https://ethereum.org/en/bug-bounty)). -* We are releasing [beta](https://github.com/paradigmxyz/reth/releases/tag/v0.2.0-beta.1) on Monday March 4th 2024, our first breaking change to the database model, providing faster query speed, smaller database footprint, and allowing "history" to be mounted on separate drives. +* We released 1.0 "production-ready" stable Reth in June 2024. + * Reth completed an audit with [Sigma Prime](https://sigmaprime.io/), the developers of [Lighthouse](https://github.com/sigp/lighthouse), the Rust Consensus Layer implementation. Find it [here](./Sigma_Prime_Paradigm_Reth_Security_Assessment_Report_v1_0.pdf). + * Revm (the EVM used in Reth) underwent an audit with [Guido Vranken](https://twitter.com/guidovranken) (#1 [Ethereum Bug Bounty](https://ethereum.org/en/bug-bounty)). We will publish the results soon. +* We released multiple iterative beta versions, up to [beta.9](https://github.com/paradigmxyz/reth/releases/tag/v0.2.0-beta.9) on Monday June 3rd 2024 the last beta release. +* We released [beta](https://github.com/paradigmxyz/reth/releases/tag/v0.2.0-beta.1) on Monday March 4th 2024, our first breaking change to the database model, providing faster query speed, smaller database footprint, and allowing "history" to be mounted on separate drives. * We shipped iterative improvements until the last alpha release on February 28th 2024, [0.1.0-alpha.21](https://github.com/paradigmxyz/reth/releases/tag/v0.1.0-alpha.21). * We [initially announced](https://www.paradigm.xyz/2023/06/reth-alpha) [0.1.0-alpha.1](https://github.com/paradigmxyz/reth/releases/tag/v0.1.0-alpha.1) in June 20th 2023. - -We will be updating the documentation with the completion status of each component, as well as include more contributing guidelines (design docs, architecture diagrams, repository layouts) and "good first issues". - -We appreciate your patience until we get there. Until then, we are happy to answer all questions in the Telegram link above. - ### Database compatibility +We do not have any breaking database changes since beta.1, and do not plan any in the near future. + Reth [v0.2.0-beta.1](https://github.com/paradigmxyz/reth/releases/tag/v0.2.0-beta.1) includes a [set of breaking database changes](https://github.com/paradigmxyz/reth/pull/5191) that makes it impossible to use database files produced by earlier versions. diff --git a/Sigma_Prime_Paradigm_Reth_Security_Assessment_Report_v1_0.pdf b/Sigma_Prime_Paradigm_Reth_Security_Assessment_Report_v1_0.pdf new file mode 100644 index 000000000000..4b31fb2b4448 Binary files /dev/null and b/Sigma_Prime_Paradigm_Reth_Security_Assessment_Report_v1_0.pdf differ diff --git a/assets/reth-prod.png b/assets/reth-prod.png new file mode 100644 index 000000000000..d06c4579ccfb Binary files /dev/null and b/assets/reth-prod.png differ diff --git a/bin/reth/src/commands/common.rs b/bin/reth/src/commands/common.rs index 0517b5395f03..5fd81d1637dd 100644 --- a/bin/reth/src/commands/common.rs +++ b/bin/reth/src/commands/common.rs @@ -14,11 +14,11 @@ use reth_node_core::{ }, dirs::{ChainPath, DataDirPath}, }; -use reth_primitives::{stage::PipelineTarget, ChainSpec}; +use reth_primitives::ChainSpec; use reth_provider::{ providers::StaticFileProvider, HeaderSyncMode, ProviderFactory, StaticFileProviderFactory, }; -use reth_stages::{sets::DefaultStages, Pipeline}; +use reth_stages::{sets::DefaultStages, Pipeline, PipelineTarget}; use reth_static_file::StaticFileProducer; use std::{path::PathBuf, sync::Arc}; use tracing::{debug, info, warn}; diff --git a/bin/reth/src/commands/debug_cmd/build_block.rs b/bin/reth/src/commands/debug_cmd/build_block.rs index 31b51f856455..119a6d98f642 100644 --- a/bin/reth/src/commands/debug_cmd/build_block.rs +++ b/bin/reth/src/commands/debug_cmd/build_block.rs @@ -25,7 +25,6 @@ use reth_payload_builder::database::CachedReads; use reth_primitives::{ constants::eip4844::{LoadKzgSettingsError, MAINNET_KZG_TRUSTED_SETUP}, revm_primitives::KzgSettings, - stage::StageId, Address, BlobTransaction, BlobTransactionSidecar, Bytes, PooledTransactionsElement, SealedBlock, SealedBlockWithSenders, Transaction, TransactionSigned, TxEip4844, B256, U256, }; @@ -35,6 +34,7 @@ use reth_provider::{ }; use reth_revm::database::StateProviderDatabase; use reth_rpc_types::engine::{BlobsBundleV1, PayloadAttributes}; +use reth_stages::StageId; use reth_transaction_pool::{ blobstore::InMemoryBlobStore, BlobStore, EthPooledTransaction, PoolConfig, TransactionOrigin, TransactionPool, TransactionValidationTaskExecutor, diff --git a/bin/reth/src/commands/debug_cmd/execution.rs b/bin/reth/src/commands/debug_cmd/execution.rs index a68716ff7821..200f212d030f 100644 --- a/bin/reth/src/commands/debug_cmd/execution.rs +++ b/bin/reth/src/commands/debug_cmd/execution.rs @@ -22,7 +22,7 @@ use reth_exex::ExExManagerHandle; use reth_network::{NetworkEvents, NetworkHandle}; use reth_network_api::NetworkInfo; use reth_network_p2p::{bodies::client::BodiesClient, headers::client::HeadersClient}; -use reth_primitives::{stage::StageId, BlockHashOrNumber, BlockNumber, B256}; +use reth_primitives::{BlockHashOrNumber, BlockNumber, B256}; use reth_provider::{ BlockExecutionWriter, ChainSpecProvider, HeaderSyncMode, ProviderFactory, StageCheckpointReader, }; @@ -30,7 +30,7 @@ use reth_prune_types::PruneModes; use reth_stages::{ sets::DefaultStages, stages::{ExecutionStage, ExecutionStageThresholds}, - Pipeline, StageSet, + Pipeline, StageId, StageSet, }; use reth_static_file::StaticFileProducer; use reth_tasks::TaskExecutor; diff --git a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs index eb6b5305dab8..aef62326a1a5 100644 --- a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs +++ b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs @@ -15,13 +15,14 @@ use reth_errors::BlockValidationError; use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; use reth_network::NetworkHandle; use reth_network_api::NetworkInfo; -use reth_primitives::{stage::StageId, BlockHashOrNumber}; +use reth_primitives::BlockHashOrNumber; use reth_provider::{ AccountExtReader, ChainSpecProvider, ExecutionOutcome, HashingWriter, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, StateWriter, StaticFileProviderFactory, StorageReader, }; use reth_revm::database::StateProviderDatabase; +use reth_stages::StageId; use reth_tasks::TaskExecutor; use reth_trie::{updates::TrieKey, StateRoot}; use std::{net::SocketAddr, path::PathBuf, sync::Arc}; diff --git a/bin/reth/src/commands/debug_cmd/merkle.rs b/bin/reth/src/commands/debug_cmd/merkle.rs index 33904d5b0912..12916cb5b51d 100644 --- a/bin/reth/src/commands/debug_cmd/merkle.rs +++ b/bin/reth/src/commands/debug_cmd/merkle.rs @@ -18,7 +18,7 @@ use reth_evm::execute::{BatchExecutor, BlockExecutorProvider}; use reth_network::NetworkHandle; use reth_network_api::NetworkInfo; use reth_network_p2p::full_block::FullBlockClient; -use reth_primitives::{stage::StageCheckpoint, BlockHashOrNumber}; +use reth_primitives::BlockHashOrNumber; use reth_provider::{ BlockNumReader, BlockWriter, ChainSpecProvider, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError, ProviderFactory, StateWriter, @@ -27,7 +27,7 @@ use reth_prune_types::PruneModes; use reth_revm::database::StateProviderDatabase; use reth_stages::{ stages::{AccountHashingStage, MerkleStage, StorageHashingStage}, - ExecInput, Stage, + ExecInput, Stage, StageCheckpoint, }; use reth_tasks::TaskExecutor; use std::{net::SocketAddr, path::PathBuf, sync::Arc}; diff --git a/bin/reth/src/commands/import.rs b/bin/reth/src/commands/import.rs index 201adf53e3d7..156e8f4d23ca 100644 --- a/bin/reth/src/commands/import.rs +++ b/bin/reth/src/commands/import.rs @@ -22,13 +22,13 @@ use reth_network_p2p::{ headers::downloader::{HeaderDownloader, SyncTarget}, }; use reth_node_events::node::NodeEvent; -use reth_primitives::{stage::StageId, B256}; +use reth_primitives::B256; use reth_provider::{ BlockNumReader, ChainSpecProvider, HeaderProvider, HeaderSyncMode, ProviderError, ProviderFactory, StageCheckpointReader, }; use reth_prune_types::PruneModes; -use reth_stages::{prelude::*, Pipeline, StageSet}; +use reth_stages::{prelude::*, Pipeline, StageId, StageSet}; use reth_static_file::StaticFileProducer; use std::{path::PathBuf, sync::Arc}; use tokio::sync::watch; diff --git a/bin/reth/src/commands/import_op.rs b/bin/reth/src/commands/import_op.rs index 206643b65050..646cd4f97232 100644 --- a/bin/reth/src/commands/import_op.rs +++ b/bin/reth/src/commands/import_op.rs @@ -16,9 +16,9 @@ use reth_downloaders::file_client::{ ChunkedFileReader, FileClient, DEFAULT_BYTE_LEN_CHUNK_CHAIN_FILE, }; use reth_optimism_primitives::bedrock_import::is_dup_tx; -use reth_primitives::stage::StageId; use reth_provider::StageCheckpointReader; use reth_prune_types::PruneModes; +use reth_stages::StageId; use reth_static_file::StaticFileProducer; use std::{path::PathBuf, sync::Arc}; use tracing::{debug, error, info}; diff --git a/bin/reth/src/commands/import_receipts_op.rs b/bin/reth/src/commands/import_receipts_op.rs index 0e2688e79926..9d84cdd01fc0 100644 --- a/bin/reth/src/commands/import_receipts_op.rs +++ b/bin/reth/src/commands/import_receipts_op.rs @@ -11,11 +11,12 @@ use reth_downloaders::{ }; use reth_node_core::version::SHORT_VERSION; use reth_optimism_primitives::bedrock_import::is_dup_tx; -use reth_primitives::{stage::StageId, Receipts, StaticFileSegment}; +use reth_primitives::{Receipts, StaticFileSegment}; use reth_provider::{ ExecutionOutcome, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, StateWriter, StaticFileProviderFactory, StaticFileWriter, StatsReader, }; +use reth_stages::StageId; use std::path::{Path, PathBuf}; use tracing::{debug, error, info, trace}; diff --git a/bin/reth/src/commands/stage/drop.rs b/bin/reth/src/commands/stage/drop.rs index 7f9453a24a37..8297eafef81a 100644 --- a/bin/reth/src/commands/stage/drop.rs +++ b/bin/reth/src/commands/stage/drop.rs @@ -10,8 +10,9 @@ use itertools::Itertools; use reth_db::{static_file::iter_static_files, tables, DatabaseEnv}; use reth_db_api::transaction::DbTxMut; use reth_db_common::init::{insert_genesis_header, insert_genesis_history, insert_genesis_state}; -use reth_primitives::{stage::StageId, static_file::find_fixed_range, StaticFileSegment}; +use reth_primitives::{static_file::find_fixed_range, StaticFileSegment}; use reth_provider::{providers::StaticFileWriter, StaticFileProviderFactory}; +use reth_stages::StageId; /// `reth drop-stage` command #[derive(Debug, Parser)] diff --git a/bin/reth/src/commands/stage/dump/execution.rs b/bin/reth/src/commands/stage/dump/execution.rs index dd9165a4b5fd..b6d6721dcf8d 100644 --- a/bin/reth/src/commands/stage/dump/execution.rs +++ b/bin/reth/src/commands/stage/dump/execution.rs @@ -5,9 +5,8 @@ use reth_db_api::{ cursor::DbCursorRO, database::Database, table::TableImporter, transaction::DbTx, }; use reth_node_core::dirs::{ChainPath, DataDirPath}; -use reth_primitives::stage::StageCheckpoint; use reth_provider::{providers::StaticFileProvider, ChainSpecProvider, ProviderFactory}; -use reth_stages::{stages::ExecutionStage, Stage, UnwindInput}; +use reth_stages::{stages::ExecutionStage, Stage, StageCheckpoint, UnwindInput}; use tracing::info; pub(crate) async fn dump_execution_stage( diff --git a/bin/reth/src/commands/stage/dump/hashing_account.rs b/bin/reth/src/commands/stage/dump/hashing_account.rs index ab5d4fffc7f7..2e50a8ad6059 100644 --- a/bin/reth/src/commands/stage/dump/hashing_account.rs +++ b/bin/reth/src/commands/stage/dump/hashing_account.rs @@ -4,9 +4,9 @@ use eyre::Result; use reth_db::{tables, DatabaseEnv}; use reth_db_api::{database::Database, table::TableImporter}; use reth_node_core::dirs::{ChainPath, DataDirPath}; -use reth_primitives::{stage::StageCheckpoint, BlockNumber}; +use reth_primitives::BlockNumber; use reth_provider::{providers::StaticFileProvider, ProviderFactory}; -use reth_stages::{stages::AccountHashingStage, Stage, UnwindInput}; +use reth_stages::{stages::AccountHashingStage, Stage, StageCheckpoint, UnwindInput}; use tracing::info; pub(crate) async fn dump_hashing_account_stage( diff --git a/bin/reth/src/commands/stage/dump/hashing_storage.rs b/bin/reth/src/commands/stage/dump/hashing_storage.rs index c2677d47dfca..1dfd722f5099 100644 --- a/bin/reth/src/commands/stage/dump/hashing_storage.rs +++ b/bin/reth/src/commands/stage/dump/hashing_storage.rs @@ -4,9 +4,8 @@ use eyre::Result; use reth_db::{tables, DatabaseEnv}; use reth_db_api::{database::Database, table::TableImporter}; use reth_node_core::dirs::{ChainPath, DataDirPath}; -use reth_primitives::stage::StageCheckpoint; use reth_provider::{providers::StaticFileProvider, ProviderFactory}; -use reth_stages::{stages::StorageHashingStage, Stage, UnwindInput}; +use reth_stages::{stages::StorageHashingStage, Stage, StageCheckpoint, UnwindInput}; use tracing::info; pub(crate) async fn dump_hashing_storage_stage( diff --git a/bin/reth/src/commands/stage/dump/merkle.rs b/bin/reth/src/commands/stage/dump/merkle.rs index 349a06b50f26..fa345bb474a4 100644 --- a/bin/reth/src/commands/stage/dump/merkle.rs +++ b/bin/reth/src/commands/stage/dump/merkle.rs @@ -6,7 +6,7 @@ use reth_db::{tables, DatabaseEnv}; use reth_db_api::{database::Database, table::TableImporter}; use reth_exex::ExExManagerHandle; use reth_node_core::dirs::{ChainPath, DataDirPath}; -use reth_primitives::{stage::StageCheckpoint, BlockNumber}; +use reth_primitives::BlockNumber; use reth_provider::{providers::StaticFileProvider, ProviderFactory}; use reth_prune_types::PruneModes; use reth_stages::{ @@ -14,7 +14,7 @@ use reth_stages::{ AccountHashingStage, ExecutionStage, ExecutionStageThresholds, MerkleStage, StorageHashingStage, MERKLE_STAGE_DEFAULT_CLEAN_THRESHOLD, }, - Stage, UnwindInput, + Stage, StageCheckpoint, UnwindInput, }; use tracing::info; diff --git a/book/installation/binaries.md b/book/installation/binaries.md index f25d756a7f65..fc741805cd93 100644 --- a/book/installation/binaries.md +++ b/book/installation/binaries.md @@ -24,7 +24,7 @@ You can verify the integrity of a Reth release by checking the signature using G The release signing key can be fetched from the Ubuntu keyserver using the following command: ```bash -gpg --keyserver keyserver.ubuntu.com --recv-keys A3AE097C89093A124049DF1F5391A3C4100530B4 +gpg --keyserver keyserver.ubuntu.com --recv-keys 50FB7CC55B2E8AFA59FE03B7AA5ED56A7FBF253E ``` A copy of the key is also included [below](#release-signing-key). Once you have @@ -32,29 +32,28 @@ imported the key you can verify a release signature (`.asc` file) using a command like this: ```bash -gpg --verify reth-v0.1.0-alpha.14-x86_64-unknown-linux-gnu.tar.gz.asc reth-v0.1.0-alpha.14-x86_64-unknown-linux-gnu.tar.gz +gpg --verify reth-v0.2.0-beta.9-x86_64-unknown-linux-gnu.tar.gz.asc reth-v0.1.0-beta.9-x86_64-unknown-linux-gnu.tar.gz ``` Replace the filenames by those corresponding to the downloaded Reth release. ### Release Signing Key -Releases are signed using the key with ID `A3AE097C89093A124049DF1F5391A3C4100530B4`. +Releases are signed using the key with ID [`50FB7CC55B2E8AFA59FE03B7AA5ED56A7FBF253E`](https://keyserver.ubuntu.com/pks/lookup?search=50FB7CC55B2E8AFA59FE03B7AA5ED56A7FBF253E&fingerprint=on&op=index). ```none -----BEGIN PGP PUBLIC KEY BLOCK----- -mDMEZGLCSBYJKwYBBAHaRw8BAQdA/q69cDkzdUx6EwEoWK7sbm59zsHda7Hgmcq+ -7kCg69q0aEdlb3JnaW9zIEtvbnN0YW50b3BvdWxvcyAoVGhpcyBpcyB0aGUga2V5 -IHVzZWQgYnkgZ2Frb25zdCB0byBzaWduIFJldGggcmVsZWFzZXMpIDxnZW9yZ2lv -c0BwYXJhZGlnbS54eXo+iJkEExYKAEEWIQSjrgl8iQk6EkBJ3x9TkaPEEAUwtAUC -ZGLCSAIbAwUJAeEzgAULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRBTkaPE -EAUwtHvmAQD+w+HZgZkkSqEiQ3XtD8ewRV3rgqFzWsFl+9GGrdmcDAD6AuqcSyAd -yxuMf0tgQDrDLiuXpuWZUsZGvkuzBiiCjwG4OARkYsJIEgorBgEEAZdVAQUBAQdA -tJr3Fle2P/hK+jscCquv5mdptWofGRJwUH3QYLmRlSwDAQgHiH4EGBYKACYWIQSj -rgl8iQk6EkBJ3x9TkaPEEAUwtAUCZGLCSAIbDAUJAeEzgAAKCRBTkaPEEAUwtO77 -AP0S+qlwRMbPpsG3No2i2c3Wa5DVqSdHhXpafbRAK9bsCAD+PaytDqwrWJecTyyi -Yg+BMVPJie5ItWPcUCuEYdj/uAM= -=Ao8Q +mDMEZl4GjhYJKwYBBAHaRw8BAQdAU5gnINBAfIgF9S9GzZ1zHDwZtv/WcJRIQI+h +wwSJCDS0U0dlb3JnaW9zIEtvbnN0YW50b3BvdWxvcyAoUmV0aCBzaWduaW5nIGtl +eSBmb3IgMjAyNCBhbmQgb24pIDxnZW9yZ2lvc0BwYXJhZGlnbS54eXo+iJMEExYK +ADsWIQRQ+3zFWy6K+ln+A7eqXtVqf78lPgUCZl4GjgIbAwULCQgHAgIiAgYVCgkI +CwIEFgIDAQIeBwIXgAAKCRCqXtVqf78lPtg6APwJXCdEG3OCrYTbOIWtLs5cdFlu +UqqUy9J/6Frn7Ss/lwD+PtqDy6AbpX83IcdlSU2cDQQkZWOHG1JPsK33l1lieQy4 +OARmXgaOEgorBgEEAZdVAQUBAQdApFaGkJqDMd9RMuAlQVbqWy23w3TxSTHS4Oy8 +dD7tvUIDAQgHiHgEGBYKACAWIQRQ+3zFWy6K+ln+A7eqXtVqf78lPgUCZl4GjgIb +DAAKCRCqXtVqf78lPlR7AP42Qr+RGsdneH73y2yd26sJpUvRoQ/IcbNMXmxAU3YZ +zwEA/K0/Im6d1n9d7fjE9fHh4gjNwZufzVTMJhX6byOo/wM= +=zczG -----END PGP PUBLIC KEY BLOCK----- ``` diff --git a/book/intro.md b/book/intro.md index 71ea24e9fc1f..1a334fbb170e 100644 --- a/book/intro.md +++ b/book/intro.md @@ -5,7 +5,10 @@ _Documentation for Reth users and developers._ Reth (short for Rust Ethereum, [pronunciation](https://twitter.com/kelvinfichter/status/1597653609411268608)) is an **Ethereum full node implementation that is focused on being user-friendly, highly modular, as well as being fast and efficient.** - +Reth is production ready, and suitable for usage in mission-critical environments such as staking or high-uptime servi +ces. We also actively recommend professional node operators to switch to Reth in production for performance and cost reasons in use cases where high performance with great margins is required such as RPC, MEV, Indexing, Simulations, and P2P activities. + + diff --git a/book/run/optimism.md b/book/run/optimism.md index 7e5078631fb9..a44d0b603fc2 100644 --- a/book/run/optimism.md +++ b/book/run/optimism.md @@ -14,12 +14,6 @@ the [L2 EL specification][l2-el-spec], and the [OP Stack specification][op-stack ## Running on Optimism -> `op-reth` is currently in the *alpha* stage of development. It is not yet ready for production use, and therefore does not have a stable release. To run it, you must build the `op-reth` binary from source. -> If you do encounter any bugs during this early stage of development, please report them in an issue on the [GitHub repository][reth]. -> -> `op-reth` also does **not** currently support OP Stack chains with legacy, pre-Bedrock state, i.e. `Optimism Mainnet` and `Optimism Goerli`. This will be possible once a database migration tool for pre-Bedrock -> state is released, with the capability to extract the legacy state from the old `l2geth` LevelDB datadir and transplant it into Reth's MDBX database. - You will need three things to run `op-reth`: 1. An archival L1 node, synced to the settlement layer of the OP Stack chain you want to sync (e.g. `reth`, `geth`, `besu`, `nethermind`, etc.) 1. A rollup node (e.g. `op-node`, `magi`, `hildr`, etc.) diff --git a/book/run/troubleshooting.md b/book/run/troubleshooting.md index fa888139f539..68a7cc29ea85 100644 --- a/book/run/troubleshooting.md +++ b/book/run/troubleshooting.md @@ -1,7 +1,5 @@ # Troubleshooting -As Reth is still in alpha, while running the node you can experience some problems related to different parts of the system: pipeline sync, blockchain tree, p2p, database, etc. - This page tries to answer how to deal with the most popular issues. ## Database diff --git a/book/theme/head.hbs b/book/theme/head.hbs index 6ff65ee74b4c..37667d80f6e7 100644 --- a/book/theme/head.hbs +++ b/book/theme/head.hbs @@ -1,5 +1,5 @@ - - \ No newline at end of file + + diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 855a458acae9..5c8ee5623d22 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -1385,7 +1385,6 @@ mod tests { keccak256, proofs::{calculate_transaction_root, state_root_unhashed}, revm_primitives::AccountInfo, - stage::StageCheckpoint, Account, Address, ChainSpecBuilder, Genesis, GenesisAccount, Header, Signature, Transaction, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, Withdrawals, B256, MAINNET, @@ -1394,6 +1393,7 @@ mod tests { test_utils::{blocks::BlockchainTestData, create_test_provider_factory_with_chain_spec}, ProviderFactory, }; + use reth_stages_api::StageCheckpoint; use reth_trie::StateRoot; use std::collections::HashMap; diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index 5a934144df5c..2badb73f4117 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -16,9 +16,8 @@ use reth_payload_builder::PayloadBuilderHandle; use reth_payload_primitives::{PayloadAttributes, PayloadBuilderAttributes}; use reth_payload_validator::ExecutionPayloadValidator; use reth_primitives::{ - constants::EPOCH_SLOTS, - stage::{PipelineTarget, StageId}, - BlockNumHash, BlockNumber, Head, Header, SealedBlock, SealedHeader, B256, + constants::EPOCH_SLOTS, BlockNumHash, BlockNumber, Head, Header, SealedBlock, SealedHeader, + B256, }; use reth_provider::{ BlockIdReader, BlockReader, BlockSource, CanonChainTracker, ChainSpecProvider, ProviderError, @@ -28,7 +27,7 @@ use reth_rpc_types::engine::{ CancunPayloadFields, ExecutionPayload, ForkchoiceState, PayloadStatus, PayloadStatusEnum, PayloadValidationError, }; -use reth_stages_api::{ControlFlow, Pipeline}; +use reth_stages_api::{ControlFlow, Pipeline, PipelineTarget, StageId}; use reth_tasks::TaskSpawner; use reth_tokio_util::EventSender; use std::{ @@ -1985,11 +1984,12 @@ mod tests { BeaconForkChoiceUpdateError, }; use assert_matches::assert_matches; - use reth_primitives::{stage::StageCheckpoint, ChainSpecBuilder, MAINNET}; + use reth_primitives::{ChainSpecBuilder, MAINNET}; use reth_provider::{BlockWriter, ProviderFactory}; use reth_rpc_types::engine::{ForkchoiceState, ForkchoiceUpdated, PayloadStatus}; use reth_rpc_types_compat::engine::payload::block_to_payload_v1; use reth_stages::{ExecOutput, PipelineError, StageError}; + use reth_stages_api::StageCheckpoint; use reth_testing_utils::generators::{self, Rng}; use std::{collections::VecDeque, sync::Arc}; use tokio::sync::oneshot::error::TryRecvError; diff --git a/crates/consensus/beacon/src/engine/sync.rs b/crates/consensus/beacon/src/engine/sync.rs index 5f14862bbc49..80e8633400ab 100644 --- a/crates/consensus/beacon/src/engine/sync.rs +++ b/crates/consensus/beacon/src/engine/sync.rs @@ -11,8 +11,8 @@ use reth_network_p2p::{ full_block::{FetchFullBlockFuture, FetchFullBlockRangeFuture, FullBlockClient}, headers::client::HeadersClient, }; -use reth_primitives::{stage::PipelineTarget, BlockNumber, ChainSpec, SealedBlock, B256}; -use reth_stages_api::{ControlFlow, Pipeline, PipelineError, PipelineWithResult}; +use reth_primitives::{BlockNumber, ChainSpec, SealedBlock, B256}; +use reth_stages_api::{ControlFlow, Pipeline, PipelineError, PipelineTarget, PipelineWithResult}; use reth_tasks::TaskSpawner; use reth_tokio_util::EventSender; use std::{ @@ -431,14 +431,15 @@ mod tests { use reth_db::{mdbx::DatabaseEnv, test_utils::TempDatabase}; use reth_network_p2p::{either::Either, test_utils::TestFullBlockClient}; use reth_primitives::{ - constants::ETHEREUM_BLOCK_GAS_LIMIT, stage::StageCheckpoint, BlockBody, ChainSpecBuilder, - Header, SealedHeader, MAINNET, + constants::ETHEREUM_BLOCK_GAS_LIMIT, BlockBody, ChainSpecBuilder, Header, SealedHeader, + MAINNET, }; use reth_provider::{ test_utils::create_test_provider_factory_with_chain_spec, ExecutionOutcome, }; use reth_prune_types::PruneModes; use reth_stages::{test_utils::TestStages, ExecOutput, StageError}; + use reth_stages_api::StageCheckpoint; use reth_static_file::StaticFileProducer; use reth_tasks::TokioTaskExecutor; use std::{collections::VecDeque, future::poll_fn, ops::Range}; diff --git a/crates/consensus/debug-client/src/client.rs b/crates/consensus/debug-client/src/client.rs index d627b630106f..a63b7a85d704 100644 --- a/crates/consensus/debug-client/src/client.rs +++ b/crates/consensus/debug-client/src/client.rs @@ -130,17 +130,20 @@ impl DebugConsensusClient

{ continue; } }; - reth_rpc_api::EngineApiClient::::fork_choice_updated_v3( + let state = reth_rpc_types::engine::ForkchoiceState { + head_block_hash: block_hash, + safe_block_hash, + finalized_block_hash, + }; + let _ = reth_rpc_api::EngineApiClient::::fork_choice_updated_v3( &execution_client, - reth_rpc_types::engine::ForkchoiceState { - head_block_hash: block_hash, - safe_block_hash, - finalized_block_hash, - }, + state, None, ) .await - .unwrap(); + .inspect_err(|err| { + warn!(target: "consensus::debug-client", %err, ?state, "failed to submit fork choice update to execution client"); + }); } } } diff --git a/crates/consensus/debug-client/src/providers/rpc.rs b/crates/consensus/debug-client/src/providers/rpc.rs index e706090ed3c2..3c0dcf9992e7 100644 --- a/crates/consensus/debug-client/src/providers/rpc.rs +++ b/crates/consensus/debug-client/src/providers/rpc.rs @@ -3,6 +3,7 @@ use alloy_eips::BlockNumberOrTag; use alloy_provider::{Provider, ProviderBuilder}; use futures::StreamExt; use reth_node_core::rpc::types::RichBlock; +use reth_rpc_types::BlockTransactionsKind; use tokio::sync::mpsc::Sender; /// Block provider that fetches new blocks from an RPC endpoint using a websocket connection. @@ -32,7 +33,7 @@ impl BlockProvider for RpcBlockProvider { while let Some(block) = stream.next().await { let full_block = ws_provider - .get_block_by_hash(block.header.hash.unwrap(), true) + .get_block_by_hash(block.header.hash.unwrap(), BlockTransactionsKind::Full) .await .expect("failed to get block") .expect("block not found"); diff --git a/crates/e2e-test-utils/Cargo.toml b/crates/e2e-test-utils/Cargo.toml index 19fafd553682..77a5676ab284 100644 --- a/crates/e2e-test-utils/Cargo.toml +++ b/crates/e2e-test-utils/Cargo.toml @@ -19,6 +19,7 @@ reth-payload-builder = { workspace = true, features = ["test-utils"] } reth-provider.workspace = true reth-node-builder.workspace = true reth-tokio-util.workspace = true +reth-stages-types.workspace = true jsonrpsee.workspace = true diff --git a/crates/e2e-test-utils/src/node.rs b/crates/e2e-test-utils/src/node.rs index 0ae20664a757..5c09f09d7be0 100644 --- a/crates/e2e-test-utils/src/node.rs +++ b/crates/e2e-test-utils/src/node.rs @@ -13,7 +13,8 @@ use reth::{ rpc::types::engine::PayloadStatusEnum, }; use reth_node_builder::NodeTypes; -use reth_primitives::{stage::StageId, BlockHash, BlockNumber, Bytes, B256}; +use reth_primitives::{BlockHash, BlockNumber, Bytes, B256}; +use reth_stages_types::StageId; use std::{marker::PhantomData, pin::Pin}; use tokio_stream::StreamExt; diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 4521f18a06ab..e9b1243f78a4 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -1315,4 +1315,94 @@ mod tests { assert_eq!(withdrawal_request.validator_public_key, validator_public_key); assert_eq!(withdrawal_request.amount, u64::from_be_bytes(withdrawal_amount.into())); } + + #[test] + fn block_gas_limit_error() { + // Create a chain specification with fork conditions set for Prague + let chain_spec = Arc::new( + ChainSpecBuilder::from(&*MAINNET) + .shanghai_activated() + .with_fork(Hardfork::Prague, ForkCondition::Timestamp(0)) + .build(), + ); + + // Create a state provider with the withdrawal requests contract pre-deployed + let mut db = create_state_provider_with_withdrawal_requests_contract(); + + // Initialize Secp256k1 for key pair generation + let secp = Secp256k1::new(); + // Generate a new key pair for the sender + let sender_key_pair = Keypair::new(&secp, &mut generators::rng()); + // Get the sender's address from the public key + let sender_address = public_key_to_address(sender_key_pair.public_key()); + + // Insert the sender account into the state with a nonce of 1 and a balance of 1 ETH in Wei + db.insert_account( + sender_address, + Account { nonce: 1, balance: U256::from(ETH_TO_WEI), bytecode_hash: None }, + None, + HashMap::new(), + ); + + // Define the validator public key and withdrawal amount as fixed bytes + let validator_public_key = fixed_bytes!("111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); + let withdrawal_amount = fixed_bytes!("2222222222222222"); + // Concatenate the validator public key and withdrawal amount into a single byte array + let input: Bytes = [&validator_public_key[..], &withdrawal_amount[..]].concat().into(); + // Ensure the input length is 56 bytes + assert_eq!(input.len(), 56); + + // Create a genesis block header with a specified gas limit and gas used + let mut header = chain_spec.genesis_header(); + header.gas_limit = 1_500_000; + header.gas_used = 134_807; + header.receipts_root = + b256!("b31a3e47b902e9211c4d349af4e4c5604ce388471e79ca008907ae4616bb0ed3"); + + // Create a transaction with a gas limit higher than the block gas limit + let tx = sign_tx_with_key_pair( + sender_key_pair, + Transaction::Legacy(TxLegacy { + chain_id: Some(chain_spec.chain.id()), + nonce: 1, + gas_price: header.base_fee_per_gas.unwrap().into(), + gas_limit: 2_500_000, // higher than block gas limit + to: TxKind::Call(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS), + value: U256::from(1), + input, + }), + ); + + // Create an executor from the state provider + let executor = executor_provider(chain_spec).executor(StateProviderDatabase::new(&db)); + + // Execute the block and capture the result + let exec_result = executor.execute( + ( + &Block { + header, + body: vec![tx], + ommers: vec![], + withdrawals: None, + requests: None, + } + .with_recovered_senders() + .unwrap(), + U256::ZERO, + ) + .into(), + ); + + // Check if the execution result is an error and assert the specific error type + match exec_result { + Ok(_) => panic!("Expected block gas limit error"), + Err(err) => assert_eq!( + *err.as_validation().unwrap(), + BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas { + transaction_gas_limit: 2_500_000, + block_available_gas: 1_500_000, + } + ), + } + } } diff --git a/crates/evm/execution-types/Cargo.toml b/crates/evm/execution-types/Cargo.toml index 8c3ce4dc071f..5f61a1eb8885 100644 --- a/crates/evm/execution-types/Cargo.toml +++ b/crates/evm/execution-types/Cargo.toml @@ -19,6 +19,8 @@ revm.workspace = true [dev-dependencies] reth-primitives = { workspace = true, features = ["test-utils"] } +alloy-primitives.workspace = true +alloy-eips.workspace = true [features] optimism = [] \ No newline at end of file diff --git a/crates/evm/execution-types/src/bundle.rs b/crates/evm/execution-types/src/bundle.rs index 5b3e8477594e..0da45fabd8ed 100644 --- a/crates/evm/execution-types/src/bundle.rs +++ b/crates/evm/execution-types/src/bundle.rs @@ -318,3 +318,277 @@ impl ExecutionOutcome { self } } + +#[cfg(test)] +mod tests { + use super::*; + use alloy_eips::{eip6110::DepositRequest, eip7002::WithdrawalRequest}; + use alloy_primitives::{FixedBytes, LogData}; + use reth_primitives::{Address, Receipts, Request, Requests, TxType, B256}; + use std::collections::HashMap; + + #[test] + fn test_initialisation() { + // Create a new BundleState object with initial data + let bundle = BundleState::new( + vec![(Address::new([2; 20]), None, Some(AccountInfo::default()), HashMap::default())], + vec![vec![(Address::new([2; 20]), None, vec![])]], + vec![], + ); + + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Create a Requests object with a vector of requests, including DepositRequest and + // WithdrawalRequest + let requests = vec![Requests(vec![ + Request::DepositRequest(DepositRequest { + pubkey: FixedBytes::<48>::from([1; 48]), + withdrawal_credentials: B256::from([0; 32]), + amount: 1111, + signature: FixedBytes::<96>::from([2; 96]), + index: 222, + }), + Request::DepositRequest(DepositRequest { + pubkey: FixedBytes::<48>::from([23; 48]), + withdrawal_credentials: B256::from([0; 32]), + amount: 34343, + signature: FixedBytes::<96>::from([43; 96]), + index: 1212, + }), + Request::WithdrawalRequest(WithdrawalRequest { + source_address: Address::from([1; 20]), + validator_public_key: FixedBytes::<48>::from([10; 48]), + amount: 72, + }), + ])]; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: bundle.clone(), + receipts: receipts.clone(), + requests: requests.clone(), + first_block, + }; + + // Assert that creating a new BundleStateWithReceipts using the constructor matches exec_res + assert_eq!( + BundleStateWithReceipts::new(bundle, receipts.clone(), first_block, requests.clone()), + exec_res + ); + + // Create a BundleStateInit object and insert initial data + let mut state_init: BundleStateInit = HashMap::new(); + state_init + .insert(Address::new([2; 20]), (None, Some(Account::default()), HashMap::default())); + + // Create a HashMap for account reverts and insert initial data + let mut revert_inner: HashMap = HashMap::new(); + revert_inner.insert(Address::new([2; 20]), (None, vec![])); + + // Create a RevertsInit object and insert the revert_inner data + let mut revert_init: RevertsInit = HashMap::new(); + revert_init.insert(123, revert_inner); + + // Assert that creating a new BundleStateWithReceipts using the new_init method matches + // exec_res + assert_eq!( + BundleStateWithReceipts::new_init( + state_init, + revert_init, + vec![], + receipts, + first_block, + requests, + ), + exec_res + ); + } + + #[test] + fn test_block_number_to_index() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), + receipts, + requests: vec![], + first_block, + }; + + // Test before the first block + assert_eq!(exec_res.block_number_to_index(12), None); + + // Test after after the first block but index larger than receipts length + assert_eq!(exec_res.block_number_to_index(133), None); + + // Test after the first block + assert_eq!(exec_res.block_number_to_index(123), Some(0)); + } + + #[test] + fn test_get_logs() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), + receipts, + requests: vec![], + first_block, + }; + + // Get logs for block number 123 + let logs: Vec<&Log> = exec_res.logs(123).unwrap().collect(); + + // Assert that the logs match the expected logs + assert_eq!(logs, vec![&Log::::default()]); + } + + #[test] + fn test_receipts_by_block() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), // Default value for bundle + receipts, // Include the created receipts + requests: vec![], // Empty vector for requests + first_block, // Set the first block number + }; + + // Get receipts for block number 123 and convert the result into a vector + let receipts_by_block: Vec<_> = exec_res.receipts_by_block(123).iter().collect(); + + // Assert that the receipts for block number 123 match the expected receipts + assert_eq!( + receipts_by_block, + vec![&Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })] + ); + } + + #[test] + fn test_receipts_len() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Create an empty Receipts object + let receipts_empty = Receipts { receipt_vec: vec![] }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), // Default value for bundle + receipts, // Include the created receipts + requests: vec![], // Empty vector for requests + first_block, // Set the first block number + }; + + // Assert that the length of receipts in exec_res is 1 + assert_eq!(exec_res.len(), 1); + + // Assert that exec_res is not empty + assert!(!exec_res.is_empty()); + + // Create a BundleStateWithReceipts object with an empty Receipts object + let exec_res_empty_receipts = BundleStateWithReceipts { + bundle: Default::default(), // Default value for bundle + receipts: receipts_empty, // Include the empty receipts + requests: vec![], // Empty vector for requests + first_block, // Set the first block number + }; + + // Assert that the length of receipts in exec_res_empty_receipts is 0 + assert_eq!(exec_res_empty_receipts.len(), 0); + + // Assert that exec_res_empty_receipts is empty + assert!(exec_res_empty_receipts.is_empty()); + } +} diff --git a/crates/node-core/Cargo.toml b/crates/node-core/Cargo.toml index 94d7aa453262..27271cdc4702 100644 --- a/crates/node-core/Cargo.toml +++ b/crates/node-core/Cargo.toml @@ -20,7 +20,6 @@ reth-storage-errors.workspace = true reth-provider.workspace = true reth-network = { workspace = true, features = ["serde"] } reth-network-p2p.workspace = true -reth-rpc-builder.workspace = true reth-rpc.workspace = true reth-rpc-server-types.workspace = true reth-rpc-types.workspace = true @@ -37,6 +36,7 @@ reth-tasks.workspace = true reth-consensus-common.workspace = true reth-beacon-consensus.workspace = true reth-prune-types.workspace = true +reth-stages-types.workspace = true # ethereum alloy-rpc-types-engine.workspace = true @@ -70,7 +70,9 @@ serde.workspace = true serde_json.workspace = true # http/rpc -hyper.workspace = true +http.workspace = true +jsonrpsee.workspace = true +tower.workspace = true # tracing tracing.workspace = true diff --git a/crates/node-core/src/args/network.rs b/crates/node-core/src/args/network.rs index a993d07e6087..93e4d8db1b12 100644 --- a/crates/node-core/src/args/network.rs +++ b/crates/node-core/src/args/network.rs @@ -158,7 +158,7 @@ impl NetworkArgs { ) .peer_config(peers_config) .boot_nodes(chain_bootnodes.clone()) - .chain_spec(chain_spec.clone()) + .chain_spec(chain_spec) .transactions_manager_config(transactions_manager_config) // Configure node identity .apply(|builder| { @@ -172,13 +172,7 @@ impl NetworkArgs { // apply discovery settings .apply(|builder| { let rlpx_socket = (self.addr, self.port).into(); - let mut builder = self.discovery.apply_to_builder(builder, rlpx_socket); - - if chain_spec.is_optimism() && !self.discovery.disable_discovery { - builder = builder.discovery_v5(reth_discv5::Config::builder(rlpx_socket)); - } - - builder + self.discovery.apply_to_builder(builder, rlpx_socket) }) // modify discv5 settings if enabled in previous step .map_discv5_config_builder(|builder| { diff --git a/crates/node-core/src/args/rpc_server.rs b/crates/node-core/src/args/rpc_server.rs index ec69e13bf65b..7ab2dd268fa1 100644 --- a/crates/node-core/src/args/rpc_server.rs +++ b/crates/node-core/src/args/rpc_server.rs @@ -1,33 +1,23 @@ //! clap [Args](clap::Args) for RPC related arguments. -use crate::{ - args::{ - types::{MaxU32, ZeroAsNoneU64}, - GasPriceOracleArgs, RpcStateCacheArgs, - }, - cli::config::RethRpcConfig, - utils::get_or_create_jwt_secret_from_path, +use crate::args::{ + types::{MaxU32, ZeroAsNoneU64}, + GasPriceOracleArgs, RpcStateCacheArgs, }; -use alloy_rpc_types_engine::{JwtError, JwtSecret}; +use alloy_rpc_types_engine::JwtSecret; use clap::{ builder::{PossibleValue, RangedU64ValueParser, TypedValueParser}, Arg, Args, Command, }; use rand::Rng; -use reth_rpc::eth::{ - cache::EthStateCacheConfig, gas_oracle::GasPriceOracleConfig, RPC_DEFAULT_GAS_CAP, -}; -use reth_rpc_builder::{ - auth::AuthServerConfig, error::RpcError, EthConfig, Identity, IpcServerBuilder, RethRpcModule, - RpcModuleConfig, RpcModuleSelection, RpcServerConfig, ServerBuilder, TransportRpcModuleConfig, -}; -use reth_rpc_server_types::constants; +use reth_rpc::eth::RPC_DEFAULT_GAS_CAP; + +use reth_rpc_server_types::{constants, RethRpcModule, RpcModuleSelection}; use std::{ ffi::OsStr, - net::{IpAddr, Ipv4Addr, SocketAddr}, + net::{IpAddr, Ipv4Addr}, path::PathBuf, }; -use tracing::debug; /// Default max number of subscriptions per connection. pub(crate) const RPC_DEFAULT_MAX_SUBS_PER_CONN: u32 = 1024; @@ -267,142 +257,6 @@ impl RpcServerArgs { } } -impl RethRpcConfig for RpcServerArgs { - fn is_ipc_enabled(&self) -> bool { - // By default IPC is enabled therefore it is enabled if the `ipcdisable` is false. - !self.ipcdisable - } - - fn ipc_path(&self) -> &str { - self.ipcpath.as_str() - } - - fn eth_config(&self) -> EthConfig { - EthConfig::default() - .max_tracing_requests(self.rpc_max_tracing_requests) - .max_blocks_per_filter(self.rpc_max_blocks_per_filter.unwrap_or_max()) - .max_logs_per_response(self.rpc_max_logs_per_response.unwrap_or_max() as usize) - .rpc_gas_cap(self.rpc_gas_cap) - .state_cache(self.state_cache_config()) - .gpo_config(self.gas_price_oracle_config()) - } - - fn state_cache_config(&self) -> EthStateCacheConfig { - EthStateCacheConfig { - max_blocks: self.rpc_state_cache.max_blocks, - max_receipts: self.rpc_state_cache.max_receipts, - max_envs: self.rpc_state_cache.max_envs, - max_concurrent_db_requests: self.rpc_state_cache.max_concurrent_db_requests, - } - } - - fn rpc_max_request_size_bytes(&self) -> u32 { - self.rpc_max_request_size.get().saturating_mul(1024 * 1024) - } - - fn rpc_max_response_size_bytes(&self) -> u32 { - self.rpc_max_response_size.get().saturating_mul(1024 * 1024) - } - - fn gas_price_oracle_config(&self) -> GasPriceOracleConfig { - self.gas_price_oracle.gas_price_oracle_config() - } - - fn transport_rpc_module_config(&self) -> TransportRpcModuleConfig { - let mut config = TransportRpcModuleConfig::default() - .with_config(RpcModuleConfig::new(self.eth_config())); - - if self.http { - config = config.with_http( - self.http_api - .clone() - .unwrap_or_else(|| RpcModuleSelection::standard_modules().into()), - ); - } - - if self.ws { - config = config.with_ws( - self.ws_api - .clone() - .unwrap_or_else(|| RpcModuleSelection::standard_modules().into()), - ); - } - - if self.is_ipc_enabled() { - config = config.with_ipc(RpcModuleSelection::default_ipc_modules()); - } - - config - } - - fn http_ws_server_builder(&self) -> ServerBuilder { - ServerBuilder::new() - .max_connections(self.rpc_max_connections.get()) - .max_request_body_size(self.rpc_max_request_size_bytes()) - .max_response_body_size(self.rpc_max_response_size_bytes()) - .max_subscriptions_per_connection(self.rpc_max_subscriptions_per_connection.get()) - } - - fn ipc_server_builder(&self) -> IpcServerBuilder { - IpcServerBuilder::default() - .max_subscriptions_per_connection(self.rpc_max_subscriptions_per_connection.get()) - .max_request_body_size(self.rpc_max_request_size_bytes()) - .max_response_body_size(self.rpc_max_response_size_bytes()) - .max_connections(self.rpc_max_connections.get()) - } - - fn rpc_server_config(&self) -> RpcServerConfig { - let mut config = RpcServerConfig::default().with_jwt_secret(self.rpc_secret_key()); - - if self.http { - let socket_address = SocketAddr::new(self.http_addr, self.http_port); - config = config - .with_http_address(socket_address) - .with_http(self.http_ws_server_builder()) - .with_http_cors(self.http_corsdomain.clone()) - .with_ws_cors(self.ws_allowed_origins.clone()); - } - - if self.ws { - let socket_address = SocketAddr::new(self.ws_addr, self.ws_port); - config = config.with_ws_address(socket_address).with_ws(self.http_ws_server_builder()); - } - - if self.is_ipc_enabled() { - config = - config.with_ipc(self.ipc_server_builder()).with_ipc_endpoint(self.ipcpath.clone()); - } - - config - } - - fn auth_server_config(&self, jwt_secret: JwtSecret) -> Result { - let address = SocketAddr::new(self.auth_addr, self.auth_port); - - let mut builder = AuthServerConfig::builder(jwt_secret).socket_addr(address); - if self.auth_ipc { - builder = builder - .ipc_endpoint(self.auth_ipc_path.clone()) - .with_ipc_config(self.ipc_server_builder()); - } - Ok(builder.build()) - } - - fn auth_jwt_secret(&self, default_jwt_path: PathBuf) -> Result { - match self.auth_jwtsecret.as_ref() { - Some(fpath) => { - debug!(target: "reth::cli", user_path=?fpath, "Reading JWT auth secret file"); - JwtSecret::from_file(fpath) - } - None => get_or_create_jwt_secret_from_path(&default_jwt_path), - } - } - - fn rpc_secret_key(&self) -> Option { - self.rpc_jwtsecret - } -} - impl Default for RpcServerArgs { fn default() -> Self { Self { @@ -473,9 +327,7 @@ impl TypedValueParser for RpcModuleSelectionValueParser { #[cfg(test)] mod tests { use super::*; - use clap::Parser; - use reth_rpc_builder::RpcModuleSelection::Selection; - use std::net::SocketAddrV4; + use clap::{Args, Parser}; /// A helper type to parse Args more easily #[derive(Parser)] @@ -484,21 +336,6 @@ mod tests { args: T, } - #[test] - fn test_rpc_gas_cap() { - let args = CommandParser::::parse_from(["reth"]).args; - let config = args.eth_config(); - assert_eq!(config.rpc_gas_cap, Into::::into(RPC_DEFAULT_GAS_CAP)); - - let args = - CommandParser::::parse_from(["reth", "--rpc.gascap", "1000"]).args; - let config = args.eth_config(); - assert_eq!(config.rpc_gas_cap, 1000); - - let args = CommandParser::::try_parse_from(["reth", "--rpc.gascap", "0"]); - assert!(args.is_err()); - } - #[test] fn test_rpc_server_args_parser() { let args = @@ -532,128 +369,10 @@ mod tests { fn test_rpc_server_args_parser_none() { let args = CommandParser::::parse_from(["reth", "--http.api", "none"]).args; let apis = args.http_api.unwrap(); - let expected = Selection(Default::default()); + let expected = RpcModuleSelection::Selection(Default::default()); assert_eq!(apis, expected); } - #[test] - fn test_transport_rpc_module_config() { - let args = CommandParser::::parse_from([ - "reth", - "--http.api", - "eth,admin,debug", - "--http", - "--ws", - ]) - .args; - let config = args.transport_rpc_module_config(); - let expected = [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Debug]; - assert_eq!(config.http().cloned().unwrap().into_selection(), expected.into()); - assert_eq!( - config.ws().cloned().unwrap().into_selection(), - RpcModuleSelection::standard_modules() - ); - } - - #[test] - fn test_transport_rpc_module_trim_config() { - let args = CommandParser::::parse_from([ - "reth", - "--http.api", - " eth, admin, debug", - "--http", - "--ws", - ]) - .args; - let config = args.transport_rpc_module_config(); - let expected = [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Debug]; - assert_eq!(config.http().cloned().unwrap().into_selection(), expected.into()); - assert_eq!( - config.ws().cloned().unwrap().into_selection(), - RpcModuleSelection::standard_modules() - ); - } - - #[test] - fn test_unique_rpc_modules() { - let args = CommandParser::::parse_from([ - "reth", - "--http.api", - " eth, admin, debug, eth,admin", - "--http", - "--ws", - ]) - .args; - let config = args.transport_rpc_module_config(); - let expected = [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Debug]; - assert_eq!(config.http().cloned().unwrap().into_selection(), expected.into()); - assert_eq!( - config.ws().cloned().unwrap().into_selection(), - RpcModuleSelection::standard_modules() - ); - } - - #[test] - fn test_rpc_server_config() { - let args = CommandParser::::parse_from([ - "reth", - "--http.api", - "eth,admin,debug", - "--http", - "--ws", - "--ws.addr", - "127.0.0.1", - "--ws.port", - "8888", - ]) - .args; - let config = args.rpc_server_config(); - assert_eq!( - config.http_address().unwrap(), - SocketAddr::V4(SocketAddrV4::new( - Ipv4Addr::LOCALHOST, - constants::DEFAULT_HTTP_RPC_PORT - )) - ); - assert_eq!( - config.ws_address().unwrap(), - SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8888)) - ); - assert_eq!(config.ipc_endpoint().unwrap(), constants::DEFAULT_IPC_ENDPOINT); - } - - #[test] - fn test_zero_filter_limits() { - let args = CommandParser::::parse_from([ - "reth", - "--rpc-max-blocks-per-filter", - "0", - "--rpc-max-logs-per-response", - "0", - ]) - .args; - - let config = args.eth_config().filter_config(); - assert_eq!(config.max_blocks_per_filter, Some(u64::MAX)); - assert_eq!(config.max_logs_per_response, Some(usize::MAX)); - } - - #[test] - fn test_custom_filter_limits() { - let args = CommandParser::::parse_from([ - "reth", - "--rpc-max-blocks-per-filter", - "100", - "--rpc-max-logs-per-response", - "200", - ]) - .args; - - let config = args.eth_config().filter_config(); - assert_eq!(config.max_blocks_per_filter, Some(100)); - assert_eq!(config.max_logs_per_response, Some(200)); - } - #[test] fn rpc_server_args_default_sanity_test() { let default_args = RpcServerArgs::default(); diff --git a/crates/node-core/src/cli/config.rs b/crates/node-core/src/cli/config.rs index ce205eb07978..e3ea46bb48ae 100644 --- a/crates/node-core/src/cli/config.rs +++ b/crates/node-core/src/cli/config.rs @@ -1,80 +1,9 @@ //! Config traits for various node components. -use alloy_rpc_types_engine::{JwtError, JwtSecret}; use reth_network::protocol::IntoRlpxSubProtocol; use reth_primitives::Bytes; -use reth_rpc::eth::{cache::EthStateCacheConfig, gas_oracle::GasPriceOracleConfig}; -use reth_rpc_builder::{ - auth::AuthServerConfig, error::RpcError, EthConfig, Identity, IpcServerBuilder, - RpcServerConfig, ServerBuilder, TransportRpcModuleConfig, -}; use reth_transaction_pool::PoolConfig; -use std::{borrow::Cow, path::PathBuf, time::Duration}; - -/// A trait that provides a configured RPC server. -/// -/// This provides all basic config values for the RPC server and is implemented by the -/// [`RpcServerArgs`](crate::args::RpcServerArgs) type. -pub trait RethRpcConfig { - /// Returns whether ipc is enabled. - fn is_ipc_enabled(&self) -> bool; - - /// Returns the path to the target ipc socket if enabled. - fn ipc_path(&self) -> &str; - - /// The configured ethereum RPC settings. - fn eth_config(&self) -> EthConfig; - - /// Returns state cache configuration. - fn state_cache_config(&self) -> EthStateCacheConfig; - - /// Returns the max request size in bytes. - fn rpc_max_request_size_bytes(&self) -> u32; - - /// Returns the max response size in bytes. - fn rpc_max_response_size_bytes(&self) -> u32; - - /// Extracts the gas price oracle config from the args. - fn gas_price_oracle_config(&self) -> GasPriceOracleConfig; - - /// Creates the [`TransportRpcModuleConfig`] from cli args. - /// - /// This sets all the api modules, and configures additional settings like gas price oracle - /// settings in the [`TransportRpcModuleConfig`]. - fn transport_rpc_module_config(&self) -> TransportRpcModuleConfig; - - /// Returns the default server builder for http/ws - fn http_ws_server_builder(&self) -> ServerBuilder; - - /// Returns the default ipc server builder - fn ipc_server_builder(&self) -> IpcServerBuilder; - - /// Creates the [`RpcServerConfig`] from cli args. - fn rpc_server_config(&self) -> RpcServerConfig; - - /// Creates the [`AuthServerConfig`] from cli args. - fn auth_server_config(&self, jwt_secret: JwtSecret) -> Result; - - /// The execution layer and consensus layer clients SHOULD accept a configuration parameter: - /// jwt-secret, which designates a file containing the hex-encoded 256 bit secret key to be used - /// for verifying/generating JWT tokens. - /// - /// If such a parameter is given, but the file cannot be read, or does not contain a hex-encoded - /// key of 256 bits, the client SHOULD treat this as an error. - /// - /// If such a parameter is not given, the client SHOULD generate such a token, valid for the - /// duration of the execution, and SHOULD store the hex-encoded secret as a jwt.hex file on - /// the filesystem. This file can then be used to provision the counterpart client. - /// - /// The `default_jwt_path` provided as an argument will be used as the default location for the - /// jwt secret in case the `auth_jwtsecret` argument is not provided. - fn auth_jwt_secret(&self, default_jwt_path: PathBuf) -> Result; - - /// Returns the configured jwt secret key for the regular rpc servers, if any. - /// - /// Note: this is not used for the auth server (engine API). - fn rpc_secret_key(&self) -> Option; -} +use std::{borrow::Cow, time::Duration}; /// A trait that provides payload builder settings. /// diff --git a/crates/node-core/src/lib.rs b/crates/node-core/src/lib.rs index 956b3ad3c3ac..a8761110aeae 100644 --- a/crates/node-core/src/lib.rs +++ b/crates/node-core/src/lib.rs @@ -28,12 +28,6 @@ pub mod primitives { /// Re-export of `reth_rpc_*` crates. pub mod rpc { - - /// Re-exported from `reth_rpc_builder`. - pub mod builder { - pub use reth_rpc_builder::*; - } - /// Re-exported from `reth_rpc_types`. pub mod types { pub use reth_rpc_types::*; diff --git a/crates/node-core/src/metrics/prometheus_exporter.rs b/crates/node-core/src/metrics/prometheus_exporter.rs index 19144ccdafc4..1ce85346fb0e 100644 --- a/crates/node-core/src/metrics/prometheus_exporter.rs +++ b/crates/node-core/src/metrics/prometheus_exporter.rs @@ -2,10 +2,7 @@ use crate::metrics::version_metrics::register_version_metrics; use eyre::WrapErr; -use hyper::{ - service::{make_service_fn, service_fn}, - Body, Request, Response, Server, -}; +use http::Response; use metrics::describe_gauge; use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle}; use metrics_util::layers::{PrefixLayer, Stack}; @@ -64,29 +61,36 @@ async fn start_endpoint( hook: Arc, task_executor: TaskExecutor, ) -> eyre::Result<()> { - let make_svc = make_service_fn(move |_| { - let handle = handle.clone(); - let hook = Arc::clone(&hook); - async move { - Ok::<_, Infallible>(service_fn(move |_: Request| { + let listener = + tokio::net::TcpListener::bind(listen_addr).await.wrap_err("Could not bind to address")?; + + task_executor.spawn_with_graceful_shutdown_signal(|signal| async move { + let mut shutdown = signal.ignore_guard(); + loop { + let io = tokio::select! { + res = listener.accept() => match res { + Ok((stream, _remote_addr)) => stream, + Err(err) => { + tracing::error!(%err, "failed to accept connection"); + continue; + } + }, + _ = &mut shutdown => break, + }; + + let handle = handle.clone(); + let hook = hook.clone(); + let service = tower::service_fn(move |_| { (hook)(); let metrics = handle.render(); - async move { Ok::<_, Infallible>(Response::new(Body::from(metrics))) } - })) - } - }); - - let server = - Server::try_bind(&listen_addr).wrap_err("Could not bind to address")?.serve(make_svc); - - task_executor.spawn_with_graceful_shutdown_signal(move |signal| async move { - if let Err(error) = server - .with_graceful_shutdown(async move { - let _ = signal.await; - }) - .await - { - tracing::error!(%error, "metrics endpoint crashed") + async move { Ok::<_, Infallible>(Response::new(metrics)) } + }); + + if let Err(error) = + jsonrpsee::server::serve_with_graceful_shutdown(io, service, &mut shutdown).await + { + tracing::error!(%error, "metrics endpoint crashed") + } } }); diff --git a/crates/node-core/src/node_config.rs b/crates/node-core/src/node_config.rs index 56ee1c84a974..b8b1ebc8be34 100644 --- a/crates/node-core/src/node_config.rs +++ b/crates/node-core/src/node_config.rs @@ -15,13 +15,14 @@ use reth_config::config::PruneConfig; use reth_db_api::{database::Database, database_metrics::DatabaseMetrics}; use reth_network_p2p::headers::client::HeadersClient; use reth_primitives::{ - constants::eip4844::MAINNET_KZG_TRUSTED_SETUP, kzg::KzgSettings, stage::StageId, - BlockHashOrNumber, BlockNumber, ChainSpec, Head, SealedHeader, B256, MAINNET, + constants::eip4844::MAINNET_KZG_TRUSTED_SETUP, kzg::KzgSettings, BlockHashOrNumber, + BlockNumber, ChainSpec, Head, SealedHeader, B256, MAINNET, }; use reth_provider::{ providers::StaticFileProvider, BlockHashReader, HeaderProvider, ProviderFactory, StageCheckpointReader, }; +use reth_stages_types::StageId; use reth_storage_errors::provider::ProviderResult; use reth_tasks::TaskExecutor; use std::{net::SocketAddr, path::PathBuf, sync::Arc}; @@ -42,7 +43,7 @@ pub static PROMETHEUS_RECORDER_HANDLE: Lazy = /// # node_config::NodeConfig, /// # args::RpcServerArgs, /// # }; -/// # use reth_rpc_builder::RpcModuleSelection; +/// # use reth_rpc_server_types::RpcModuleSelection; /// # use tokio::runtime::Handle; /// /// async fn t() { @@ -70,7 +71,7 @@ pub static PROMETHEUS_RECORDER_HANDLE: Lazy = /// # node_config::NodeConfig, /// # args::RpcServerArgs, /// # }; -/// # use reth_rpc_builder::RpcModuleSelection; +/// # use reth_rpc_server_types::RpcModuleSelection; /// # use tokio::runtime::Handle; /// /// async fn t() { diff --git a/crates/node/api/src/node.rs b/crates/node/api/src/node.rs index 810d0d8b1f6a..b8649d858c92 100644 --- a/crates/node/api/src/node.rs +++ b/crates/node/api/src/node.rs @@ -19,7 +19,7 @@ use std::marker::PhantomData; /// consensus layer. /// /// This trait is intended to be stateless and only define the types of the node. -pub trait NodeTypes: Send + Sync + 'static { +pub trait NodeTypes: Send + Sync + Unpin + 'static { /// The node's primitive types, defining basic operations and structures. type Primitives: NodePrimitives; /// The node's engine types, defining the interaction with the consensus engine. @@ -61,11 +61,17 @@ impl Default for FullNodeTypesAdapter } } +impl Clone for FullNodeTypesAdapter { + fn clone(&self) -> Self { + Self { types: self.types, db: self.db, provider: self.provider } + } +} + impl NodeTypes for FullNodeTypesAdapter where Types: NodeTypes, - DB: Send + Sync + 'static, - Provider: Send + Sync + 'static, + DB: Send + Sync + Unpin + 'static, + Provider: Send + Sync + Unpin + 'static, { type Primitives = Types::Primitives; type Engine = Types::Engine; diff --git a/crates/node/builder/Cargo.toml b/crates/node/builder/Cargo.toml index d2e7c8052796..f47ed8e7d4be 100644 --- a/crates/node/builder/Cargo.toml +++ b/crates/node/builder/Cargo.toml @@ -24,6 +24,7 @@ reth-db = { workspace = true, features = ["mdbx"] } reth-db-api.workspace = true reth-rpc-engine-api.workspace = true reth-rpc.workspace = true +reth-rpc-builder.workspace = true reth-rpc-layer.workspace = true reth-node-api.workspace = true reth-node-core.workspace = true diff --git a/crates/node/builder/src/builder/mod.rs b/crates/node/builder/src/builder/mod.rs index 52467f476b39..02d1b0e04a5a 100644 --- a/crates/node/builder/src/builder/mod.rs +++ b/crates/node/builder/src/builder/mod.rs @@ -20,7 +20,9 @@ use reth_db_api::{ database_metrics::{DatabaseMetadata, DatabaseMetrics}, }; use reth_exex::ExExContext; -use reth_network::{NetworkBuilder, NetworkConfig, NetworkHandle, NetworkManager}; +use reth_network::{ + NetworkBuilder, NetworkConfig, NetworkConfigBuilder, NetworkHandle, NetworkManager, +}; use reth_node_api::{FullNodeTypes, FullNodeTypesAdapter, NodeTypes}; use reth_node_core::{ args::{get_secret_key, DatadirArgs}, @@ -38,7 +40,6 @@ use secp256k1::SecretKey; pub use states::*; use std::{ net::{IpAddr, SocketAddr, SocketAddrV4, SocketAddrV6}, - path::PathBuf, sync::Arc, }; @@ -515,9 +516,20 @@ impl BuilderContext { /// Returns the default network config for the node. pub fn network_config(&self) -> eyre::Result> { + let network_builder = self.network_config_builder(); + Ok(self.build_network_config(network_builder?)) + } + + /// Get the [`NetworkConfigBuilder`]. + pub fn network_config_builder(&self) -> eyre::Result { let secret_key = self.network_secret(&self.config().datadir())?; let default_peers_path = self.config().datadir().known_peers(); - Ok(self.build_network_config(secret_key, default_peers_path)) + Ok(self.config().network.network_config( + self.reth_config(), + self.config().chain.clone(), + secret_key, + default_peers_path, + )) } /// Get the network secret from the given data dir @@ -529,19 +541,11 @@ impl BuilderContext { } /// Builds the [`NetworkConfig`]. - fn build_network_config( + pub fn build_network_config( &self, - secret_key: SecretKey, - default_peers_path: PathBuf, + network_builder: NetworkConfigBuilder, ) -> NetworkConfig { - self.config() - .network - .network_config( - self.reth_config(), - self.config().chain.clone(), - secret_key, - default_peers_path, - ) + network_builder .with_task_executor(Box::new(self.executor.clone())) .set_head(self.head) .listener_addr(SocketAddr::new( @@ -549,7 +553,6 @@ impl BuilderContext { // set discovery port based on instance number self.config().network.port + self.config().instance - 1, )) - .disable_discv4_discovery_if(self.config().chain.chain.is_optimism()) .discovery_addr(SocketAddr::new( self.config().network.discovery.addr, // set discovery port based on instance number diff --git a/crates/node/builder/src/components/mod.rs b/crates/node/builder/src/components/mod.rs index ef5ea4995655..8d0494470cb1 100644 --- a/crates/node/builder/src/components/mod.rs +++ b/crates/node/builder/src/components/mod.rs @@ -29,7 +29,7 @@ mod pool; /// - transaction pool /// - network /// - payload builder. -pub trait NodeComponents: Clone + Send + Sync + 'static { +pub trait NodeComponents: Clone + Unpin + Send + Sync + 'static { /// The transaction pool of the node. type Pool: TransactionPool + Unpin; diff --git a/crates/node/builder/src/launch/common.rs b/crates/node/builder/src/launch/common.rs index 4981b387a628..395e5e19eb12 100644 --- a/crates/node/builder/src/launch/common.rs +++ b/crates/node/builder/src/launch/common.rs @@ -12,17 +12,17 @@ use reth_downloaders::{bodies::noop::NoopBodiesDownloader, headers::noop::NoopHe use reth_evm::noop::NoopBlockExecutorProvider; use reth_network_p2p::headers::client::HeadersClient; use reth_node_core::{ - cli::config::RethRpcConfig, dirs::{ChainPath, DataDirPath}, node_config::NodeConfig, }; -use reth_primitives::{stage::PipelineTarget, BlockNumber, Chain, ChainSpec, Head, B256}; +use reth_primitives::{BlockNumber, Chain, ChainSpec, Head, B256}; use reth_provider::{ providers::StaticFileProvider, HeaderSyncMode, ProviderFactory, StaticFileProviderFactory, }; use reth_prune::{PruneModes, PrunerBuilder}; +use reth_rpc_builder::config::RethRpcServerConfig; use reth_rpc_layer::JwtSecret; -use reth_stages::{sets::DefaultStages, Pipeline}; +use reth_stages::{sets::DefaultStages, Pipeline, PipelineTarget}; use reth_static_file::StaticFileProducer; use reth_tasks::TaskExecutor; use reth_tracing::tracing::{debug, error, info, warn}; diff --git a/crates/node/builder/src/launch/exex.rs b/crates/node/builder/src/launch/exex.rs index 4622bc3f2592..103223357c7c 100644 --- a/crates/node/builder/src/launch/exex.rs +++ b/crates/node/builder/src/launch/exex.rs @@ -71,7 +71,7 @@ impl ExExLauncher { executor.spawn_critical("exex", async move { info!(target: "reth::cli", "ExEx started"); match exex.await { - Ok(_) => panic!("ExEx {id} finished. ExEx's should run indefinitely"), + Ok(_) => panic!("ExEx {id} finished. ExExes should run indefinitely"), Err(err) => panic!("ExEx {id} crashed: {err}"), } }); diff --git a/crates/node/builder/src/lib.rs b/crates/node/builder/src/lib.rs index ce509658a741..6e85cef5d389 100644 --- a/crates/node/builder/src/lib.rs +++ b/crates/node/builder/src/lib.rs @@ -36,7 +36,7 @@ pub mod exex; /// Re-export the core configuration traits. pub use reth_node_core::cli::config::{ - PayloadBuilderConfig, RethNetworkConfig, RethRpcConfig, RethTransactionPoolConfig, + PayloadBuilderConfig, RethNetworkConfig, RethTransactionPoolConfig, }; // re-export the core config for convenience diff --git a/crates/node/builder/src/node.rs b/crates/node/builder/src/node.rs index 135d08234cb5..681db4148cd1 100644 --- a/crates/node/builder/src/node.rs +++ b/crates/node/builder/src/node.rs @@ -4,14 +4,12 @@ use reth_node_api::FullNodeComponents; use reth_node_core::{ dirs::{ChainPath, DataDirPath}, node_config::NodeConfig, - rpc::{ - api::EngineApiClient, - builder::{auth::AuthServerHandle, RpcServerHandle}, - }, + rpc::api::EngineApiClient, }; use reth_payload_builder::PayloadBuilderHandle; use reth_primitives::ChainSpec; use reth_provider::ChainSpecProvider; +use reth_rpc_builder::{auth::AuthServerHandle, RpcServerHandle}; use reth_tasks::TaskExecutor; use std::sync::Arc; diff --git a/crates/node/builder/src/rpc.rs b/crates/node/builder/src/rpc.rs index c148827d9236..9a6ada8f916d 100644 --- a/crates/node/builder/src/rpc.rs +++ b/crates/node/builder/src/rpc.rs @@ -3,18 +3,13 @@ use futures::TryFutureExt; use reth_network::NetworkHandle; use reth_node_api::FullNodeComponents; -use reth_node_core::{ - cli::config::RethRpcConfig, - node_config::NodeConfig, - rpc::{ - api::EngineApiServer, - builder::{ - auth::{AuthRpcModule, AuthServerHandle}, - RethModuleRegistry, RpcModuleBuilder, RpcServerHandle, TransportRpcModules, - }, - }, -}; +use reth_node_core::{node_config::NodeConfig, rpc::api::EngineApiServer}; use reth_payload_builder::PayloadBuilderHandle; +use reth_rpc_builder::{ + auth::{AuthRpcModule, AuthServerHandle}, + config::RethRpcServerConfig, + RethModuleRegistry, RpcModuleBuilder, RpcServerHandle, TransportRpcModules, +}; use reth_rpc_layer::JwtSecret; use reth_tasks::TaskExecutor; use reth_tracing::tracing::{debug, info}; diff --git a/crates/node/events/src/node.rs b/crates/node/events/src/node.rs index 21c07ebe61cf..1fc62a9b61e2 100644 --- a/crates/node/events/src/node.rs +++ b/crates/node/events/src/node.rs @@ -8,14 +8,10 @@ use reth_beacon_consensus::{ use reth_db_api::{database::Database, database_metrics::DatabaseMetadata}; use reth_network::{NetworkEvent, NetworkHandle}; use reth_network_api::PeersInfo; -use reth_primitives::{ - constants, - stage::{EntitiesCheckpoint, StageCheckpoint, StageId}, - BlockNumber, B256, -}; +use reth_primitives::{constants, BlockNumber, B256}; use reth_prune::PrunerEvent; use reth_rpc_types::engine::ForkchoiceState; -use reth_stages::{ExecOutput, PipelineEvent}; +use reth_stages::{EntitiesCheckpoint, ExecOutput, PipelineEvent, StageCheckpoint, StageId}; use reth_static_file::StaticFileProducerEvent; use std::{ fmt::{Display, Formatter}, diff --git a/crates/optimism/node/Cargo.toml b/crates/optimism/node/Cargo.toml index 5cd32f8f489f..f3ca7cf96b7e 100644 --- a/crates/optimism/node/Cargo.toml +++ b/crates/optimism/node/Cargo.toml @@ -30,13 +30,11 @@ reth-revm.workspace = true reth-evm-optimism.workspace = true reth-beacon-consensus.workspace = true revm-primitives.workspace = true +reth-discv5.workspace = true # async async-trait.workspace = true -hyper.workspace = true -reqwest = { workspace = true, default-features = false, features = [ - "rustls-tls-native-roots", -] } +reqwest = { workspace = true, features = ["rustls-tls-native-roots"] } tracing.workspace = true # misc diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index 3ab287824428..c62cb598580d 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -269,7 +269,26 @@ where pool: Pool, ) -> eyre::Result { let Self { disable_txpool_gossip } = self; - let mut network_config = ctx.network_config()?; + + let args = &ctx.config().network; + + let network_builder = ctx + .network_config_builder()? + // purposefully disable discv4 + .disable_discv4_discovery() + // apply discovery settings + .apply(|builder| { + let rlpx_socket = (args.addr, args.port).into(); + let mut builder = args.discovery.apply_to_builder(builder, rlpx_socket); + + if !args.discovery.disable_discovery { + builder = builder.discovery_v5(reth_discv5::Config::builder(rlpx_socket)); + } + + builder + }); + + let mut network_config = ctx.build_network_config(network_builder); // When `sequencer_endpoint` is configured, the node will forward all transactions to a // Sequencer node for execution and inclusion on L1, and disable its own txpool diff --git a/crates/optimism/node/src/rpc.rs b/crates/optimism/node/src/rpc.rs index be5f81af7e8d..5ae1ba7b2538 100644 --- a/crates/optimism/node/src/rpc.rs +++ b/crates/optimism/node/src/rpc.rs @@ -12,9 +12,6 @@ use std::sync::{atomic::AtomicUsize, Arc}; /// Error type when interacting with the Sequencer #[derive(Debug, thiserror::Error)] pub enum SequencerRpcError { - /// Wrapper around a [`hyper::Error`]. - #[error(transparent)] - HyperError(#[from] hyper::Error), /// Wrapper around an [`reqwest::Error`]. #[error(transparent)] HttpError(#[from] reqwest::Error), diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index eb02acc025c5..d9cb4d326e44 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -39,7 +39,6 @@ mod receipt; mod request; /// Helpers for working with revm pub mod revm; -pub mod stage; pub use reth_static_file_types as static_file; mod storage; pub mod transaction; diff --git a/crates/rpc/ipc/src/server/mod.rs b/crates/rpc/ipc/src/server/mod.rs index b47c0d86a51b..d001909d37f6 100644 --- a/crates/rpc/ipc/src/server/mod.rs +++ b/crates/rpc/ipc/src/server/mod.rs @@ -91,7 +91,7 @@ where /// async fn run_server() -> Result<(), Box> { /// let server = Builder::default().build("/tmp/my-uds"); /// let mut module = RpcModule::new(()); - /// module.register_method("say_hello", |_, _| "lo")?; + /// module.register_method("say_hello", |_, _, _| "lo")?; /// let handle = server.start(module).await?; /// /// // In this example we don't care about doing shutdown so let's it run forever. @@ -390,7 +390,7 @@ where let rpc_service = self.rpc_middleware.service(RpcService::new( self.inner.methods.clone(), max_response_body_size, - self.inner.conn_id as usize, + self.inner.conn_id.into(), cfg, )); // an ipc connection needs to handle read+write concurrently @@ -896,7 +896,7 @@ mod tests { let endpoint = dummy_endpoint(); let server = Builder::default().max_response_body_size(100).build(&endpoint); let mut module = RpcModule::new(()); - module.register_method("anything", |_, _| "a".repeat(101)).unwrap(); + module.register_method("anything", |_, _, _| "a".repeat(101)).unwrap(); let handle = server.start(module).await.unwrap(); tokio::spawn(handle.stopped()); @@ -911,7 +911,7 @@ mod tests { let endpoint = dummy_endpoint(); let server = Builder::default().max_request_body_size(100).build(&endpoint); let mut module = RpcModule::new(()); - module.register_method("anything", |_, _| "succeed").unwrap(); + module.register_method("anything", |_, _, _| "succeed").unwrap(); let handle = server.start(module).await.unwrap(); tokio::spawn(handle.stopped()); @@ -939,7 +939,7 @@ mod tests { let endpoint = dummy_endpoint(); let server = Builder::default().max_connections(2).build(&endpoint); let mut module = RpcModule::new(()); - module.register_method("anything", |_, _| "succeed").unwrap(); + module.register_method("anything", |_, _, _| "succeed").unwrap(); let handle = server.start(module).await.unwrap(); tokio::spawn(handle.stopped()); @@ -973,7 +973,7 @@ mod tests { let server = Builder::default().build(&endpoint); let mut module = RpcModule::new(()); let msg = r#"{"jsonrpc":"2.0","id":83,"result":"0x7a69"}"#; - module.register_method("eth_chainId", move |_, _| msg).unwrap(); + module.register_method("eth_chainId", move |_, _, _| msg).unwrap(); let handle = server.start(module).await.unwrap(); tokio::spawn(handle.stopped()); @@ -987,7 +987,7 @@ mod tests { let endpoint = dummy_endpoint(); let server = Builder::default().build(&endpoint); let mut module = RpcModule::new(()); - module.register_method("anything", |_, _| "ok").unwrap(); + module.register_method("anything", |_, _, _| "ok").unwrap(); let handle = server.start(module).await.unwrap(); tokio::spawn(handle.stopped()); @@ -1013,7 +1013,7 @@ mod tests { let server = Builder::default().build(&endpoint); let mut module = RpcModule::new(()); let msg = r#"{"admin":"1.0","debug":"1.0","engine":"1.0","eth":"1.0","ethash":"1.0","miner":"1.0","net":"1.0","rpc":"1.0","txpool":"1.0","web3":"1.0"}"#; - module.register_method("rpc_modules", move |_, _| msg).unwrap(); + module.register_method("rpc_modules", move |_, _, _| msg).unwrap(); let handle = server.start(module).await.unwrap(); tokio::spawn(handle.stopped()); @@ -1036,7 +1036,7 @@ mod tests { "subscribe_hello", "s_hello", "unsubscribe_hello", - |_, pending, tx| async move { + |_, pending, tx, _| async move { let rx = tx.subscribe(); let stream = BroadcastStream::new(rx); pipe_from_stream_with_bounded_buffer(pending, stream).await?; @@ -1088,8 +1088,8 @@ mod tests { let mut module = RpcModule::new(()); let goodbye_msg = r#"{"jsonrpc":"2.0","id":1,"result":"goodbye"}"#; let hello_msg = r#"{"jsonrpc":"2.0","id":2,"result":"hello"}"#; - module.register_method("say_hello", move |_, _| hello_msg).unwrap(); - module.register_method("say_goodbye", move |_, _| goodbye_msg).unwrap(); + module.register_method("say_hello", move |_, _, _| hello_msg).unwrap(); + module.register_method("say_goodbye", move |_, _, _| goodbye_msg).unwrap(); let handle = server.start(module).await.unwrap(); tokio::spawn(handle.stopped()); diff --git a/crates/rpc/ipc/src/server/rpc_service.rs b/crates/rpc/ipc/src/server/rpc_service.rs index d98564bda087..2f645605da72 100644 --- a/crates/rpc/ipc/src/server/rpc_service.rs +++ b/crates/rpc/ipc/src/server/rpc_service.rs @@ -6,15 +6,15 @@ use jsonrpsee::{ IdProvider, }, types::{error::reject_too_many_subscriptions, ErrorCode, ErrorObject, Request}, - BoundedSubscriptions, ConnectionDetails, MethodCallback, MethodResponse, MethodSink, Methods, - SubscriptionState, + BoundedSubscriptions, ConnectionId, Extensions, MethodCallback, MethodResponse, MethodSink, + Methods, SubscriptionState, }; use std::sync::Arc; /// JSON-RPC service middleware. #[derive(Clone, Debug)] pub struct RpcService { - conn_id: usize, + conn_id: ConnectionId, methods: Methods, max_response_body_size: usize, cfg: RpcServiceCfg, @@ -39,7 +39,7 @@ impl RpcService { pub(crate) const fn new( methods: Methods, max_response_body_size: usize, - conn_id: usize, + conn_id: ConnectionId, cfg: RpcServiceCfg, ) -> Self { Self { methods, max_response_body_size, conn_id, cfg } @@ -58,6 +58,7 @@ impl<'a> RpcServiceT<'a> for RpcService { let params = req.params(); let name = req.method_name(); let id = req.id().clone(); + let extensions = Extensions::new(); match self.methods.method_with_name(name) { None => { @@ -65,31 +66,17 @@ impl<'a> RpcServiceT<'a> for RpcService { ResponseFuture::ready(rp) } Some((_name, method)) => match method { - MethodCallback::Async(callback) => { - let params = params.into_owned(); - let id = id.into_owned(); - - let fut = (callback)(id, params, conn_id, max_response_body_size); - ResponseFuture::future(fut) + MethodCallback::Sync(callback) => { + let rp = (callback)(id, params, max_response_body_size, extensions); + ResponseFuture::ready(rp) } - MethodCallback::AsyncWithDetails(callback) => { + MethodCallback::Async(callback) => { let params = params.into_owned(); let id = id.into_owned(); - // Note: Add the `Request::extensions` to the connection details when available - // here. - let fut = (callback)( - id, - params, - ConnectionDetails::_new(conn_id), - max_response_body_size, - ); + let fut = (callback)(id, params, conn_id, max_response_body_size, extensions); ResponseFuture::future(fut) } - MethodCallback::Sync(callback) => { - let rp = (callback)(id, params, max_response_body_size); - ResponseFuture::ready(rp) - } MethodCallback::Subscription(callback) => { let RpcServiceCfg::CallsAndSubscriptions { bounded_subscriptions, @@ -110,7 +97,7 @@ impl<'a> RpcServiceT<'a> for RpcService { subscription_permit: p, }; - let fut = callback(id.clone(), params, sink, conn_state); + let fut = callback(id.clone(), params, sink, conn_state, extensions); ResponseFuture::future(fut) } else { let max = bounded_subscriptions.max(); @@ -129,7 +116,7 @@ impl<'a> RpcServiceT<'a> for RpcService { return ResponseFuture::ready(rp); }; - let rp = callback(id, params, conn_id, max_response_body_size); + let rp = callback(id, params, conn_id, max_response_body_size, extensions); ResponseFuture::ready(rp) } }, diff --git a/crates/rpc/rpc-builder/Cargo.toml b/crates/rpc/rpc-builder/Cargo.toml index 50aef5224c3b..fa1aabae7118 100644 --- a/crates/rpc/rpc-builder/Cargo.toml +++ b/crates/rpc/rpc-builder/Cargo.toml @@ -15,6 +15,7 @@ workspace = true # reth reth-ipc.workspace = true reth-network-api.workspace = true +reth-node-core.workspace = true reth-provider.workspace = true reth-rpc.workspace = true reth-rpc-api.workspace = true @@ -29,7 +30,7 @@ reth-engine-primitives.workspace = true jsonrpsee = { workspace = true, features = ["server"] } tower-http = { workspace = true, features = ["full"] } tower = { workspace = true, features = ["full"] } -hyper.workspace = true +http.workspace = true pin-project.workspace = true # metrics @@ -37,7 +38,6 @@ reth-metrics = { workspace = true, features = ["common"] } metrics.workspace = true # misc -strum = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] } thiserror.workspace = true tracing.workspace = true @@ -60,3 +60,4 @@ reth-tokio-util.workspace = true tokio = { workspace = true, features = ["rt", "rt-multi-thread"] } serde_json.workspace = true +clap = { workspace = true, features = ["derive"] } diff --git a/crates/rpc/rpc-builder/src/auth.rs b/crates/rpc/rpc-builder/src/auth.rs index 0d865987bf4b..62a676eaa946 100644 --- a/crates/rpc/rpc-builder/src/auth.rs +++ b/crates/rpc/rpc-builder/src/auth.rs @@ -1,6 +1,5 @@ use crate::error::{RpcError, ServerKind}; -use hyper::header::AUTHORIZATION; -pub use jsonrpsee::server::ServerBuilder; +use http::header::AUTHORIZATION; use jsonrpsee::{ core::RegisterMethodError, http_client::{transport::HttpBackend, HeaderMap}, @@ -8,7 +7,6 @@ use jsonrpsee::{ Methods, }; use reth_engine_primitives::EngineTypes; -pub use reth_ipc::server::Builder as IpcServerBuilder; use reth_rpc::EthSubscriptionIdProvider; use reth_rpc_api::servers::*; use reth_rpc_layer::{ @@ -19,6 +17,9 @@ use reth_rpc_server_types::constants; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use tower::layer::util::Identity; +pub use jsonrpsee::server::ServerBuilder; +pub use reth_ipc::server::Builder as IpcServerBuilder; + /// Server configuration for the auth server. #[derive(Debug)] pub struct AuthServerConfig { diff --git a/crates/rpc/rpc-builder/src/config.rs b/crates/rpc/rpc-builder/src/config.rs new file mode 100644 index 000000000000..45cad81cd7f0 --- /dev/null +++ b/crates/rpc/rpc-builder/src/config.rs @@ -0,0 +1,364 @@ +use crate::{ + auth::AuthServerConfig, error::RpcError, EthConfig, IpcServerBuilder, RpcModuleConfig, + RpcServerConfig, TransportRpcModuleConfig, +}; +use jsonrpsee::server::ServerBuilder; +use reth_node_core::{args::RpcServerArgs, utils::get_or_create_jwt_secret_from_path}; +use reth_rpc::eth::{cache::EthStateCacheConfig, gas_oracle::GasPriceOracleConfig}; +use reth_rpc_layer::{JwtError, JwtSecret}; +use reth_rpc_server_types::RpcModuleSelection; +use std::{net::SocketAddr, path::PathBuf}; +use tower::layer::util::Identity; +use tracing::debug; + +/// A trait that provides a configured RPC server. +/// +/// This provides all basic config values for the RPC server and is implemented by the +/// [`RpcServerArgs`] type. +pub trait RethRpcServerConfig { + /// Returns whether ipc is enabled. + fn is_ipc_enabled(&self) -> bool; + + /// Returns the path to the target ipc socket if enabled. + fn ipc_path(&self) -> &str; + + /// The configured ethereum RPC settings. + fn eth_config(&self) -> EthConfig; + + /// Returns state cache configuration. + fn state_cache_config(&self) -> EthStateCacheConfig; + + /// Returns the max request size in bytes. + fn rpc_max_request_size_bytes(&self) -> u32; + + /// Returns the max response size in bytes. + fn rpc_max_response_size_bytes(&self) -> u32; + + /// Extracts the gas price oracle config from the args. + fn gas_price_oracle_config(&self) -> GasPriceOracleConfig; + + /// Creates the [`TransportRpcModuleConfig`] from cli args. + /// + /// This sets all the api modules, and configures additional settings like gas price oracle + /// settings in the [`TransportRpcModuleConfig`]. + fn transport_rpc_module_config(&self) -> TransportRpcModuleConfig; + + /// Returns the default server builder for http/ws + fn http_ws_server_builder(&self) -> ServerBuilder; + + /// Returns the default ipc server builder + fn ipc_server_builder(&self) -> IpcServerBuilder; + + /// Creates the [`RpcServerConfig`] from cli args. + fn rpc_server_config(&self) -> RpcServerConfig; + + /// Creates the [`AuthServerConfig`] from cli args. + fn auth_server_config(&self, jwt_secret: JwtSecret) -> Result; + + /// The execution layer and consensus layer clients SHOULD accept a configuration parameter: + /// jwt-secret, which designates a file containing the hex-encoded 256 bit secret key to be used + /// for verifying/generating JWT tokens. + /// + /// If such a parameter is given, but the file cannot be read, or does not contain a hex-encoded + /// key of 256 bits, the client SHOULD treat this as an error. + /// + /// If such a parameter is not given, the client SHOULD generate such a token, valid for the + /// duration of the execution, and SHOULD store the hex-encoded secret as a jwt.hex file on + /// the filesystem. This file can then be used to provision the counterpart client. + /// + /// The `default_jwt_path` provided as an argument will be used as the default location for the + /// jwt secret in case the `auth_jwtsecret` argument is not provided. + fn auth_jwt_secret(&self, default_jwt_path: PathBuf) -> Result; + + /// Returns the configured jwt secret key for the regular rpc servers, if any. + /// + /// Note: this is not used for the auth server (engine API). + fn rpc_secret_key(&self) -> Option; +} + +impl RethRpcServerConfig for RpcServerArgs { + fn is_ipc_enabled(&self) -> bool { + // By default IPC is enabled therefore it is enabled if the `ipcdisable` is false. + !self.ipcdisable + } + + fn ipc_path(&self) -> &str { + self.ipcpath.as_str() + } + + fn eth_config(&self) -> EthConfig { + EthConfig::default() + .max_tracing_requests(self.rpc_max_tracing_requests) + .max_blocks_per_filter(self.rpc_max_blocks_per_filter.unwrap_or_max()) + .max_logs_per_response(self.rpc_max_logs_per_response.unwrap_or_max() as usize) + .rpc_gas_cap(self.rpc_gas_cap) + .state_cache(self.state_cache_config()) + .gpo_config(self.gas_price_oracle_config()) + } + + fn state_cache_config(&self) -> EthStateCacheConfig { + EthStateCacheConfig { + max_blocks: self.rpc_state_cache.max_blocks, + max_receipts: self.rpc_state_cache.max_receipts, + max_envs: self.rpc_state_cache.max_envs, + max_concurrent_db_requests: self.rpc_state_cache.max_concurrent_db_requests, + } + } + + fn rpc_max_request_size_bytes(&self) -> u32 { + self.rpc_max_request_size.get().saturating_mul(1024 * 1024) + } + + fn rpc_max_response_size_bytes(&self) -> u32 { + self.rpc_max_response_size.get().saturating_mul(1024 * 1024) + } + + fn gas_price_oracle_config(&self) -> GasPriceOracleConfig { + self.gas_price_oracle.gas_price_oracle_config() + } + + fn transport_rpc_module_config(&self) -> TransportRpcModuleConfig { + let mut config = TransportRpcModuleConfig::default() + .with_config(RpcModuleConfig::new(self.eth_config())); + + if self.http { + config = config.with_http( + self.http_api + .clone() + .unwrap_or_else(|| RpcModuleSelection::standard_modules().into()), + ); + } + + if self.ws { + config = config.with_ws( + self.ws_api + .clone() + .unwrap_or_else(|| RpcModuleSelection::standard_modules().into()), + ); + } + + if self.is_ipc_enabled() { + config = config.with_ipc(RpcModuleSelection::default_ipc_modules()); + } + + config + } + + fn http_ws_server_builder(&self) -> ServerBuilder { + ServerBuilder::new() + .max_connections(self.rpc_max_connections.get()) + .max_request_body_size(self.rpc_max_request_size_bytes()) + .max_response_body_size(self.rpc_max_response_size_bytes()) + .max_subscriptions_per_connection(self.rpc_max_subscriptions_per_connection.get()) + } + + fn ipc_server_builder(&self) -> IpcServerBuilder { + IpcServerBuilder::default() + .max_subscriptions_per_connection(self.rpc_max_subscriptions_per_connection.get()) + .max_request_body_size(self.rpc_max_request_size_bytes()) + .max_response_body_size(self.rpc_max_response_size_bytes()) + .max_connections(self.rpc_max_connections.get()) + } + + fn rpc_server_config(&self) -> RpcServerConfig { + let mut config = RpcServerConfig::default().with_jwt_secret(self.rpc_secret_key()); + + if self.http { + let socket_address = SocketAddr::new(self.http_addr, self.http_port); + config = config + .with_http_address(socket_address) + .with_http(self.http_ws_server_builder()) + .with_http_cors(self.http_corsdomain.clone()) + .with_ws_cors(self.ws_allowed_origins.clone()); + } + + if self.ws { + let socket_address = SocketAddr::new(self.ws_addr, self.ws_port); + config = config.with_ws_address(socket_address).with_ws(self.http_ws_server_builder()); + } + + if self.is_ipc_enabled() { + config = + config.with_ipc(self.ipc_server_builder()).with_ipc_endpoint(self.ipcpath.clone()); + } + + config + } + + fn auth_server_config(&self, jwt_secret: JwtSecret) -> Result { + let address = SocketAddr::new(self.auth_addr, self.auth_port); + + let mut builder = AuthServerConfig::builder(jwt_secret).socket_addr(address); + if self.auth_ipc { + builder = builder + .ipc_endpoint(self.auth_ipc_path.clone()) + .with_ipc_config(self.ipc_server_builder()); + } + Ok(builder.build()) + } + + fn auth_jwt_secret(&self, default_jwt_path: PathBuf) -> Result { + match self.auth_jwtsecret.as_ref() { + Some(fpath) => { + debug!(target: "reth::cli", user_path=?fpath, "Reading JWT auth secret file"); + JwtSecret::from_file(fpath) + } + None => get_or_create_jwt_secret_from_path(&default_jwt_path), + } + } + + fn rpc_secret_key(&self) -> Option { + self.rpc_jwtsecret + } +} + +#[cfg(test)] +mod tests { + use clap::{Args, Parser}; + use reth_node_core::args::RpcServerArgs; + use reth_rpc::eth::RPC_DEFAULT_GAS_CAP; + use reth_rpc_server_types::{constants, RethRpcModule, RpcModuleSelection}; + use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; + + use crate::config::RethRpcServerConfig; + + /// A helper type to parse Args more easily + #[derive(Parser)] + struct CommandParser { + #[command(flatten)] + args: T, + } + + #[test] + fn test_rpc_gas_cap() { + let args = CommandParser::::parse_from(["reth"]).args; + let config = args.eth_config(); + assert_eq!(config.rpc_gas_cap, Into::::into(RPC_DEFAULT_GAS_CAP)); + + let args = + CommandParser::::parse_from(["reth", "--rpc.gascap", "1000"]).args; + let config = args.eth_config(); + assert_eq!(config.rpc_gas_cap, 1000); + + let args = CommandParser::::try_parse_from(["reth", "--rpc.gascap", "0"]); + assert!(args.is_err()); + } + + #[test] + fn test_transport_rpc_module_config() { + let args = CommandParser::::parse_from([ + "reth", + "--http.api", + "eth,admin,debug", + "--http", + "--ws", + ]) + .args; + let config = args.transport_rpc_module_config(); + let expected = [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Debug]; + assert_eq!(config.http().cloned().unwrap().into_selection(), expected.into()); + assert_eq!( + config.ws().cloned().unwrap().into_selection(), + RpcModuleSelection::standard_modules() + ); + } + + #[test] + fn test_transport_rpc_module_trim_config() { + let args = CommandParser::::parse_from([ + "reth", + "--http.api", + " eth, admin, debug", + "--http", + "--ws", + ]) + .args; + let config = args.transport_rpc_module_config(); + let expected = [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Debug]; + assert_eq!(config.http().cloned().unwrap().into_selection(), expected.into()); + assert_eq!( + config.ws().cloned().unwrap().into_selection(), + RpcModuleSelection::standard_modules() + ); + } + + #[test] + fn test_unique_rpc_modules() { + let args = CommandParser::::parse_from([ + "reth", + "--http.api", + " eth, admin, debug, eth,admin", + "--http", + "--ws", + ]) + .args; + let config = args.transport_rpc_module_config(); + let expected = [RethRpcModule::Eth, RethRpcModule::Admin, RethRpcModule::Debug]; + assert_eq!(config.http().cloned().unwrap().into_selection(), expected.into()); + assert_eq!( + config.ws().cloned().unwrap().into_selection(), + RpcModuleSelection::standard_modules() + ); + } + + #[test] + fn test_rpc_server_config() { + let args = CommandParser::::parse_from([ + "reth", + "--http.api", + "eth,admin,debug", + "--http", + "--ws", + "--ws.addr", + "127.0.0.1", + "--ws.port", + "8888", + ]) + .args; + let config = args.rpc_server_config(); + assert_eq!( + config.http_address().unwrap(), + SocketAddr::V4(SocketAddrV4::new( + Ipv4Addr::LOCALHOST, + constants::DEFAULT_HTTP_RPC_PORT + )) + ); + assert_eq!( + config.ws_address().unwrap(), + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8888)) + ); + assert_eq!(config.ipc_endpoint().unwrap(), constants::DEFAULT_IPC_ENDPOINT); + } + + #[test] + fn test_zero_filter_limits() { + let args = CommandParser::::parse_from([ + "reth", + "--rpc-max-blocks-per-filter", + "0", + "--rpc-max-logs-per-response", + "0", + ]) + .args; + + let config = args.eth_config().filter_config(); + assert_eq!(config.max_blocks_per_filter, Some(u64::MAX)); + assert_eq!(config.max_logs_per_response, Some(usize::MAX)); + } + + #[test] + fn test_custom_filter_limits() { + let args = CommandParser::::parse_from([ + "reth", + "--rpc-max-blocks-per-filter", + "100", + "--rpc-max-logs-per-response", + "200", + ]) + .args; + + let config = args.eth_config().filter_config(); + assert_eq!(config.max_blocks_per_filter, Some(100)); + assert_eq!(config.max_logs_per_response, Some(200)); + } +} diff --git a/crates/rpc/rpc-builder/src/cors.rs b/crates/rpc/rpc-builder/src/cors.rs index 6124e9e4e7be..0d98b4411bfb 100644 --- a/crates/rpc/rpc-builder/src/cors.rs +++ b/crates/rpc/rpc-builder/src/cors.rs @@ -1,4 +1,4 @@ -use hyper::{http::HeaderValue, Method}; +use http::{HeaderValue, Method}; use tower_http::cors::{AllowOrigin, Any, CorsLayer}; /// Error thrown when parsing cors domains went wrong diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index a03a2846564a..d05ec8239722 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -157,11 +157,10 @@ use crate::{ auth::AuthRpcModule, cors::CorsDomainError, error::WsHttpSamePortError, - metrics::RpcRequestMetrics, RpcModuleSelection::Selection, + metrics::RpcRequestMetrics, }; use error::{ConflictingModules, RpcError, ServerKind}; -use hyper::{header::AUTHORIZATION, HeaderMap}; -pub use jsonrpsee::server::ServerBuilder; +use http::{header::AUTHORIZATION, HeaderMap}; use jsonrpsee::{ core::RegisterMethodError, server::{AlreadyStoppedError, IdProvider, RpcServiceBuilder, Server, ServerHandle}, @@ -170,9 +169,6 @@ use jsonrpsee::{ use reth_engine_primitives::EngineTypes; use reth_evm::ConfigureEvm; use reth_ipc::server::IpcServer; -pub use reth_ipc::server::{ - Builder as IpcServerBuilder, RpcServiceBuilder as IpcRpcServiceBuilder, -}; use reth_network_api::{noop::NoopNetwork, NetworkInfo, Peers}; use reth_provider::{ AccountReader, BlockReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, @@ -191,32 +187,36 @@ use reth_rpc::{ }; use reth_rpc_api::servers::*; use reth_rpc_layer::{AuthLayer, Claims, JwtAuthValidator, JwtSecret}; -pub use reth_rpc_server_types::constants; use reth_tasks::{ pool::{BlockingTaskGuard, BlockingTaskPool}, TaskSpawner, TokioTaskExecutor, }; use reth_transaction_pool::{noop::NoopTransactionPool, TransactionPool}; -use serde::{Deserialize, Serialize, Serializer}; +use serde::{Deserialize, Serialize}; use std::{ - collections::{HashMap, HashSet}, + collections::HashMap, fmt, net::{Ipv4Addr, SocketAddr, SocketAddrV4}, - str::FromStr, sync::Arc, time::{Duration, SystemTime, UNIX_EPOCH}, }; -use strum::{AsRefStr, EnumIter, IntoStaticStr, ParseError, VariantArray, VariantNames}; -pub use tower::layer::util::{Identity, Stack}; use tower_http::cors::CorsLayer; use tracing::{instrument, trace}; // re-export for convenience -pub use crate::eth::{EthConfig, EthHandlers}; +pub use jsonrpsee::server::ServerBuilder; +pub use reth_ipc::server::{ + Builder as IpcServerBuilder, RpcServiceBuilder as IpcRpcServiceBuilder, +}; +pub use reth_rpc_server_types::{constants, RethRpcModule, RpcModuleSelection}; +pub use tower::layer::util::{Identity, Stack}; /// Auth server utilities. pub mod auth; +/// RPC server utilities. +pub mod config; + /// Cors utilities. mod cors; @@ -225,6 +225,7 @@ pub mod error; /// Eth utils mod eth; +pub use eth::{EthConfig, EthHandlers}; // Rpc server metrics mod metrics; @@ -623,339 +624,6 @@ impl RpcModuleConfigBuilder { } } -/// Describes the modules that should be installed. -/// -/// # Example -/// -/// Create a [`RpcModuleSelection`] from a selection. -/// -/// ``` -/// use reth_rpc_builder::{RethRpcModule, RpcModuleSelection}; -/// let config: RpcModuleSelection = vec![RethRpcModule::Eth].into(); -/// ``` -#[derive(Debug, Default, Clone, Eq, PartialEq)] -pub enum RpcModuleSelection { - /// Use _all_ available modules. - All, - /// The default modules `eth`, `net`, `web3` - #[default] - Standard, - /// Only use the configured modules. - Selection(HashSet), -} - -// === impl RpcModuleSelection === - -impl RpcModuleSelection { - /// The standard modules to instantiate by default `eth`, `net`, `web3` - pub const STANDARD_MODULES: [RethRpcModule; 3] = - [RethRpcModule::Eth, RethRpcModule::Net, RethRpcModule::Web3]; - - /// Returns a selection of [`RethRpcModule`] with all [`RethRpcModule::all_variants`]. - pub fn all_modules() -> HashSet { - RethRpcModule::modules().into_iter().collect() - } - - /// Returns the [`RpcModuleSelection::STANDARD_MODULES`] as a selection. - pub fn standard_modules() -> HashSet { - HashSet::from(Self::STANDARD_MODULES) - } - - /// All modules that are available by default on IPC. - /// - /// By default all modules are available on IPC. - pub fn default_ipc_modules() -> HashSet { - Self::all_modules() - } - - /// Creates a new _unique_ [`RpcModuleSelection::Selection`] from the given items. - /// - /// # Note - /// - /// This will dedupe the selection and remove duplicates while preserving the order. - /// - /// # Example - /// - /// Create a selection from the [`RethRpcModule`] string identifiers - /// - /// ``` - /// use reth_rpc_builder::{RethRpcModule, RpcModuleSelection}; - /// let selection = vec!["eth", "admin"]; - /// let config = RpcModuleSelection::try_from_selection(selection).unwrap(); - /// assert_eq!(config, RpcModuleSelection::from([RethRpcModule::Eth, RethRpcModule::Admin])); - /// ``` - /// - /// Create a unique selection from the [`RethRpcModule`] string identifiers - /// - /// ``` - /// use reth_rpc_builder::{RethRpcModule, RpcModuleSelection}; - /// let selection = vec!["eth", "admin", "eth", "admin"]; - /// let config = RpcModuleSelection::try_from_selection(selection).unwrap(); - /// assert_eq!(config, RpcModuleSelection::from([RethRpcModule::Eth, RethRpcModule::Admin])); - /// ``` - pub fn try_from_selection(selection: I) -> Result - where - I: IntoIterator, - T: TryInto, - { - selection.into_iter().map(TryInto::try_into).collect() - } - - /// Returns the number of modules in the selection - pub fn len(&self) -> usize { - match self { - Self::All => RethRpcModule::variant_count(), - Self::Standard => Self::STANDARD_MODULES.len(), - Self::Selection(s) => s.len(), - } - } - - /// Returns true if no selection is configured - pub fn is_empty(&self) -> bool { - match self { - Self::Selection(sel) => sel.is_empty(), - _ => false, - } - } - - /// Returns an iterator over all configured [`RethRpcModule`] - pub fn iter_selection(&self) -> Box + '_> { - match self { - Self::All => Box::new(RethRpcModule::modules().into_iter()), - Self::Standard => Box::new(Self::STANDARD_MODULES.iter().copied()), - Self::Selection(s) => Box::new(s.iter().copied()), - } - } - - /// Clones the set of configured [`RethRpcModule`]. - pub fn to_selection(&self) -> HashSet { - match self { - Self::All => Self::all_modules(), - Self::Standard => Self::standard_modules(), - Self::Selection(s) => s.clone(), - } - } - - /// Converts the selection into a [`HashSet`]. - pub fn into_selection(self) -> HashSet { - match self { - Self::All => Self::all_modules(), - Self::Standard => Self::standard_modules(), - Self::Selection(s) => s, - } - } - - /// Returns true if both selections are identical. - fn are_identical(http: Option<&Self>, ws: Option<&Self>) -> bool { - match (http, ws) { - // Shortcut for common case to avoid iterating later - (Some(Self::All), Some(other)) | (Some(other), Some(Self::All)) => { - other.len() == RethRpcModule::variant_count() - } - - // If either side is disabled, then the other must be empty - (Some(some), None) | (None, Some(some)) => some.is_empty(), - - (Some(http), Some(ws)) => http.to_selection() == ws.to_selection(), - (None, None) => true, - } - } -} - -impl From<&HashSet> for RpcModuleSelection { - fn from(s: &HashSet) -> Self { - Self::from(s.clone()) - } -} - -impl From> for RpcModuleSelection { - fn from(s: HashSet) -> Self { - Self::Selection(s) - } -} - -impl From<&[RethRpcModule]> for RpcModuleSelection { - fn from(s: &[RethRpcModule]) -> Self { - Self::Selection(s.iter().copied().collect()) - } -} - -impl From> for RpcModuleSelection { - fn from(s: Vec) -> Self { - Self::Selection(s.into_iter().collect()) - } -} - -impl From<[RethRpcModule; N]> for RpcModuleSelection { - fn from(s: [RethRpcModule; N]) -> Self { - Self::Selection(s.iter().copied().collect()) - } -} - -impl<'a> FromIterator<&'a RethRpcModule> for RpcModuleSelection { - fn from_iter(iter: I) -> Self - where - I: IntoIterator, - { - iter.into_iter().copied().collect() - } -} - -impl FromIterator for RpcModuleSelection { - fn from_iter(iter: I) -> Self - where - I: IntoIterator, - { - Self::Selection(iter.into_iter().collect()) - } -} - -impl FromStr for RpcModuleSelection { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - if s.is_empty() { - return Ok(Selection(Default::default())) - } - let mut modules = s.split(',').map(str::trim).peekable(); - let first = modules.peek().copied().ok_or(ParseError::VariantNotFound)?; - match first { - "all" | "All" => Ok(Self::All), - "none" | "None" => Ok(Selection(Default::default())), - _ => Self::try_from_selection(modules), - } - } -} - -impl fmt::Display for RpcModuleSelection { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "[{}]", - self.iter_selection().map(|s| s.to_string()).collect::>().join(", ") - ) - } -} - -/// Represents RPC modules that are supported by reth -#[derive( - Debug, - Clone, - Copy, - Eq, - PartialEq, - Hash, - AsRefStr, - IntoStaticStr, - VariantNames, - VariantArray, - EnumIter, - Deserialize, -)] -#[serde(rename_all = "snake_case")] -#[strum(serialize_all = "kebab-case")] -pub enum RethRpcModule { - /// `admin_` module - Admin, - /// `debug_` module - Debug, - /// `eth_` module - Eth, - /// `net_` module - Net, - /// `trace_` module - Trace, - /// `txpool_` module - Txpool, - /// `web3_` module - Web3, - /// `rpc_` module - Rpc, - /// `reth_` module - Reth, - /// `ots_` module - Ots, - /// For single non-standard `eth_` namespace call `eth_callBundle` - /// - /// This is separate from [`RethRpcModule::Eth`] because it is a non standardized call that - /// should be opt-in. - EthCallBundle, -} - -// === impl RethRpcModule === - -impl RethRpcModule { - /// Returns the number of variants in the enum - pub const fn variant_count() -> usize { - ::VARIANTS.len() - } - - /// Returns all variant names of the enum - pub const fn all_variant_names() -> &'static [&'static str] { - ::VARIANTS - } - - /// Returns all variants of the enum - pub const fn all_variants() -> &'static [Self] { - ::VARIANTS - } - - /// Returns all variants of the enum - pub fn modules() -> impl IntoIterator { - use strum::IntoEnumIterator; - Self::iter() - } - - /// Returns the string representation of the module. - #[inline] - pub fn as_str(&self) -> &'static str { - self.into() - } -} - -impl FromStr for RethRpcModule { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - Ok(match s { - "admin" => Self::Admin, - "debug" => Self::Debug, - "eth" => Self::Eth, - "net" => Self::Net, - "trace" => Self::Trace, - "txpool" => Self::Txpool, - "web3" => Self::Web3, - "rpc" => Self::Rpc, - "reth" => Self::Reth, - "ots" => Self::Ots, - "eth-call-bundle" | "eth_callBundle" => Self::EthCallBundle, - _ => return Err(ParseError::VariantNotFound), - }) - } -} - -impl TryFrom<&str> for RethRpcModule { - type Error = ParseError; - fn try_from(s: &str) -> Result>::Error> { - FromStr::from_str(s) - } -} - -impl fmt::Display for RethRpcModule { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad(self.as_ref()) - } -} - -impl Serialize for RethRpcModule { - fn serialize(&self, s: S) -> Result - where - S: Serializer, - { - s.serialize_str(self.as_ref()) - } -} - /// A Helper type the holds instances of the configured modules. #[derive(Debug, Clone)] pub struct RethModuleRegistry { @@ -2290,6 +1958,7 @@ impl RpcServerHandle { client.expect("failed to create http client").into() } + /// Returns a ws client connected to the server. pub async fn ws_client(&self) -> Option { let url = self.ws_url()?; @@ -2343,7 +2012,7 @@ mod tests { #[test] fn parse_rpc_module_selection_none() { let selection = "none".parse::().unwrap(); - assert_eq!(selection, Selection(Default::default())); + assert_eq!(selection, RpcModuleSelection::Selection(Default::default())); } #[test] diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index 1bfd389a9acf..17bd638d0747 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -20,7 +20,7 @@ use reth_rpc_api::{ DebugApiClient, EthFilterApiClient, NetApiClient, OtterscanClient, TraceApiClient, Web3ApiClient, }; -use reth_rpc_builder::RethRpcModule; +use reth_rpc_server_types::RethRpcModule; use reth_rpc_types::{ trace::filter::TraceFilter, FeeHistory, Filter, Index, Log, PendingTransactionFilterKind, RichBlock, SyncStatus, Transaction, TransactionReceipt, TransactionRequest, diff --git a/crates/rpc/rpc-builder/tests/it/serde.rs b/crates/rpc/rpc-builder/tests/it/serde.rs index 6a51c4f8d5b0..5df41b2d19b7 100644 --- a/crates/rpc/rpc-builder/tests/it/serde.rs +++ b/crates/rpc/rpc-builder/tests/it/serde.rs @@ -6,7 +6,7 @@ use jsonrpsee::{ types::Request, }; use reth_primitives::U256; -use reth_rpc_builder::RethRpcModule; +use reth_rpc_server_types::RethRpcModule; use serde_json::value::RawValue; struct RawRpcParams(Box); diff --git a/crates/rpc/rpc-builder/tests/it/startup.rs b/crates/rpc/rpc-builder/tests/it/startup.rs index 6237b164737e..91800166f1d9 100644 --- a/crates/rpc/rpc-builder/tests/it/startup.rs +++ b/crates/rpc/rpc-builder/tests/it/startup.rs @@ -5,8 +5,9 @@ use crate::utils::{ }; use reth_rpc_builder::{ error::{RpcError, ServerKind, WsHttpSamePortError}, - RethRpcModule, RpcServerConfig, TransportRpcModuleConfig, + RpcServerConfig, TransportRpcModuleConfig, }; +use reth_rpc_server_types::RethRpcModule; use std::io; fn is_addr_in_use_kind(err: &RpcError, kind: ServerKind) -> bool { diff --git a/crates/rpc/rpc-builder/tests/it/utils.rs b/crates/rpc/rpc-builder/tests/it/utils.rs index d1234973e56d..9d660ae3035d 100644 --- a/crates/rpc/rpc-builder/tests/it/utils.rs +++ b/crates/rpc/rpc-builder/tests/it/utils.rs @@ -7,11 +7,11 @@ use reth_primitives::MAINNET; use reth_provider::test_utils::{NoopProvider, TestCanonStateSubscriptions}; use reth_rpc_builder::{ auth::{AuthRpcModule, AuthServerConfig, AuthServerHandle}, - RpcModuleBuilder, RpcModuleSelection, RpcServerConfig, RpcServerHandle, - TransportRpcModuleConfig, + RpcModuleBuilder, RpcServerConfig, RpcServerHandle, TransportRpcModuleConfig, }; use reth_rpc_engine_api::EngineApi; use reth_rpc_layer::JwtSecret; +use reth_rpc_server_types::RpcModuleSelection; use reth_rpc_types::engine::{ClientCode, ClientVersionV1}; use reth_tasks::TokioTaskExecutor; use reth_transaction_pool::test_utils::{TestPool, TestPoolBuilder}; diff --git a/crates/rpc/rpc-engine-api/Cargo.toml b/crates/rpc/rpc-engine-api/Cargo.toml index e18ecafe4a1c..80c69d8a4dc4 100644 --- a/crates/rpc/rpc-engine-api/Cargo.toml +++ b/crates/rpc/rpc-engine-api/Cargo.toml @@ -34,11 +34,11 @@ metrics.workspace = true # misc async-trait.workspace = true -thiserror.workspace = true -jsonrpsee-types.workspace = true jsonrpsee-core.workspace = true -tracing.workspace = true +jsonrpsee-types.workspace = true serde.workspace = true +thiserror.workspace = true +tracing.workspace = true [dev-dependencies] reth-ethereum-engine-primitives.workspace = true diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index b793440d9128..a856bdc1707a 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -804,6 +804,7 @@ where self.inner.metrics.latency.exchange_transition_configuration.record(start.elapsed()); Ok(res?) } + /// Handler for `engine_getClientVersionV1` /// /// See also diff --git a/crates/rpc/rpc-layer/Cargo.toml b/crates/rpc/rpc-layer/Cargo.toml index b08bb21e76c7..b11e8ea50776 100644 --- a/crates/rpc/rpc-layer/Cargo.toml +++ b/crates/rpc/rpc-layer/Cargo.toml @@ -14,15 +14,14 @@ workspace = true alloy-rpc-types-engine.workspace = true http.workspace = true -hyper.workspace = true -tower.workspace = true -http-body.workspace = true +jsonrpsee-http-client.workspace = true pin-project.workspace = true +tower.workspace = true tracing.workspace = true [dev-dependencies] -hyper = { workspace = true, features = ["client", "tcp"] } +reqwest.workspace = true assert_matches.workspace = true tokio = { workspace = true, features = ["macros"] } tempfile.workspace = true diff --git a/crates/rpc/rpc-layer/src/auth_client_layer.rs b/crates/rpc/rpc-layer/src/auth_client_layer.rs index 94403ce4bcee..5eda04aa0f37 100644 --- a/crates/rpc/rpc-layer/src/auth_client_layer.rs +++ b/crates/rpc/rpc-layer/src/auth_client_layer.rs @@ -1,11 +1,10 @@ use crate::{Claims, JwtSecret}; -use http::HeaderValue; -use hyper::{header::AUTHORIZATION, service::Service}; +use http::{header::AUTHORIZATION, HeaderValue}; use std::{ task::{Context, Poll}, time::{Duration, SystemTime, UNIX_EPOCH}, }; -use tower::Layer; +use tower::{Layer, Service}; /// A layer that adds a new JWT token to every request using `AuthClientService`. #[derive(Debug)] @@ -41,9 +40,9 @@ impl AuthClientService { } } -impl Service> for AuthClientService +impl Service> for AuthClientService where - S: Service>, + S: Service>, { type Response = S::Response; type Error = S::Error; @@ -53,7 +52,7 @@ where self.inner.poll_ready(cx) } - fn call(&mut self, mut request: hyper::Request) -> Self::Future { + fn call(&mut self, mut request: http::Request) -> Self::Future { request.headers_mut().insert(AUTHORIZATION, secret_to_bearer_header(&self.secret)); self.inner.call(request) } diff --git a/crates/rpc/rpc-layer/src/auth_layer.rs b/crates/rpc/rpc-layer/src/auth_layer.rs index 6b10ec03203a..0a11ae8024f6 100644 --- a/crates/rpc/rpc-layer/src/auth_layer.rs +++ b/crates/rpc/rpc-layer/src/auth_layer.rs @@ -1,6 +1,5 @@ use super::AuthValidator; -use http::{Request, Response}; -use http_body::Body; +use jsonrpsee_http_client::{HttpRequest, HttpResponse}; use pin_project::pin_project; use std::{ future::Future, @@ -65,7 +64,7 @@ where /// This type is the actual implementation of the middleware. It follows the [`Service`] /// specification to correctly proxy Http requests to its inner service after headers validation. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct AuthService { /// Performs auth validation logics validator: V, @@ -73,16 +72,15 @@ pub struct AuthService { inner: S, } -impl Service> for AuthService +impl Service for AuthService where - S: Service, Response = Response>, - V: AuthValidator, - ReqBody: Body, - ResBody: Body, + S: Service, + V: AuthValidator, + Self: Clone, { - type Response = Response; + type Response = HttpResponse; type Error = S::Error; - type Future = ResponseFuture; + type Future = ResponseFuture; /// If we get polled it means that we dispatched an authorized Http request to the inner layer. /// So we just poll the inner layer ourselves. @@ -96,7 +94,7 @@ where /// Returns a future that wraps either: /// - The inner service future for authorized requests /// - An error Http response in case of authorization errors - fn call(&mut self, req: Request) -> Self::Future { + fn call(&mut self, req: HttpRequest) -> Self::Future { match self.validator.validate(req.headers()) { Ok(_) => ResponseFuture::future(self.inner.call(req)), Err(res) => ResponseFuture::invalid_auth(res), @@ -106,39 +104,35 @@ where #[pin_project] #[allow(missing_debug_implementations)] -pub struct ResponseFuture { +pub struct ResponseFuture { #[pin] - kind: Kind, + kind: Kind, } -impl ResponseFuture -where - B: Body, -{ +impl ResponseFuture { const fn future(future: F) -> Self { Self { kind: Kind::Future { future } } } - const fn invalid_auth(err_res: Response) -> Self { + const fn invalid_auth(err_res: HttpResponse) -> Self { Self { kind: Kind::Error { response: Some(err_res) } } } } #[pin_project(project = KindProj)] -enum Kind { +enum Kind { Future { #[pin] future: F, }, Error { - response: Option>, + response: Option, }, } -impl Future for ResponseFuture +impl Future for ResponseFuture where - F: Future, E>>, - B: Body, + F: Future>, { type Output = F::Output; @@ -158,12 +152,11 @@ mod tests { use super::*; use crate::JwtAuthValidator; use alloy_rpc_types_engine::{Claims, JwtError, JwtSecret}; - use http::{header, Method, Request, StatusCode}; - use hyper::{body, Body}; use jsonrpsee::{ server::{RandomStringIdProvider, ServerBuilder, ServerHandle}, RpcModule, }; + use reqwest::{header, StatusCode}; use std::{ net::SocketAddr, time::{SystemTime, UNIX_EPOCH}, @@ -234,25 +227,20 @@ mod tests { async fn send_request(jwt: Option) -> (StatusCode, String) { let server = spawn_server().await; - let client = hyper::Client::new(); + let client = + reqwest::Client::builder().timeout(std::time::Duration::from_secs(1)).build().unwrap(); - let jwt = jwt.unwrap_or_default(); - let address = format!("http://{AUTH_ADDR}:{AUTH_PORT}"); - let bearer = format!("Bearer {jwt}"); let body = r#"{"jsonrpc": "2.0", "method": "greet_melkor", "params": [], "id": 1}"#; - - let req = Request::builder() - .method(Method::POST) - .header(header::AUTHORIZATION, bearer) + let response = client + .post(&format!("http://{AUTH_ADDR}:{AUTH_PORT}")) + .bearer_auth(jwt.unwrap_or_default()) + .body(body) .header(header::CONTENT_TYPE, "application/json") - .uri(address) - .body(Body::from(body)) + .send() + .await .unwrap(); - - let res = client.request(req).await.unwrap(); - let status = res.status(); - let body_bytes = body::to_bytes(res.into_body()).await.unwrap(); - let body = String::from_utf8(body_bytes.to_vec()).expect("response was not valid utf-8"); + let status = response.status(); + let body = response.text().await.unwrap(); server.stop().unwrap(); server.stopped().await; @@ -278,7 +266,7 @@ mod tests { // Create a mock rpc module let mut module = RpcModule::new(()); - module.register_method("greet_melkor", |_, _| "You are the dark lord").unwrap(); + module.register_method("greet_melkor", |_, _, _| "You are the dark lord").unwrap(); server.start(module) } diff --git a/crates/rpc/rpc-layer/src/jwt_validator.rs b/crates/rpc/rpc-layer/src/jwt_validator.rs index f1485be9ccf0..5fe3beaba0a8 100644 --- a/crates/rpc/rpc-layer/src/jwt_validator.rs +++ b/crates/rpc/rpc-layer/src/jwt_validator.rs @@ -1,8 +1,8 @@ +use crate::{AuthValidator, JwtError, JwtSecret}; use http::{header, HeaderMap, Response, StatusCode}; +use jsonrpsee_http_client::{HttpBody, HttpResponse}; use tracing::error; -use crate::{AuthValidator, JwtError, JwtSecret}; - /// Implements JWT validation logics and integrates /// to an Http [`AuthLayer`][crate::AuthLayer] /// by implementing the [`AuthValidator`] trait. @@ -22,9 +22,7 @@ impl JwtAuthValidator { } impl AuthValidator for JwtAuthValidator { - type ResponseBody = hyper::Body; - - fn validate(&self, headers: &HeaderMap) -> Result<(), Response> { + fn validate(&self, headers: &HeaderMap) -> Result<(), HttpResponse> { match get_bearer(headers) { Some(jwt) => match self.secret.validate(&jwt) { Ok(_) => Ok(()), @@ -55,14 +53,13 @@ fn get_bearer(headers: &HeaderMap) -> Option { Some(token.into()) } -fn err_response(err: JwtError) -> Response { - let body = hyper::Body::from(err.to_string()); +fn err_response(err: JwtError) -> HttpResponse { // We build a response from an error message. // We don't cope with headers or other structured fields. // Then we are safe to "expect" on the result. Response::builder() .status(StatusCode::UNAUTHORIZED) - .body(body) + .body(HttpBody::new(err.to_string())) .expect("This should never happen") } diff --git a/crates/rpc/rpc-layer/src/lib.rs b/crates/rpc/rpc-layer/src/lib.rs index a379461dfb03..e4f7dbe06f16 100644 --- a/crates/rpc/rpc-layer/src/lib.rs +++ b/crates/rpc/rpc-layer/src/lib.rs @@ -8,7 +8,8 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -use http::{HeaderMap, Response}; +use http::HeaderMap; +use jsonrpsee_http_client::HttpResponse; mod auth_client_layer; mod auth_layer; @@ -24,10 +25,7 @@ pub use jwt_validator::JwtAuthValidator; /// General purpose trait to validate Http Authorization headers. It's supposed to be integrated as /// a validator trait into an [`AuthLayer`]. pub trait AuthValidator { - /// Body type of the error response - type ResponseBody; - /// This function is invoked by the [`AuthLayer`] to perform validation on Http headers. /// The result conveys validation errors in the form of an Http response. - fn validate(&self, headers: &HeaderMap) -> Result<(), Response>; + fn validate(&self, headers: &HeaderMap) -> Result<(), HttpResponse>; } diff --git a/crates/rpc/rpc-server-types/Cargo.toml b/crates/rpc/rpc-server-types/Cargo.toml index 93efbb133993..ddecc0a490ca 100644 --- a/crates/rpc/rpc-server-types/Cargo.toml +++ b/crates/rpc/rpc-server-types/Cargo.toml @@ -14,3 +14,7 @@ workspace = true [dependencies] # ethereum alloy-primitives.workspace = true + +# misc +strum = { workspace = true, features = ["derive"] } +serde = { workspace = true, features = ["derive"] } diff --git a/crates/rpc/rpc-server-types/src/lib.rs b/crates/rpc/rpc-server-types/src/lib.rs index 93e6a8170e47..4bdee53f83cb 100644 --- a/crates/rpc/rpc-server-types/src/lib.rs +++ b/crates/rpc/rpc-server-types/src/lib.rs @@ -10,3 +10,6 @@ /// Common RPC constants. pub mod constants; + +mod module; +pub use module::{RethRpcModule, RpcModuleSelection}; diff --git a/crates/rpc/rpc-server-types/src/module.rs b/crates/rpc/rpc-server-types/src/module.rs new file mode 100644 index 000000000000..a94c53d89a0b --- /dev/null +++ b/crates/rpc/rpc-server-types/src/module.rs @@ -0,0 +1,337 @@ +use std::{collections::HashSet, fmt, str::FromStr}; + +use serde::{Deserialize, Serialize, Serializer}; +use strum::{AsRefStr, EnumIter, IntoStaticStr, ParseError, VariantArray, VariantNames}; + +/// Describes the modules that should be installed. +/// +/// # Example +/// +/// Create a [`RpcModuleSelection`] from a selection. +/// +/// ``` +/// use reth_rpc_server_types::{RethRpcModule, RpcModuleSelection}; +/// let config: RpcModuleSelection = vec![RethRpcModule::Eth].into(); +/// ``` +#[derive(Debug, Default, Clone, Eq, PartialEq)] +pub enum RpcModuleSelection { + /// Use _all_ available modules. + All, + /// The default modules `eth`, `net`, `web3` + #[default] + Standard, + /// Only use the configured modules. + Selection(HashSet), +} + +// === impl RpcModuleSelection === + +impl RpcModuleSelection { + /// The standard modules to instantiate by default `eth`, `net`, `web3` + pub const STANDARD_MODULES: [RethRpcModule; 3] = + [RethRpcModule::Eth, RethRpcModule::Net, RethRpcModule::Web3]; + + /// Returns a selection of [`RethRpcModule`] with all [`RethRpcModule::all_variants`]. + pub fn all_modules() -> HashSet { + RethRpcModule::modules().into_iter().collect() + } + + /// Returns the [`RpcModuleSelection::STANDARD_MODULES`] as a selection. + pub fn standard_modules() -> HashSet { + HashSet::from(Self::STANDARD_MODULES) + } + + /// All modules that are available by default on IPC. + /// + /// By default all modules are available on IPC. + pub fn default_ipc_modules() -> HashSet { + Self::all_modules() + } + + /// Creates a new _unique_ [`RpcModuleSelection::Selection`] from the given items. + /// + /// # Note + /// + /// This will dedupe the selection and remove duplicates while preserving the order. + /// + /// # Example + /// + /// Create a selection from the [`RethRpcModule`] string identifiers + /// + /// ``` + /// use reth_rpc_server_types::{RethRpcModule, RpcModuleSelection}; + /// let selection = vec!["eth", "admin"]; + /// let config = RpcModuleSelection::try_from_selection(selection).unwrap(); + /// assert_eq!(config, RpcModuleSelection::from([RethRpcModule::Eth, RethRpcModule::Admin])); + /// ``` + /// + /// Create a unique selection from the [`RethRpcModule`] string identifiers + /// + /// ``` + /// use reth_rpc_server_types::{RethRpcModule, RpcModuleSelection}; + /// let selection = vec!["eth", "admin", "eth", "admin"]; + /// let config = RpcModuleSelection::try_from_selection(selection).unwrap(); + /// assert_eq!(config, RpcModuleSelection::from([RethRpcModule::Eth, RethRpcModule::Admin])); + /// ``` + pub fn try_from_selection(selection: I) -> Result + where + I: IntoIterator, + T: TryInto, + { + selection.into_iter().map(TryInto::try_into).collect() + } + + /// Returns the number of modules in the selection + pub fn len(&self) -> usize { + match self { + Self::All => RethRpcModule::variant_count(), + Self::Standard => Self::STANDARD_MODULES.len(), + Self::Selection(s) => s.len(), + } + } + + /// Returns true if no selection is configured + pub fn is_empty(&self) -> bool { + match self { + Self::Selection(sel) => sel.is_empty(), + _ => false, + } + } + + /// Returns an iterator over all configured [`RethRpcModule`] + pub fn iter_selection(&self) -> Box + '_> { + match self { + Self::All => Box::new(RethRpcModule::modules().into_iter()), + Self::Standard => Box::new(Self::STANDARD_MODULES.iter().copied()), + Self::Selection(s) => Box::new(s.iter().copied()), + } + } + + /// Clones the set of configured [`RethRpcModule`]. + pub fn to_selection(&self) -> HashSet { + match self { + Self::All => Self::all_modules(), + Self::Standard => Self::standard_modules(), + Self::Selection(s) => s.clone(), + } + } + + /// Converts the selection into a [`HashSet`]. + pub fn into_selection(self) -> HashSet { + match self { + Self::All => Self::all_modules(), + Self::Standard => Self::standard_modules(), + Self::Selection(s) => s, + } + } + + /// Returns true if both selections are identical. + pub fn are_identical(http: Option<&Self>, ws: Option<&Self>) -> bool { + match (http, ws) { + // Shortcut for common case to avoid iterating later + (Some(Self::All), Some(other)) | (Some(other), Some(Self::All)) => { + other.len() == RethRpcModule::variant_count() + } + + // If either side is disabled, then the other must be empty + (Some(some), None) | (None, Some(some)) => some.is_empty(), + + (Some(http), Some(ws)) => http.to_selection() == ws.to_selection(), + (None, None) => true, + } + } +} + +impl From<&HashSet> for RpcModuleSelection { + fn from(s: &HashSet) -> Self { + Self::from(s.clone()) + } +} + +impl From> for RpcModuleSelection { + fn from(s: HashSet) -> Self { + Self::Selection(s) + } +} + +impl From<&[RethRpcModule]> for RpcModuleSelection { + fn from(s: &[RethRpcModule]) -> Self { + Self::Selection(s.iter().copied().collect()) + } +} + +impl From> for RpcModuleSelection { + fn from(s: Vec) -> Self { + Self::Selection(s.into_iter().collect()) + } +} + +impl From<[RethRpcModule; N]> for RpcModuleSelection { + fn from(s: [RethRpcModule; N]) -> Self { + Self::Selection(s.iter().copied().collect()) + } +} + +impl<'a> FromIterator<&'a RethRpcModule> for RpcModuleSelection { + fn from_iter(iter: I) -> Self + where + I: IntoIterator, + { + iter.into_iter().copied().collect() + } +} + +impl FromIterator for RpcModuleSelection { + fn from_iter(iter: I) -> Self + where + I: IntoIterator, + { + Self::Selection(iter.into_iter().collect()) + } +} + +impl FromStr for RpcModuleSelection { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + if s.is_empty() { + return Ok(Self::Selection(Default::default())) + } + let mut modules = s.split(',').map(str::trim).peekable(); + let first = modules.peek().copied().ok_or(ParseError::VariantNotFound)?; + match first { + "all" | "All" => Ok(Self::All), + "none" | "None" => Ok(Self::Selection(Default::default())), + _ => Self::try_from_selection(modules), + } + } +} + +impl fmt::Display for RpcModuleSelection { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "[{}]", + self.iter_selection().map(|s| s.to_string()).collect::>().join(", ") + ) + } +} + +/// Represents RPC modules that are supported by reth +#[derive( + Debug, + Clone, + Copy, + Eq, + PartialEq, + Hash, + AsRefStr, + IntoStaticStr, + VariantNames, + VariantArray, + EnumIter, + Deserialize, +)] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "kebab-case")] +pub enum RethRpcModule { + /// `admin_` module + Admin, + /// `debug_` module + Debug, + /// `eth_` module + Eth, + /// `net_` module + Net, + /// `trace_` module + Trace, + /// `txpool_` module + Txpool, + /// `web3_` module + Web3, + /// `rpc_` module + Rpc, + /// `reth_` module + Reth, + /// `ots_` module + Ots, + /// For single non-standard `eth_` namespace call `eth_callBundle` + /// + /// This is separate from [`RethRpcModule::Eth`] because it is a non standardized call that + /// should be opt-in. + EthCallBundle, +} + +// === impl RethRpcModule === + +impl RethRpcModule { + /// Returns the number of variants in the enum + pub const fn variant_count() -> usize { + ::VARIANTS.len() + } + + /// Returns all variant names of the enum + pub const fn all_variant_names() -> &'static [&'static str] { + ::VARIANTS + } + + /// Returns all variants of the enum + pub const fn all_variants() -> &'static [Self] { + ::VARIANTS + } + + /// Returns all variants of the enum + pub fn modules() -> impl IntoIterator { + use strum::IntoEnumIterator; + Self::iter() + } + + /// Returns the string representation of the module. + #[inline] + pub fn as_str(&self) -> &'static str { + self.into() + } +} + +impl FromStr for RethRpcModule { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + Ok(match s { + "admin" => Self::Admin, + "debug" => Self::Debug, + "eth" => Self::Eth, + "net" => Self::Net, + "trace" => Self::Trace, + "txpool" => Self::Txpool, + "web3" => Self::Web3, + "rpc" => Self::Rpc, + "reth" => Self::Reth, + "ots" => Self::Ots, + "eth-call-bundle" | "eth_callBundle" => Self::EthCallBundle, + _ => return Err(ParseError::VariantNotFound), + }) + } +} + +impl TryFrom<&str> for RethRpcModule { + type Error = ParseError; + fn try_from(s: &str) -> Result>::Error> { + FromStr::from_str(s) + } +} + +impl fmt::Display for RethRpcModule { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(self.as_ref()) + } +} + +impl Serialize for RethRpcModule { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + s.serialize_str(self.as_ref()) + } +} diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index 81e2ae34610c..52efa4c34456 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -1734,7 +1734,7 @@ pub(crate) fn build_transaction_receipt_with_block_receipts( } let rpc_receipt = reth_rpc_types::Receipt { - status: receipt.success, + status: receipt.success.into(), cumulative_gas_used: receipt.cumulative_gas_used as u128, logs, }; diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index f1343c46ec2e..e658402f3a94 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -158,7 +158,12 @@ where .drain(page_start..page_end) .map(|receipt| { let receipt = receipt.inner.map_inner(|receipt| OtsReceipt { - status: receipt.inner.receipt.status, + status: receipt + .inner + .receipt + .status + .as_eip658() + .expect("ETH API returned pre-EIP-658 status"), cumulative_gas_used: receipt.inner.receipt.cumulative_gas_used as u64, logs: None, logs_bloom: None, diff --git a/crates/stages/api/Cargo.toml b/crates/stages/api/Cargo.toml index e7b6ca70b14c..cb58818b503c 100644 --- a/crates/stages/api/Cargo.toml +++ b/crates/stages/api/Cargo.toml @@ -21,6 +21,7 @@ reth-tokio-util.workspace = true reth-consensus.workspace = true reth-prune.workspace = true reth-errors.workspace = true +reth-stages-types.workspace = true # metrics reth-metrics.workspace = true diff --git a/crates/stages/api/src/lib.rs b/crates/stages/api/src/lib.rs index 084680ce4461..ec01876c9951 100644 --- a/crates/stages/api/src/lib.rs +++ b/crates/stages/api/src/lib.rs @@ -26,3 +26,6 @@ pub use pipeline::*; pub use stage::*; use aquamarine as _; + +// re-export the stages types for convenience +pub use reth_stages_types::*; diff --git a/crates/stages/api/src/metrics/listener.rs b/crates/stages/api/src/metrics/listener.rs index d92e157bacf4..408ecab4a95c 100644 --- a/crates/stages/api/src/metrics/listener.rs +++ b/crates/stages/api/src/metrics/listener.rs @@ -1,9 +1,5 @@ -use crate::metrics::SyncMetrics; -use reth_primitives::{ - constants::MGAS_TO_GAS, - stage::{StageCheckpoint, StageId}, - BlockNumber, -}; +use crate::{metrics::SyncMetrics, StageCheckpoint, StageId}; +use reth_primitives::{constants::MGAS_TO_GAS, BlockNumber}; use std::{ future::Future, pin::Pin, diff --git a/crates/stages/api/src/metrics/sync_metrics.rs b/crates/stages/api/src/metrics/sync_metrics.rs index 3548f6d91209..3ee2964ea715 100644 --- a/crates/stages/api/src/metrics/sync_metrics.rs +++ b/crates/stages/api/src/metrics/sync_metrics.rs @@ -1,8 +1,8 @@ +use crate::StageId; use reth_metrics::{ metrics::{Counter, Gauge}, Metrics, }; -use reth_primitives::stage::StageId; use std::collections::HashMap; #[derive(Debug, Default)] diff --git a/crates/stages/api/src/pipeline/builder.rs b/crates/stages/api/src/pipeline/builder.rs index 317f7a51203f..ada5ffd3734a 100644 --- a/crates/stages/api/src/pipeline/builder.rs +++ b/crates/stages/api/src/pipeline/builder.rs @@ -1,6 +1,6 @@ -use crate::{pipeline::BoxedStage, MetricEventsSender, Pipeline, Stage, StageSet}; +use crate::{pipeline::BoxedStage, MetricEventsSender, Pipeline, Stage, StageId, StageSet}; use reth_db_api::database::Database; -use reth_primitives::{stage::StageId, BlockNumber, B256}; +use reth_primitives::{BlockNumber, B256}; use reth_provider::ProviderFactory; use reth_static_file::StaticFileProducer; use tokio::sync::watch; diff --git a/crates/stages/api/src/pipeline/event.rs b/crates/stages/api/src/pipeline/event.rs index 1dd761d3f451..9bbaaa79b468 100644 --- a/crates/stages/api/src/pipeline/event.rs +++ b/crates/stages/api/src/pipeline/event.rs @@ -1,8 +1,8 @@ -use crate::stage::{ExecOutput, UnwindInput, UnwindOutput}; -use reth_primitives::{ - stage::{StageCheckpoint, StageId}, - BlockNumber, +use crate::{ + stage::{ExecOutput, UnwindInput, UnwindOutput}, + StageCheckpoint, StageId, }; +use reth_primitives::BlockNumber; use std::fmt::{Display, Formatter}; /// An event emitted by a [Pipeline][crate::Pipeline]. diff --git a/crates/stages/api/src/pipeline/mod.rs b/crates/stages/api/src/pipeline/mod.rs index 5bf72d11d3c3..2b7fcf6cbec4 100644 --- a/crates/stages/api/src/pipeline/mod.rs +++ b/crates/stages/api/src/pipeline/mod.rs @@ -1,14 +1,13 @@ mod ctrl; mod event; pub use crate::pipeline::ctrl::ControlFlow; +use crate::{PipelineTarget, StageCheckpoint, StageId}; pub use event::*; use futures_util::Future; use reth_db_api::database::Database; use reth_primitives::{ - constants::BEACON_CONSENSUS_REORG_UNWIND_DEPTH, - stage::{PipelineTarget, StageCheckpoint, StageId}, - static_file::HighestStaticFiles, - BlockNumber, B256, + constants::BEACON_CONSENSUS_REORG_UNWIND_DEPTH, static_file::HighestStaticFiles, BlockNumber, + B256, }; use reth_provider::{ providers::StaticFileWriter, FinalizedBlockReader, FinalizedBlockWriter, ProviderFactory, @@ -369,6 +368,8 @@ where provider_rw.commit()?; self.provider_factory.static_file_provider().commit()?; + stage.post_unwind_commit()?; + provider_rw = self.provider_factory.provider_rw()?; } Err(err) => { @@ -479,6 +480,8 @@ where self.provider_factory.static_file_provider().commit()?; provider_rw.commit()?; + stage.post_execute_commit()?; + if done { let block_number = checkpoint.block_number; return Ok(if made_progress { diff --git a/crates/stages/api/src/pipeline/set.rs b/crates/stages/api/src/pipeline/set.rs index af644652f700..527d9a99a468 100644 --- a/crates/stages/api/src/pipeline/set.rs +++ b/crates/stages/api/src/pipeline/set.rs @@ -1,6 +1,5 @@ -use crate::Stage; +use crate::{Stage, StageId}; use reth_db_api::database::Database; -use reth_primitives::stage::StageId; use std::{ collections::HashMap, fmt::{Debug, Formatter}, diff --git a/crates/stages/api/src/stage.rs b/crates/stages/api/src/stage.rs index 6603ea5043c6..381acf5f2d99 100644 --- a/crates/stages/api/src/stage.rs +++ b/crates/stages/api/src/stage.rs @@ -1,9 +1,6 @@ -use crate::error::StageError; +use crate::{error::StageError, StageCheckpoint, StageId}; use reth_db_api::database::Database; -use reth_primitives::{ - stage::{StageCheckpoint, StageId}, - BlockNumber, TxNumber, -}; +use reth_primitives::{BlockNumber, TxNumber}; use reth_provider::{BlockReader, DatabaseProviderRW, ProviderError, TransactionsProvider}; use std::{ cmp::{max, min}, @@ -238,12 +235,30 @@ pub trait Stage: Send + Sync { input: ExecInput, ) -> Result; + /// Post execution commit hook. + /// + /// This is called after the stage has been executed and the data has been committed by the + /// provider. The stage may want to pass some data from [`Self::execute`] via the internal + /// field. + fn post_execute_commit(&mut self) -> Result<(), StageError> { + Ok(()) + } + /// Unwind the stage. fn unwind( &mut self, provider: &DatabaseProviderRW, input: UnwindInput, ) -> Result; + + /// Post unwind commit hook. + /// + /// This is called after the stage has been unwound and the data has been committed by the + /// provider. The stage may want to pass some data from [`Self::unwind`] via the internal + /// field. + fn post_unwind_commit(&mut self) -> Result<(), StageError> { + Ok(()) + } } /// [Stage] trait extension. diff --git a/crates/stages/api/src/test_utils.rs b/crates/stages/api/src/test_utils.rs index e2844799e269..1495c54b0601 100644 --- a/crates/stages/api/src/test_utils.rs +++ b/crates/stages/api/src/test_utils.rs @@ -1,8 +1,7 @@ #![allow(missing_docs)] -use crate::{ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput}; +use crate::{ExecInput, ExecOutput, Stage, StageError, StageId, UnwindInput, UnwindOutput}; use reth_db_api::database::Database; -use reth_primitives::stage::StageId; use reth_provider::DatabaseProviderRW; use std::collections::VecDeque; diff --git a/crates/stages/stages/benches/criterion.rs b/crates/stages/stages/benches/criterion.rs index 976723dcd2d7..0e13437553b5 100644 --- a/crates/stages/stages/benches/criterion.rs +++ b/crates/stages/stages/benches/criterion.rs @@ -5,10 +5,11 @@ use pprof::criterion::{Output, PProfProfiler}; use reth_config::config::{EtlConfig, TransactionLookupConfig}; use reth_db::{test_utils::TempDatabase, DatabaseEnv}; -use reth_primitives::{stage::StageCheckpoint, BlockNumber}; +use reth_primitives::BlockNumber; use reth_stages::{ stages::{MerkleStage, SenderRecoveryStage, TransactionLookupStage}, test_utils::TestStageDB, + StageCheckpoint, }; use reth_stages_api::{ExecInput, Stage, StageExt, UnwindInput}; use std::{ops::RangeInclusive, sync::Arc}; diff --git a/crates/stages/stages/benches/setup/account_hashing.rs b/crates/stages/stages/benches/setup/account_hashing.rs index d3d62dda430f..86831418e53f 100644 --- a/crates/stages/stages/benches/setup/account_hashing.rs +++ b/crates/stages/stages/benches/setup/account_hashing.rs @@ -5,10 +5,11 @@ use reth_db::tables; use reth_db_api::{ cursor::DbCursorRO, database::Database, transaction::DbTx, DatabaseError as DbError, }; -use reth_primitives::{stage::StageCheckpoint, BlockNumber}; +use reth_primitives::BlockNumber; use reth_stages::{ stages::{AccountHashingStage, SeedOpts}, test_utils::TestStageDB, + StageCheckpoint, }; use std::{fs, ops::RangeInclusive, path::Path}; diff --git a/crates/stages/stages/src/stages/bodies.rs b/crates/stages/stages/src/stages/bodies.rs index 7c9ced8e40d9..454ee50bbe20 100644 --- a/crates/stages/stages/src/stages/bodies.rs +++ b/crates/stages/stages/src/stages/bodies.rs @@ -14,17 +14,15 @@ use reth_db_api::{ transaction::DbTxMut, }; use reth_network_p2p::bodies::{downloader::BodyDownloader, response::BlockResponse}; -use reth_primitives::{ - stage::{EntitiesCheckpoint, StageCheckpoint, StageId}, - StaticFileSegment, TxNumber, -}; +use reth_primitives::{StaticFileSegment, TxNumber}; use reth_provider::{ providers::{StaticFileProvider, StaticFileWriter}, BlockReader, DatabaseProviderRW, HeaderProvider, ProviderError, StatsReader, }; -use reth_stages_api::{ExecInput, ExecOutput, StageError, UnwindInput, UnwindOutput}; - -use reth_stages_api::Stage; +use reth_stages_api::{ + EntitiesCheckpoint, ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, StageId, + UnwindInput, UnwindOutput, +}; use reth_storage_errors::provider::ProviderResult; // TODO(onbjerg): Metrics and events (gradual status for e.g. CLI) @@ -397,8 +395,8 @@ fn stage_checkpoint( mod tests { use assert_matches::assert_matches; - use reth_primitives::stage::StageUnitCheckpoint; use reth_provider::StaticFileProviderFactory; + use reth_stages_api::StageUnitCheckpoint; use test_utils::*; use crate::test_utils::{ diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 8b62ffeb5dbc..9fe06d547229 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -5,12 +5,7 @@ use reth_db::{static_file::HeaderMask, tables}; use reth_db_api::{cursor::DbCursorRO, database::Database, transaction::DbTx}; use reth_evm::execute::{BatchExecutor, BlockExecutorProvider}; use reth_exex::{ExExManagerHandle, ExExNotification}; -use reth_primitives::{ - stage::{ - CheckpointBlockRange, EntitiesCheckpoint, ExecutionCheckpoint, StageCheckpoint, StageId, - }, - BlockNumber, Header, StaticFileSegment, -}; +use reth_primitives::{BlockNumber, Header, StaticFileSegment}; use reth_provider::{ providers::{StaticFileProvider, StaticFileProviderRWRefMut, StaticFileWriter}, ExecutionOutcome, BlockReader, Chain, DatabaseProviderRW, HeaderProvider, @@ -20,8 +15,9 @@ use reth_provider::{ use reth_prune_types::PruneModes; use reth_revm::database::StateProviderDatabase; use reth_stages_api::{ - BlockErrorKind, ExecInput, ExecOutput, MetricEvent, MetricEventsSender, Stage, StageError, - UnwindInput, UnwindOutput, + BlockErrorKind, CheckpointBlockRange, EntitiesCheckpoint, ExecInput, ExecOutput, + ExecutionCheckpoint, MetricEvent, MetricEventsSender, Stage, StageCheckpoint, StageError, + StageId, UnwindInput, UnwindOutput, }; use std::{ cmp::Ordering, @@ -75,6 +71,14 @@ pub struct ExecutionStage { external_clean_threshold: u64, /// Pruning configuration. prune_modes: PruneModes, + /// Input for the post execute commit hook. + /// Set after every [`ExecutionStage::execute`] and cleared after + /// [`ExecutionStage::post_execute_commit`]. + post_execute_commit_input: Option, + /// Input for the post unwind commit hook. + /// Set after every [`ExecutionStage::unwind`] and cleared after + /// [`ExecutionStage::post_unwind_commit`]. + post_unwind_commit_input: Option, /// Handle to communicate with `ExEx` manager. exex_manager_handle: ExExManagerHandle, } @@ -94,6 +98,8 @@ impl ExecutionStage { executor_provider, thresholds, prune_modes, + post_execute_commit_input: None, + post_unwind_commit_input: None, exex_manager_handle, } } @@ -272,7 +278,7 @@ where stage_progress = block_number; stage_checkpoint.progress.processed += block.gas_used; - // If we have ExEx's we need to save the block in memory for later + // If we have ExExes we need to save the block in memory for later if self.exex_manager_handle.has_exexs() { blocks.push(block); } @@ -288,28 +294,41 @@ where break } } + + // prepare execution output for writing let time = Instant::now(); let ExecutionOutcome { bundle, receipts, requests, first_block } = executor.finalize(); let state = ExecutionOutcome::new(bundle, receipts, first_block, requests); let write_preparation_duration = time.elapsed(); - // Check if we should send a [`ExExNotification`] to execution extensions. + // log the gas per second for the range we just executed + debug!( + target: "sync::stages::execution", + start = start_block, + end = stage_progress, + throughput = format_gas_throughput(cumulative_gas, execution_duration), + "Finished executing block range" + ); + + // Prepare the input for post execute commit hook, where an `ExExNotification` will be sent. // - // Note: Since we only write to `blocks` if there are any ExEx's we don't need to perform + // Note: Since we only write to `blocks` if there are any ExExes, we don't need to perform // the `has_exexs` check here as well if !blocks.is_empty() { - let chain = Arc::new(Chain::new( - blocks.into_iter().map(|block| { - let hash = block.header.hash_slow(); - block.seal(hash) - }), - state.clone(), - None, - )); - - // NOTE: We can ignore the error here, since an error means that the channel is closed, - // which means the manager has died, which then in turn means the node is shutting down. - let _ = self.exex_manager_handle.send(ExExNotification::ChainCommitted { new: chain }); + let blocks = blocks.into_iter().map(|block| { + let hash = block.header.hash_slow(); + block.seal(hash) + }); + + let previous_input = + self.post_execute_commit_input.replace(Chain::new(blocks, state.clone(), None)); + debug_assert!( + previous_input.is_none(), + "Previous post execute commit input wasn't processed" + ); + if let Some(previous_input) = previous_input { + tracing::debug!(target: "sync::stages::execution", ?previous_input, "Previous post execute commit input wasn't processed"); + } } let time = Instant::now(); @@ -337,6 +356,18 @@ where }) } + fn post_execute_commit(&mut self) -> Result<(), StageError> { + let Some(chain) = self.post_execute_commit_input.take() else { return Ok(()) }; + + // NOTE: We can ignore the error here, since an error means that the channel is closed, + // which means the manager has died, which then in turn means the node is shutting down. + let _ = self + .exex_manager_handle + .send(ExExNotification::ChainCommitted { new: Arc::new(chain) }); + + Ok(()) + } + /// Unwind the stage. fn unwind( &mut self, @@ -356,17 +387,23 @@ where // This also updates `PlainStorageState` and `PlainAccountState`. let bundle_state_with_receipts = provider.unwind_or_peek_state::(range.clone())?; - // Construct a `ExExNotification` if we have ExEx's installed. + // Prepare the input for post unwind commit hook, where an `ExExNotification` will be sent. if self.exex_manager_handle.has_exexs() { - // Get the blocks for the unwound range. This is needed for `ExExNotification`. + // Get the blocks for the unwound range. let blocks = provider.get_take_block_range::(range.clone())?; - let chain = Chain::new(blocks, bundle_state_with_receipts, None); + let previous_input = self.post_unwind_commit_input.replace(Chain::new( + blocks, + bundle_state_with_receipts, + None, + )); - // NOTE: We can ignore the error here, since an error means that the channel is closed, - // which means the manager has died, which then in turn means the node is shutting down. - let _ = self - .exex_manager_handle - .send(ExExNotification::ChainReverted { old: Arc::new(chain) }); + debug_assert!( + previous_input.is_none(), + "Previous post unwind commit input wasn't processed" + ); + if let Some(previous_input) = previous_input { + tracing::debug!(target: "sync::stages::execution", ?previous_input, "Previous post unwind commit input wasn't processed"); + } } // Unwind all receipts for transactions in the block range @@ -403,6 +440,17 @@ where Ok(UnwindOutput { checkpoint }) } + + fn post_unwind_commit(&mut self) -> Result<(), StageError> { + let Some(chain) = self.post_unwind_commit_input.take() else { return Ok(()) }; + + // NOTE: We can ignore the error here, since an error means that the channel is closed, + // which means the manager has died, which then in turn means the node is shutting down. + let _ = + self.exex_manager_handle.send(ExExNotification::ChainReverted { old: Arc::new(chain) }); + + Ok(()) + } } fn execution_checkpoint( @@ -555,6 +603,23 @@ impl From for ExecutionStageThresholds { } } +/// Returns a formatted gas throughput log, showing either: +/// * "Kgas/s", or 1,000 gas per second +/// * "Mgas/s", or 1,000,000 gas per second +/// * "Ggas/s", or 1,000,000,000 gas per second +/// +/// Depending on the magnitude of the gas throughput. +pub fn format_gas_throughput(gas: u64, execution_duration: Duration) -> String { + let gas_per_second = gas as f64 / execution_duration.as_secs_f64(); + if gas_per_second < 1_000_000.0 { + format!("{:.} Kgas/second", gas_per_second / 1_000.0) + } else if gas_per_second < 1_000_000_000.0 { + format!("{:.} Mgas/second", gas_per_second / 1_000_000.0) + } else { + format!("{:.} Ggas/second", gas_per_second / 1_000_000_000.0) + } +} + /// Returns a `StaticFileProviderRWRefMut` static file producer after performing a consistency /// check. /// @@ -643,14 +708,15 @@ mod tests { use reth_evm_ethereum::execute::EthExecutorProvider; use reth_execution_errors::BlockValidationError; use reth_primitives::{ - address, hex_literal::hex, keccak256, stage::StageUnitCheckpoint, Account, Address, - Bytecode, ChainSpecBuilder, SealedBlock, StorageEntry, B256, U256, + address, hex_literal::hex, keccak256, Account, Address, Bytecode, ChainSpecBuilder, + SealedBlock, StorageEntry, B256, U256, }; use reth_provider::{ test_utils::create_test_provider_factory, AccountReader, ReceiptProvider, StaticFileProviderFactory, }; use reth_prune_types::{PruneMode, ReceiptsLogPruneConfig}; + use reth_stages_api::StageUnitCheckpoint; use std::collections::BTreeMap; fn stage() -> ExecutionStage { @@ -671,6 +737,22 @@ mod tests { ) } + #[test] + fn test_gas_throughput_fmt() { + let duration = Duration::from_secs(1); + let gas = 100_000; + let throughput = format_gas_throughput(gas, duration); + assert_eq!(throughput, "100 Kgas/second"); + + let gas = 100_000_000; + let throughput = format_gas_throughput(gas, duration); + assert_eq!(throughput, "100 Mgas/second"); + + let gas = 100_000_000_000; + let throughput = format_gas_throughput(gas, duration); + assert_eq!(throughput, "100 Ggas/second"); + } + #[test] fn execution_checkpoint_matches() { let factory = create_test_provider_factory(); diff --git a/crates/stages/stages/src/stages/finish.rs b/crates/stages/stages/src/stages/finish.rs index bfc2fc91d351..9eb3a6d762b8 100644 --- a/crates/stages/stages/src/stages/finish.rs +++ b/crates/stages/stages/src/stages/finish.rs @@ -1,7 +1,8 @@ use reth_db_api::database::Database; -use reth_primitives::stage::{StageCheckpoint, StageId}; use reth_provider::DatabaseProviderRW; -use reth_stages_api::{ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput}; +use reth_stages_api::{ + ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, StageId, UnwindInput, UnwindOutput, +}; /// The finish stage. /// diff --git a/crates/stages/stages/src/stages/hashing_account.rs b/crates/stages/stages/src/stages/hashing_account.rs index 4ded60a3d9d6..fe8bc8547a58 100644 --- a/crates/stages/stages/src/stages/hashing_account.rs +++ b/crates/stages/stages/src/stages/hashing_account.rs @@ -7,13 +7,12 @@ use reth_db_api::{ transaction::{DbTx, DbTxMut}, }; use reth_etl::Collector; -use reth_primitives::{ - keccak256, - stage::{AccountHashingCheckpoint, EntitiesCheckpoint, StageCheckpoint, StageId}, - Account, B256, -}; +use reth_primitives::{keccak256, Account, B256}; use reth_provider::{AccountExtReader, DatabaseProviderRW, HashingWriter, StatsReader}; -use reth_stages_api::{ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput}; +use reth_stages_api::{ + AccountHashingCheckpoint, EntitiesCheckpoint, ExecInput, ExecOutput, Stage, StageCheckpoint, + StageError, StageId, UnwindInput, UnwindOutput, +}; use reth_storage_errors::provider::ProviderResult; use std::{ fmt::Debug, @@ -296,8 +295,9 @@ mod tests { UnwindStageTestRunner, }; use assert_matches::assert_matches; - use reth_primitives::{stage::StageUnitCheckpoint, Account, U256}; + use reth_primitives::{Account, U256}; use reth_provider::providers::StaticFileWriter; + use reth_stages_api::StageUnitCheckpoint; use test_utils::*; stage_test_suite_ext!(AccountHashingTestRunner, account_hashing); diff --git a/crates/stages/stages/src/stages/hashing_storage.rs b/crates/stages/stages/src/stages/hashing_storage.rs index 77374fb0b754..662f1d1a7728 100644 --- a/crates/stages/stages/src/stages/hashing_storage.rs +++ b/crates/stages/stages/src/stages/hashing_storage.rs @@ -9,13 +9,12 @@ use reth_db_api::{ transaction::{DbTx, DbTxMut}, }; use reth_etl::Collector; -use reth_primitives::{ - keccak256, - stage::{EntitiesCheckpoint, StageCheckpoint, StageId, StorageHashingCheckpoint}, - BufMut, StorageEntry, B256, -}; +use reth_primitives::{keccak256, BufMut, StorageEntry, B256}; use reth_provider::{DatabaseProviderRW, HashingWriter, StatsReader, StorageReader}; -use reth_stages_api::{ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput}; +use reth_stages_api::{ + EntitiesCheckpoint, ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, StageId, + StorageHashingCheckpoint, UnwindInput, UnwindOutput, +}; use reth_storage_errors::provider::ProviderResult; use std::{ fmt::Debug, diff --git a/crates/stages/stages/src/stages/headers.rs b/crates/stages/stages/src/stages/headers.rs index 0864da06e6c9..6aa464b89192 100644 --- a/crates/stages/stages/src/stages/headers.rs +++ b/crates/stages/stages/src/stages/headers.rs @@ -10,19 +10,15 @@ use reth_db_api::{ }; use reth_etl::Collector; use reth_network_p2p::headers::{downloader::HeaderDownloader, error::HeadersDownloaderError}; -use reth_primitives::{ - stage::{ - CheckpointBlockRange, EntitiesCheckpoint, HeadersCheckpoint, StageCheckpoint, StageId, - }, - BlockHash, BlockNumber, SealedHeader, StaticFileSegment, -}; +use reth_primitives::{BlockHash, BlockNumber, SealedHeader, StaticFileSegment}; use reth_provider::{ providers::{StaticFileProvider, StaticFileWriter}, BlockHashReader, DatabaseProviderRW, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, HeaderSyncMode, }; use reth_stages_api::{ - BlockErrorKind, ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput, + BlockErrorKind, CheckpointBlockRange, EntitiesCheckpoint, ExecInput, ExecOutput, + HeadersCheckpoint, Stage, StageCheckpoint, StageError, StageId, UnwindInput, UnwindOutput, }; use reth_storage_errors::provider::ProviderError; use std::{ @@ -380,12 +376,11 @@ mod tests { stage_test_suite, ExecuteStageTestRunner, StageTestRunner, UnwindStageTestRunner, }; use assert_matches::assert_matches; - use reth_primitives::{ - stage::StageUnitCheckpoint, BlockBody, SealedBlock, SealedBlockWithSenders, B256, - }; + use reth_primitives::{BlockBody, SealedBlock, SealedBlockWithSenders, B256}; use reth_provider::{ ExecutionOutcome, BlockWriter, ProviderFactory, StaticFileProviderFactory, }; + use reth_stages_api::StageUnitCheckpoint; use reth_testing_utils::generators::{self, random_header, random_header_range}; use reth_trie::{updates::TrieUpdates, HashedPostState}; use test_runner::HeadersTestRunner; diff --git a/crates/stages/stages/src/stages/index_account_history.rs b/crates/stages/stages/src/stages/index_account_history.rs index d4c77bd24c59..7f83185277c6 100644 --- a/crates/stages/stages/src/stages/index_account_history.rs +++ b/crates/stages/stages/src/stages/index_account_history.rs @@ -2,15 +2,14 @@ use super::{collect_history_indices, load_history_indices}; use reth_config::config::{EtlConfig, IndexHistoryConfig}; use reth_db::tables; use reth_db_api::{database::Database, models::ShardedKey, table::Decode, transaction::DbTxMut}; -use reth_primitives::{ - stage::{StageCheckpoint, StageId}, - Address, -}; +use reth_primitives::Address; use reth_provider::{ DatabaseProviderRW, HistoryWriter, PruneCheckpointReader, PruneCheckpointWriter, }; use reth_prune_types::{PruneCheckpoint, PruneMode, PrunePurpose, PruneSegment}; -use reth_stages_api::{ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput}; +use reth_stages_api::{ + ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, StageId, UnwindInput, UnwindOutput, +}; use std::fmt::Debug; use tracing::info; diff --git a/crates/stages/stages/src/stages/index_storage_history.rs b/crates/stages/stages/src/stages/index_storage_history.rs index 5fcbe1fb4cbb..23332f2d6ee8 100644 --- a/crates/stages/stages/src/stages/index_storage_history.rs +++ b/crates/stages/stages/src/stages/index_storage_history.rs @@ -1,4 +1,5 @@ use super::{collect_history_indices, load_history_indices}; +use crate::{StageCheckpoint, StageId}; use reth_config::config::{EtlConfig, IndexHistoryConfig}; use reth_db::tables; use reth_db_api::{ @@ -7,7 +8,6 @@ use reth_db_api::{ table::Decode, transaction::DbTxMut, }; -use reth_primitives::stage::{StageCheckpoint, StageId}; use reth_provider::{ DatabaseProviderRW, HistoryWriter, PruneCheckpointReader, PruneCheckpointWriter, }; diff --git a/crates/stages/stages/src/stages/merkle.rs b/crates/stages/stages/src/stages/merkle.rs index defe248944e4..885fc86c579b 100644 --- a/crates/stages/stages/src/stages/merkle.rs +++ b/crates/stages/stages/src/stages/merkle.rs @@ -5,16 +5,14 @@ use reth_db_api::{ database::Database, transaction::{DbTx, DbTxMut}, }; -use reth_primitives::{ - stage::{EntitiesCheckpoint, MerkleCheckpoint, StageCheckpoint, StageId}, - BlockNumber, GotExpected, SealedHeader, B256, -}; +use reth_primitives::{BlockNumber, GotExpected, SealedHeader, B256}; use reth_provider::{ DatabaseProviderRW, HeaderProvider, ProviderError, StageCheckpointReader, StageCheckpointWriter, StatsReader, }; use reth_stages_api::{ - BlockErrorKind, ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput, + BlockErrorKind, EntitiesCheckpoint, ExecInput, ExecOutput, MerkleCheckpoint, Stage, + StageCheckpoint, StageError, StageId, UnwindInput, UnwindOutput, }; use reth_trie::{IntermediateStateRootState, StateRoot, StateRootProgress, StoredSubNode}; use std::fmt::Debug; @@ -367,10 +365,9 @@ mod tests { }; use assert_matches::assert_matches; use reth_db_api::cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO}; - use reth_primitives::{ - keccak256, stage::StageUnitCheckpoint, SealedBlock, StaticFileSegment, StorageEntry, U256, - }; + use reth_primitives::{keccak256, SealedBlock, StaticFileSegment, StorageEntry, U256}; use reth_provider::{providers::StaticFileWriter, StaticFileProviderFactory}; + use reth_stages_api::StageUnitCheckpoint; use reth_testing_utils::{ generators, generators::{ diff --git a/crates/stages/stages/src/stages/mod.rs b/crates/stages/stages/src/stages/mod.rs index c1a8666be573..1f7ae1e9b6a0 100644 --- a/crates/stages/stages/src/stages/mod.rs +++ b/crates/stages/stages/src/stages/mod.rs @@ -56,12 +56,8 @@ mod tests { use reth_evm_ethereum::execute::EthExecutorProvider; use reth_exex::ExExManagerHandle; use reth_primitives::{ - address, - hex_literal::hex, - keccak256, - stage::{PipelineTarget, StageCheckpoint, StageId}, - Account, BlockNumber, Bytecode, ChainSpecBuilder, SealedBlock, StaticFileSegment, B256, - U256, + address, hex_literal::hex, keccak256, Account, BlockNumber, Bytecode, ChainSpecBuilder, + SealedBlock, StaticFileSegment, B256, U256, }; use reth_provider::{ providers::StaticFileWriter, AccountExtReader, BlockReader, DatabaseProviderFactory, @@ -69,7 +65,7 @@ mod tests { StaticFileProviderFactory, StorageReader, }; use reth_prune_types::{PruneMode, PruneModes}; - use reth_stages_api::{ExecInput, Stage}; + use reth_stages_api::{ExecInput, PipelineTarget, Stage, StageCheckpoint, StageId}; use reth_testing_utils::generators::{self, random_block, random_block_range, random_receipt}; use std::{io::Write, sync::Arc}; diff --git a/crates/stages/stages/src/stages/sender_recovery.rs b/crates/stages/stages/src/stages/sender_recovery.rs index a60f6bc52800..41df7795c3c4 100644 --- a/crates/stages/stages/src/stages/sender_recovery.rs +++ b/crates/stages/stages/src/stages/sender_recovery.rs @@ -6,17 +6,15 @@ use reth_db_api::{ database::Database, transaction::{DbTx, DbTxMut}, }; -use reth_primitives::{ - stage::{EntitiesCheckpoint, StageCheckpoint, StageId}, - Address, StaticFileSegment, TransactionSignedNoHash, TxNumber, -}; +use reth_primitives::{Address, StaticFileSegment, TransactionSignedNoHash, TxNumber}; use reth_provider::{ BlockReader, DatabaseProviderRW, HeaderProvider, ProviderError, PruneCheckpointReader, StatsReader, }; use reth_prune_types::PruneSegment; use reth_stages_api::{ - BlockErrorKind, ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput, + BlockErrorKind, EntitiesCheckpoint, ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, + StageId, UnwindInput, UnwindOutput, }; use std::{fmt::Debug, ops::Range, sync::mpsc}; use thiserror::Error; @@ -282,14 +280,13 @@ struct FailedSenderRecoveryError { mod tests { use assert_matches::assert_matches; use reth_db_api::cursor::DbCursorRO; - use reth_primitives::{ - stage::StageUnitCheckpoint, BlockNumber, SealedBlock, TransactionSigned, B256, - }; + use reth_primitives::{BlockNumber, SealedBlock, TransactionSigned, B256}; use reth_provider::{ providers::StaticFileWriter, PruneCheckpointWriter, StaticFileProviderFactory, TransactionsProvider, }; use reth_prune_types::{PruneCheckpoint, PruneMode}; + use reth_stages_api::StageUnitCheckpoint; use reth_testing_utils::{ generators, generators::{random_block, random_block_range}, diff --git a/crates/stages/stages/src/stages/tx_lookup.rs b/crates/stages/stages/src/stages/tx_lookup.rs index 66fa76810404..4cb422e3392d 100644 --- a/crates/stages/stages/src/stages/tx_lookup.rs +++ b/crates/stages/stages/src/stages/tx_lookup.rs @@ -7,16 +7,16 @@ use reth_db_api::{ transaction::{DbTx, DbTxMut}, }; use reth_etl::Collector; -use reth_primitives::{ - stage::{EntitiesCheckpoint, StageCheckpoint, StageId}, - TxHash, TxNumber, -}; +use reth_primitives::{TxHash, TxNumber}; use reth_provider::{ BlockReader, DatabaseProviderRW, PruneCheckpointReader, PruneCheckpointWriter, StatsReader, TransactionsProvider, TransactionsProviderExt, }; use reth_prune_types::{PruneCheckpoint, PruneMode, PrunePurpose, PruneSegment}; -use reth_stages_api::{ExecInput, ExecOutput, Stage, StageError, UnwindInput, UnwindOutput}; +use reth_stages_api::{ + EntitiesCheckpoint, ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, StageId, + UnwindInput, UnwindOutput, +}; use reth_storage_errors::provider::ProviderError; use tracing::*; @@ -242,8 +242,9 @@ mod tests { TestRunnerError, TestStageDB, UnwindStageTestRunner, }; use assert_matches::assert_matches; - use reth_primitives::{stage::StageUnitCheckpoint, BlockNumber, SealedBlock, B256}; + use reth_primitives::{BlockNumber, SealedBlock, B256}; use reth_provider::{providers::StaticFileWriter, StaticFileProviderFactory}; + use reth_stages_api::StageUnitCheckpoint; use reth_testing_utils::{ generators, generators::{random_block, random_block_range}, diff --git a/crates/stages/stages/src/test_utils/macros.rs b/crates/stages/stages/src/test_utils/macros.rs index 11fb46cde0b1..90f39e5bbf4d 100644 --- a/crates/stages/stages/src/test_utils/macros.rs +++ b/crates/stages/stages/src/test_utils/macros.rs @@ -36,7 +36,7 @@ macro_rules! stage_test_suite { let mut runner = $runner::default(); let input = reth_stages_api::ExecInput { target: Some(target), - checkpoint: Some(reth_primitives::stage::StageCheckpoint::new(current_checkpoint)), + checkpoint: Some(crate::StageCheckpoint::new(current_checkpoint)), }; let seed = runner.seed_execution(input).expect("failed to seed"); let rx = runner.execute(input); @@ -100,7 +100,7 @@ macro_rules! stage_test_suite { let mut runner = $runner::default(); let execute_input = reth_stages_api::ExecInput { target: Some(target), - checkpoint: Some(reth_primitives::stage::StageCheckpoint::new(current_checkpoint)), + checkpoint: Some(crate::StageCheckpoint::new(current_checkpoint)), }; let seed = runner.seed_execution(execute_input).expect("failed to seed"); @@ -127,7 +127,7 @@ macro_rules! stage_test_suite { // Run stage unwind let unwind_input = reth_stages_api::UnwindInput { unwind_to: current_checkpoint, - checkpoint: reth_primitives::stage::StageCheckpoint::new(target), + checkpoint: crate::StageCheckpoint::new(target), bad_block: None, }; @@ -167,7 +167,7 @@ macro_rules! stage_test_suite_ext { let mut runner = $runner::default(); let input = reth_stages_api::ExecInput { target: Some(current_checkpoint), - checkpoint: Some(reth_primitives::stage::StageCheckpoint::new(current_checkpoint)), + checkpoint: Some(crate::StageCheckpoint::new(current_checkpoint)), }; let seed = runner.seed_execution(input).expect("failed to seed"); diff --git a/crates/stages/stages/src/test_utils/mod.rs b/crates/stages/stages/src/test_utils/mod.rs index 9e60417551ab..4e5344b22755 100644 --- a/crates/stages/stages/src/test_utils/mod.rs +++ b/crates/stages/stages/src/test_utils/mod.rs @@ -1,4 +1,4 @@ -use reth_primitives::stage::StageId; +use reth_stages_api::StageId; #[cfg(test)] mod macros; diff --git a/crates/stages/types/Cargo.toml b/crates/stages/types/Cargo.toml new file mode 100644 index 000000000000..ab64a89c9036 --- /dev/null +++ b/crates/stages/types/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "reth-stages-types" +version.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true +description = "Commonly used types for stages usage in reth." + +[lints] +workspace = true + +[dependencies] +reth-codecs.workspace = true +reth-trie-types.workspace = true +alloy-primitives.workspace = true + +modular-bitfield.workspace = true +bytes.workspace = true +serde.workspace = true + +[dev-dependencies] +arbitrary = { workspace = true, features = ["derive"] } +proptest.workspace = true +proptest-derive.workspace = true +test-fuzz.workspace = true +rand.workspace = true \ No newline at end of file diff --git a/crates/primitives/src/stage/checkpoints.rs b/crates/stages/types/src/checkpoints.rs similarity index 99% rename from crates/primitives/src/stage/checkpoints.rs rename to crates/stages/types/src/checkpoints.rs index 1ab42c56c77d..b78751cc675b 100644 --- a/crates/primitives/src/stage/checkpoints.rs +++ b/crates/stages/types/src/checkpoints.rs @@ -1,4 +1,4 @@ -use crate::{Address, BlockNumber, B256}; +use alloy_primitives::{Address, BlockNumber, B256}; use bytes::Buf; use reth_codecs::{main_codec, Compact}; use reth_trie_types::{hash_builder::HashBuilderState, StoredSubNode}; diff --git a/crates/primitives/src/stage/id.rs b/crates/stages/types/src/id.rs similarity index 100% rename from crates/primitives/src/stage/id.rs rename to crates/stages/types/src/id.rs diff --git a/crates/primitives/src/stage/mod.rs b/crates/stages/types/src/lib.rs similarity index 76% rename from crates/primitives/src/stage/mod.rs rename to crates/stages/types/src/lib.rs index 6637cb41e8fa..93106bd886d1 100644 --- a/crates/primitives/src/stage/mod.rs +++ b/crates/stages/types/src/lib.rs @@ -1,7 +1,17 @@ -//! Staged sync primitives. +//! Commonly used types for staged sync usage. + +#![doc( + html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", + html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", + issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" +)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +// TODO: remove when https://github.com/proptest-rs/proptest/pull/427 is merged +#![allow(unknown_lints, non_local_definitions)] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] mod id; -use crate::{BlockHash, BlockNumber}; +use alloy_primitives::{BlockHash, BlockNumber}; pub use id::StageId; mod checkpoints; diff --git a/crates/storage/db-api/Cargo.toml b/crates/storage/db-api/Cargo.toml index 7a97075f3c65..fbbf0ca5d7be 100644 --- a/crates/storage/db-api/Cargo.toml +++ b/crates/storage/db-api/Cargo.toml @@ -17,6 +17,7 @@ reth-codecs.workspace = true reth-primitives.workspace = true reth-prune-types.workspace = true reth-storage-errors.workspace = true +reth-stages-types.workspace = true reth-trie-types.workspace = true # codecs diff --git a/crates/storage/db-api/src/models/mod.rs b/crates/storage/db-api/src/models/mod.rs index 108095a3c568..7438feedea51 100644 --- a/crates/storage/db-api/src/models/mod.rs +++ b/crates/storage/db-api/src/models/mod.rs @@ -5,8 +5,9 @@ use crate::{ DatabaseError, }; use reth_codecs::{main_codec, Compact}; -use reth_primitives::{stage::StageCheckpoint, Address, B256, *}; +use reth_primitives::{Address, B256, *}; use reth_prune_types::{PruneCheckpoint, PruneSegment}; +use reth_stages_types::StageCheckpoint; use reth_trie_types::{StoredNibbles, StoredNibblesSubKey, *}; pub mod accounts; @@ -298,15 +299,15 @@ add_wrapper_struct!((ClientVersion, CompactClientVersion)); mod tests { use super::*; use reth_primitives::{ - stage::{ - AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint, - ExecutionCheckpoint, HeadersCheckpoint, IndexHistoryCheckpoint, StageCheckpoint, - StageUnitCheckpoint, StorageHashingCheckpoint, - }, Account, Header, Receipt, ReceiptWithBloom, SealedHeader, TxEip1559, TxEip2930, TxEip4844, TxLegacy, Withdrawals, }; use reth_prune_types::{PruneCheckpoint, PruneMode, PruneSegment}; + use reth_stages_types::{ + AccountHashingCheckpoint, CheckpointBlockRange, EntitiesCheckpoint, ExecutionCheckpoint, + HeadersCheckpoint, IndexHistoryCheckpoint, StageCheckpoint, StageUnitCheckpoint, + StorageHashingCheckpoint, + }; // each value in the database has an extra field named flags that encodes metadata about other // fields in the value, e.g. offset and length. diff --git a/crates/storage/db-common/Cargo.toml b/crates/storage/db-common/Cargo.toml index b0bf2b84c6d1..0e6a3720dc87 100644 --- a/crates/storage/db-common/Cargo.toml +++ b/crates/storage/db-common/Cargo.toml @@ -17,6 +17,7 @@ reth-config.workspace = true reth-trie.workspace = true reth-etl.workspace = true reth-codecs.workspace = true +reth-stages-types.workspace = true # misc eyre.workspace = true diff --git a/crates/storage/db-common/src/init.rs b/crates/storage/db-common/src/init.rs index 3440e0031c7d..9f5cc692e365 100644 --- a/crates/storage/db-common/src/init.rs +++ b/crates/storage/db-common/src/init.rs @@ -6,7 +6,6 @@ use reth_db::tables; use reth_db_api::{database::Database, transaction::DbTxMut, DatabaseError}; use reth_etl::Collector; use reth_primitives::{ - stage::{StageCheckpoint, StageId}, Account, Address, Bytecode, ChainSpec, GenesisAccount, Receipts, StaticFileSegment, StorageEntry, B256, U256, }; @@ -18,6 +17,7 @@ use reth_provider::{ HashingWriter, HistoryWriter, OriginalValuesKnown, ProviderError, ProviderFactory, StageCheckpointWriter, StateWriter, StaticFileProviderFactory, }; +use reth_stages_types::{StageCheckpoint, StageId}; use reth_trie::{IntermediateStateRootState, StateRoot as StateRootComputer, StateRootProgress}; use serde::{Deserialize, Serialize}; use std::{ diff --git a/crates/storage/db/Cargo.toml b/crates/storage/db/Cargo.toml index 63c750ce8a99..ca27a9a40739 100644 --- a/crates/storage/db/Cargo.toml +++ b/crates/storage/db/Cargo.toml @@ -23,6 +23,7 @@ reth-libmdbx = { workspace = true, optional = true, features = [ ] } reth-nippy-jar.workspace = true reth-prune-types.workspace = true +reth-stages-types.workspace = true reth-tracing.workspace = true reth-trie-types.workspace = true diff --git a/crates/storage/db/src/implementation/mdbx/mod.rs b/crates/storage/db/src/implementation/mdbx/mod.rs index d9d1a8e2a92c..78b1ad6359ea 100644 --- a/crates/storage/db/src/implementation/mdbx/mod.rs +++ b/crates/storage/db/src/implementation/mdbx/mod.rs @@ -17,8 +17,8 @@ use reth_db_api::{ transaction::{DbTx, DbTxMut}, }; use reth_libmdbx::{ - DatabaseFlags, Environment, EnvironmentFlags, Geometry, MaxReadTransactionDuration, Mode, - PageSize, SyncMode, RO, RW, + ffi, DatabaseFlags, Environment, EnvironmentFlags, Geometry, HandleSlowReadersReturnCode, + MaxReadTransactionDuration, Mode, PageSize, SyncMode, RO, RW, }; use reth_storage_errors::db::LogLevel; use reth_tracing::tracing::error; @@ -289,42 +289,52 @@ impl DatabaseEnv { shrink_threshold: Some(0), page_size: Some(PageSize::Set(default_page_size())), }); - #[cfg(not(windows))] - { - fn is_current_process(id: u32) -> bool { - #[cfg(unix)] - { - id == std::os::unix::process::parent_id() || id == std::process::id() - } - #[cfg(not(unix))] - { - id == std::process::id() - } + fn is_current_process(id: u32) -> bool { + #[cfg(unix)] + { + id == std::os::unix::process::parent_id() || id == std::process::id() + } + + #[cfg(not(unix))] + { + id == std::process::id() } - inner_env.set_handle_slow_readers( - |process_id: u32, thread_id: u32, read_txn_id: u64, gap: usize, space: usize, retry: isize| { - if space > MAX_SAFE_READER_SPACE { - let message = if is_current_process(process_id) { - "Current process has a long-lived database transaction that grows the database file." - } else { - "External process has a long-lived database transaction that grows the database file. Use shorter-lived read transactions or shut down the node." - }; - reth_tracing::tracing::warn!( - target: "storage::db::mdbx", - ?process_id, - ?thread_id, - ?read_txn_id, - ?gap, - ?space, - ?retry, - message - ) - } - - reth_libmdbx::HandleSlowReadersReturnCode::ProceedWithoutKillingReader - }); } + + extern "C" fn handle_slow_readers( + _env: *const ffi::MDBX_env, + _txn: *const ffi::MDBX_txn, + process_id: ffi::mdbx_pid_t, + thread_id: ffi::mdbx_tid_t, + read_txn_id: u64, + gap: std::ffi::c_uint, + space: usize, + retry: std::ffi::c_int, + ) -> HandleSlowReadersReturnCode { + if space > MAX_SAFE_READER_SPACE { + let message = if is_current_process(process_id as u32) { + "Current process has a long-lived database transaction that grows the database file." + } else { + "External process has a long-lived database transaction that grows the database file. \ + Use shorter-lived read transactions or shut down the node." + }; + reth_tracing::tracing::warn!( + target: "storage::db::mdbx", + ?process_id, + ?thread_id, + ?read_txn_id, + ?gap, + ?space, + ?retry, + "{message}" + ) + } + + reth_libmdbx::HandleSlowReadersReturnCode::ProceedWithoutKillingReader + } + inner_env.set_handle_slow_readers(handle_slow_readers); + inner_env.set_flags(EnvironmentFlags { mode, // We disable readahead because it improves performance for linear scans, but diff --git a/crates/storage/db/src/implementation/mdbx/tx.rs b/crates/storage/db/src/implementation/mdbx/tx.rs index b95d543f901a..8feb6c90ab27 100644 --- a/crates/storage/db/src/implementation/mdbx/tx.rs +++ b/crates/storage/db/src/implementation/mdbx/tx.rs @@ -10,7 +10,7 @@ use reth_db_api::{ table::{Compress, DupSort, Encode, Table, TableImporter}, transaction::{DbTx, DbTxMut}, }; -use reth_libmdbx::{ffi::DBI, CommitLatency, Transaction, TransactionKind, WriteFlags, RW}; +use reth_libmdbx::{ffi::MDBX_dbi, CommitLatency, Transaction, TransactionKind, WriteFlags, RW}; use reth_storage_errors::db::{DatabaseWriteError, DatabaseWriteOperation}; use reth_tracing::tracing::{debug, trace, warn}; use std::{ @@ -75,7 +75,7 @@ impl Tx { } /// Gets a table database handle if it exists, otherwise creates it. - pub fn get_dbi(&self) -> Result { + pub fn get_dbi(&self) -> Result { self.inner .open_db(Some(T::NAME)) .map(|db| db.dbi()) diff --git a/crates/storage/db/src/tables/mod.rs b/crates/storage/db/src/tables/mod.rs index f94c07d7776a..5d3c685a526f 100644 --- a/crates/storage/db/src/tables/mod.rs +++ b/crates/storage/db/src/tables/mod.rs @@ -32,10 +32,11 @@ use reth_db_api::{ table::{Decode, DupSort, Encode, Table}, }; use reth_primitives::{ - stage::StageCheckpoint, Account, Address, BlockHash, BlockNumber, Bytecode, Header, - IntegerList, Receipt, Requests, StorageEntry, TransactionSignedNoHash, TxHash, TxNumber, B256, + Account, Address, BlockHash, BlockNumber, Bytecode, Header, IntegerList, Receipt, Requests, + StorageEntry, TransactionSignedNoHash, TxHash, TxNumber, B256, }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; +use reth_stages_types::StageCheckpoint; use reth_trie_types::{StorageTrieEntry, StoredBranchNode, StoredNibbles, StoredNibblesSubKey}; use serde::{Deserialize, Serialize}; use std::fmt; diff --git a/crates/storage/libmdbx-rs/Cargo.toml b/crates/storage/libmdbx-rs/Cargo.toml index 2042cd896cc5..68576e0d066e 100644 --- a/crates/storage/libmdbx-rs/Cargo.toml +++ b/crates/storage/libmdbx-rs/Cargo.toml @@ -25,10 +25,7 @@ thiserror.workspace = true dashmap = { workspace = true, features = ["inline"], optional = true } tracing.workspace = true -ffi = { package = "reth-mdbx-sys", path = "./mdbx-sys" } - -[target.'cfg(not(windows))'.dependencies] -libffi = "3.2.0" +reth-mdbx-sys.workspace = true [features] default = [] @@ -36,7 +33,11 @@ return-borrowed = [] read-tx-timeouts = ["dashmap", "dashmap/inline"] [dev-dependencies] -pprof = { workspace = true, features = ["flamegraph", "frame-pointer", "criterion"] } +pprof = { workspace = true, features = [ + "flamegraph", + "frame-pointer", + "criterion", +] } criterion.workspace = true rand.workspace = true rand_xorshift = "0.3" diff --git a/crates/storage/libmdbx-rs/benches/cursor.rs b/crates/storage/libmdbx-rs/benches/cursor.rs index a73b4fe275e8..acd7d9a72c72 100644 --- a/crates/storage/libmdbx-rs/benches/cursor.rs +++ b/crates/storage/libmdbx-rs/benches/cursor.rs @@ -1,10 +1,9 @@ #![allow(missing_docs)] mod utils; -use ::ffi::*; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use pprof::criterion::{Output, PProfProfiler}; -use reth_libmdbx::*; +use reth_libmdbx::{ffi::*, *}; use std::ptr; use utils::*; diff --git a/crates/storage/libmdbx-rs/benches/transaction.rs b/crates/storage/libmdbx-rs/benches/transaction.rs index 8ec7702f7b25..8cc84b01f3c4 100644 --- a/crates/storage/libmdbx-rs/benches/transaction.rs +++ b/crates/storage/libmdbx-rs/benches/transaction.rs @@ -2,11 +2,10 @@ mod utils; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use ffi::*; use libc::size_t; use rand::{prelude::SliceRandom, SeedableRng}; use rand_xorshift::XorShiftRng; -use reth_libmdbx::{ObjectLength, WriteFlags}; +use reth_libmdbx::{ffi::*, ObjectLength, WriteFlags}; use std::ptr; use utils::*; diff --git a/crates/storage/libmdbx-rs/src/environment.rs b/crates/storage/libmdbx-rs/src/environment.rs index 34e64fa183a8..f1a2cbe14a50 100644 --- a/crates/storage/libmdbx-rs/src/environment.rs +++ b/crates/storage/libmdbx-rs/src/environment.rs @@ -10,8 +10,7 @@ use byteorder::{ByteOrder, NativeEndian}; use mem::size_of; use std::{ ffi::CString, - fmt, - fmt::Debug, + fmt::{self, Debug}, mem, ops::{Bound, RangeBounds}, path::Path, @@ -51,7 +50,6 @@ impl Environment { geometry: None, log_level: None, kind: Default::default(), - #[cfg(not(windows))] handle_slow_readers: None, #[cfg(feature = "read-tx-timeouts")] max_read_transaction_duration: None, @@ -514,6 +512,7 @@ impl Default for Geometry { /// implement timeout reset logic while waiting for a readers. /// /// # Returns +/// /// A return code that determines the further actions for MDBX and must match the action which /// was executed by the callback: /// * `-2` or less – An error condition and the reader was not killed. @@ -528,46 +527,37 @@ impl Default for Geometry { /// called later. /// * `2` or greater – The reader process was terminated or killed, and MDBX should entirely reset /// reader registration. -pub type HandleSlowReadersCallback = fn( - process_id: u32, - thread_id: u32, - read_txn_id: u64, - gap: usize, +pub type HandleSlowReadersCallback = extern "C" fn( + env: *const ffi::MDBX_env, + txn: *const ffi::MDBX_txn, + pid: ffi::mdbx_pid_t, + tid: ffi::mdbx_tid_t, + laggard: u64, + gap: std::ffi::c_uint, space: usize, - retry: isize, + retry: std::ffi::c_int, ) -> HandleSlowReadersReturnCode; #[derive(Debug)] +#[repr(i32)] pub enum HandleSlowReadersReturnCode { /// An error condition and the reader was not killed. - Error, + Error = -2, /// The callback was unable to solve the problem and agreed on `MDBX_MAP_FULL` error; /// MDBX should increase the database size or return `MDBX_MAP_FULL` error. - ProceedWithoutKillingReader, + ProceedWithoutKillingReader = -1, /// The callback solved the problem or just waited for a while, libmdbx should rescan the /// reader lock table and retry. This also includes a situation when corresponding transaction /// terminated in normal way by `mdbx_txn_abort()` or `mdbx_txn_reset()`, and may be restarted. /// I.e. reader slot isn't needed to be cleaned from transaction. - Success, + Success = 0, /// Transaction aborted asynchronous and reader slot should be cleared immediately, i.e. read /// transaction will not continue but `mdbx_txn_abort()` nor `mdbx_txn_reset()` will be called /// later. - ClearReaderSlot, + ClearReaderSlot = 1, /// The reader process was terminated or killed, and MDBX should entirely reset reader /// registration. - ReaderProcessTerminated, -} - -impl From for i32 { - fn from(value: HandleSlowReadersReturnCode) -> Self { - match value { - HandleSlowReadersReturnCode::Error => -2, - HandleSlowReadersReturnCode::ProceedWithoutKillingReader => -1, - HandleSlowReadersReturnCode::Success => 0, - HandleSlowReadersReturnCode::ClearReaderSlot => 1, - HandleSlowReadersReturnCode::ReaderProcessTerminated => 2, - } - } + ReaderProcessTerminated = 2, } /// Options for opening or creating an environment. @@ -585,7 +575,6 @@ pub struct EnvironmentBuilder { geometry: Option, Option)>>, log_level: Option, kind: EnvironmentKind, - #[cfg(not(windows))] handle_slow_readers: Option, #[cfg(feature = "read-tx-timeouts")] /// The maximum duration of a read transaction. If [None], but the `read-tx-timeout` feature is @@ -671,11 +660,10 @@ impl EnvironmentBuilder { ))?; } - #[cfg(not(windows))] if let Some(handle_slow_readers) = self.handle_slow_readers { mdbx_result(ffi::mdbx_env_set_hsr( env, - handle_slow_readers_callback(handle_slow_readers), + convert_hsr_fn(Some(handle_slow_readers)), ))?; } @@ -834,7 +822,6 @@ impl EnvironmentBuilder { /// Set the Handle-Slow-Readers callback. See [`HandleSlowReadersCallback`] for more /// information. - #[cfg(not(windows))] pub fn set_handle_slow_readers(&mut self, hsr: HandleSlowReadersCallback) -> &mut Self { self.handle_slow_readers = Some(hsr); self @@ -878,42 +865,10 @@ pub(crate) mod read_transactions { } } -/// Creates an instance of `MDBX_hsr_func`. -/// -/// Caution: this leaks the memory for callbacks, so they're alive throughout the program. It's -/// fine, because we also expect the database environment to be alive during this whole time. -#[cfg(not(windows))] -unsafe fn handle_slow_readers_callback(callback: HandleSlowReadersCallback) -> ffi::MDBX_hsr_func { - // Move the callback function to heap and intentionally leak it, so it's not dropped and the - // MDBX env can use it throughout the whole program. - let callback = Box::leak(Box::new(callback)); - - // Wrap the callback into an ffi binding. The callback is needed for a nicer UX with Rust types, - // and without `env` and `txn` arguments that we don't want to expose to the user. Again, - // move the closure to heap and leak. - let hsr = Box::leak(Box::new( - |_env: *const ffi::MDBX_env, - _txn: *const ffi::MDBX_txn, - pid: ffi::mdbx_pid_t, - tid: ffi::mdbx_tid_t, - laggard: u64, - gap: ::libc::c_uint, - space: usize, - retry: ::libc::c_int| - -> i32 { - callback(pid as u32, tid as u32, laggard, gap as usize, space, retry as isize).into() - }, - )); - - // Create a pointer to the C function from the Rust closure, and forcefully forget the original - // closure. - let closure = libffi::high::Closure8::new(hsr); - let closure_ptr = *closure.code_ptr(); - std::mem::forget(closure); - - // Cast the closure to FFI `extern fn` type. - #[allow(clippy::missing_transmute_annotations)] - Some(std::mem::transmute(closure_ptr)) +/// Converts a [`HandleSlowReadersCallback`] to the actual FFI function pointer. +#[allow(clippy::missing_transmute_annotations)] +fn convert_hsr_fn(callback: Option) -> ffi::MDBX_hsr_func { + unsafe { std::mem::transmute(callback) } } #[cfg(test)] @@ -924,11 +879,24 @@ mod tests { sync::atomic::{AtomicBool, Ordering}, }; - #[cfg(not(windows))] #[test] fn test_handle_slow_readers_callback() { static CALLED: AtomicBool = AtomicBool::new(false); + extern "C" fn handle_slow_readers( + _env: *const ffi::MDBX_env, + _txn: *const ffi::MDBX_txn, + _pid: ffi::mdbx_pid_t, + _tid: ffi::mdbx_tid_t, + _laggard: u64, + _gap: std::ffi::c_uint, + _space: usize, + _retry: std::ffi::c_int, + ) -> HandleSlowReadersReturnCode { + CALLED.store(true, Ordering::Relaxed); + HandleSlowReadersReturnCode::ProceedWithoutKillingReader + } + let tempdir = tempfile::tempdir().unwrap(); let env = Environment::builder() .set_geometry(Geometry::> { @@ -936,18 +904,7 @@ mod tests { page_size: Some(PageSize::MinimalAcceptable), // To create as many pages as possible ..Default::default() }) - .set_handle_slow_readers( - |_process_id: u32, - _thread_id: u32, - _read_txn_id: u64, - _gap: usize, - _space: usize, - _retry: isize| { - CALLED.store(true, Ordering::Relaxed); - - HandleSlowReadersReturnCode::ProceedWithoutKillingReader - }, - ) + .set_handle_slow_readers(handle_slow_readers) .open(tempdir.path()) .unwrap(); diff --git a/crates/storage/libmdbx-rs/src/lib.rs b/crates/storage/libmdbx-rs/src/lib.rs index 6ffaf8cb0897..6a0fe97f7276 100644 --- a/crates/storage/libmdbx-rs/src/lib.rs +++ b/crates/storage/libmdbx-rs/src/lib.rs @@ -8,6 +8,8 @@ #![allow(missing_docs, clippy::needless_pass_by_ref_mut)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +pub extern crate reth_mdbx_sys as ffi; + pub use crate::{ codec::*, cursor::{Cursor, Iter, IterDup}, @@ -20,9 +22,6 @@ pub use crate::{ flags::*, transaction::{CommitLatency, Transaction, TransactionKind, RO, RW}, }; -pub mod ffi { - pub use ffi::{MDBX_dbi as DBI, MDBX_log_level_t as LogLevel}; -} #[cfg(feature = "read-tx-timeouts")] pub use crate::environment::read_transactions::MaxReadTransactionDuration; diff --git a/crates/storage/libmdbx-rs/src/transaction.rs b/crates/storage/libmdbx-rs/src/transaction.rs index 035246b4ff18..5e8049bb22c9 100644 --- a/crates/storage/libmdbx-rs/src/transaction.rs +++ b/crates/storage/libmdbx-rs/src/transaction.rs @@ -523,27 +523,35 @@ impl Transaction { #[derive(Debug, Clone)] pub(crate) struct TransactionPtr { txn: *mut ffi::MDBX_txn, + #[cfg(feature = "read-tx-timeouts")] timed_out: Arc, lock: Arc>, } impl TransactionPtr { fn new(txn: *mut ffi::MDBX_txn) -> Self { - Self { txn, timed_out: Arc::new(AtomicBool::new(false)), lock: Arc::new(Mutex::new(())) } + Self { + txn, + #[cfg(feature = "read-tx-timeouts")] + timed_out: Arc::new(AtomicBool::new(false)), + lock: Arc::new(Mutex::new(())), + } } - // Returns `true` if the transaction is timed out. - // - // When transaction is timed out via `TxnManager`, it's actually reset using - // `mdbx_txn_reset`. It makes the transaction unusable (MDBX fails on any usages of such - // transactions). - // - // Importantly, we can't rely on `MDBX_TXN_FINISHED` flag to check if the transaction is timed - // out using `mdbx_txn_reset`, because MDBX uses it in other cases too. + /// Returns `true` if the transaction is timed out. + /// + /// When transaction is timed out via `TxnManager`, it's actually reset using + /// `mdbx_txn_reset`. It makes the transaction unusable (MDBX fails on any usages of such + /// transactions). + /// + /// Importantly, we can't rely on `MDBX_TXN_FINISHED` flag to check if the transaction is timed + /// out using `mdbx_txn_reset`, because MDBX uses it in other cases too. + #[cfg(feature = "read-tx-timeouts")] fn is_timed_out(&self) -> bool { self.timed_out.load(std::sync::atomic::Ordering::SeqCst) } + #[cfg(feature = "read-tx-timeouts")] pub(crate) fn set_timed_out(&self) { self.timed_out.store(true, std::sync::atomic::Ordering::SeqCst); } @@ -575,6 +583,7 @@ impl TransactionPtr { // No race condition with the `TxnManager` timing out the transaction is possible here, // because we're taking a lock for any actions on the transaction pointer, including a call // to the `mdbx_txn_reset`. + #[cfg(feature = "read-tx-timeouts")] if self.is_timed_out() { return Err(Error::ReadTransactionTimeout) } @@ -594,6 +603,7 @@ impl TransactionPtr { let _lck = self.lock(); // To be able to do any operations on the transaction, we need to renew it first. + #[cfg(feature = "read-tx-timeouts")] if self.is_timed_out() { mdbx_result(unsafe { mdbx_txn_renew(self.txn) })?; } diff --git a/crates/storage/provider/Cargo.toml b/crates/storage/provider/Cargo.toml index 14c45ca1297b..de2fea7578d9 100644 --- a/crates/storage/provider/Cargo.toml +++ b/crates/storage/provider/Cargo.toml @@ -24,6 +24,7 @@ reth-network-p2p.workspace = true reth-db = { workspace = true, features = ["mdbx"] } reth-db-api.workspace = true reth-prune-types.workspace = true +reth-stages-types.workspace = true reth-trie = { workspace = true, features = ["metrics"] } reth-nippy-jar.workspace = true reth-codecs.workspace = true diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 0fe0eeb6df3b..8b2b7bd6d7dd 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -13,13 +13,13 @@ use reth_db_api::{database::Database, models::StoredBlockBodyIndices}; use reth_errors::{RethError, RethResult}; use reth_evm::ConfigureEvmEnv; use reth_primitives::{ - stage::{StageCheckpoint, StageId}, Address, Block, BlockHash, BlockHashOrNumber, BlockNumber, BlockWithSenders, ChainInfo, ChainSpec, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256, }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; +use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_errors::provider::ProviderResult; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 3e4034f1c0ff..5bab40d6273e 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -32,7 +32,6 @@ use reth_network_p2p::headers::downloader::SyncTarget; use reth_primitives::{ keccak256, revm::{config::revm_spec, env::fill_block_env}, - stage::{StageCheckpoint, StageId}, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockNumber, BlockWithSenders, ChainInfo, ChainSpec, GotExpected, Head, Header, Receipt, Requests, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, StorageEntry, TransactionMeta, @@ -40,6 +39,7 @@ use reth_primitives::{ Withdrawal, Withdrawals, B256, U256, }; use reth_prune_types::{PruneCheckpoint, PruneLimiter, PruneModes, PruneSegment}; +use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_errors::provider::{ProviderResult, RootMismatch}; use reth_trie::{ prefix_set::{PrefixSet, PrefixSetMut, TriePrefixSets}, diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index c1ad67885a16..a8e08be62fed 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -18,13 +18,13 @@ use reth_db_api::{ }; use reth_evm::ConfigureEvmEnv; use reth_primitives::{ - stage::{StageCheckpoint, StageId}, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag, BlockWithSenders, ChainInfo, ChainSpec, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256, }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; +use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_errors::provider::ProviderResult; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ diff --git a/crates/storage/provider/src/providers/static_file/manager.rs b/crates/storage/provider/src/providers/static_file/manager.rs index 9b41bac0924b..f0b4234e3265 100644 --- a/crates/storage/provider/src/providers/static_file/manager.rs +++ b/crates/storage/provider/src/providers/static_file/manager.rs @@ -23,13 +23,13 @@ use reth_db_api::{ use reth_nippy_jar::NippyJar; use reth_primitives::{ keccak256, - stage::{PipelineTarget, StageId}, static_file::{find_fixed_range, HighestStaticFiles, SegmentHeader, SegmentRangeInclusive}, Address, Block, BlockHash, BlockHashOrNumber, BlockNumber, BlockWithSenders, ChainInfo, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, U256, }; +use reth_stages_types::{PipelineTarget, StageId}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use std::{ collections::{hash_map::Entry, BTreeMap, HashMap}, diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 62422a811a9f..ce5e18de45a8 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -9,14 +9,14 @@ use crate::{ use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; use reth_evm::ConfigureEvmEnv; use reth_primitives::{ - proofs::AccountProof, - stage::{StageCheckpoint, StageId}, - Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, BlockWithSenders, - Bytecode, ChainInfo, ChainSpec, Header, Receipt, SealedBlock, SealedBlockWithSenders, - SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned, - TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, MAINNET, U256, + proofs::AccountProof, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, + BlockNumber, BlockWithSenders, Bytecode, ChainInfo, ChainSpec, Header, Receipt, SealedBlock, + SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta, + TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, Withdrawals, B256, + MAINNET, U256, }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; +use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_errors::provider::ProviderResult; use reth_trie::updates::TrieUpdates; use revm::{ diff --git a/crates/storage/storage-api/Cargo.toml b/crates/storage/storage-api/Cargo.toml index d1806408f660..2c6f5bc1460a 100644 --- a/crates/storage/storage-api/Cargo.toml +++ b/crates/storage/storage-api/Cargo.toml @@ -17,6 +17,7 @@ reth-execution-types.workspace = true reth-db-api.workspace = true reth-primitives.workspace = true reth-prune-types.workspace = true +reth-stages-types.workspace = true reth-storage-errors.workspace = true reth-trie.workspace = true diff --git a/crates/storage/storage-api/src/stage_checkpoint.rs b/crates/storage/storage-api/src/stage_checkpoint.rs index 1eca807638db..3815239be2c2 100644 --- a/crates/storage/storage-api/src/stage_checkpoint.rs +++ b/crates/storage/storage-api/src/stage_checkpoint.rs @@ -1,7 +1,5 @@ -use reth_primitives::{ - stage::{StageCheckpoint, StageId}, - BlockNumber, -}; +use reth_primitives::BlockNumber; +use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_errors::provider::ProviderResult; /// The trait for fetching stage checkpoint related data. diff --git a/crates/tasks/src/shutdown.rs b/crates/tasks/src/shutdown.rs index ec63450e6080..918a0cf36a57 100644 --- a/crates/tasks/src/shutdown.rs +++ b/crates/tasks/src/shutdown.rs @@ -13,8 +13,6 @@ use std::{ use tokio::sync::oneshot; /// A Future that resolves when the shutdown event has been fired. -/// -/// The [`TaskManager`](crate) #[derive(Debug)] pub struct GracefulShutdown { shutdown: Shutdown, @@ -25,6 +23,13 @@ impl GracefulShutdown { pub(crate) fn new(shutdown: Shutdown, guard: GracefulShutdownGuard) -> Self { Self { shutdown, guard: Some(guard) } } + + /// Returns a new shutdown future that is ignores the returned [`GracefulShutdownGuard`]. + /// + /// This just maps the return value of the future to `()`, it does not drop the guard. + pub fn ignore_guard(self) -> impl Future + Send + Sync + Unpin + 'static { + self.map(drop) + } } impl Future for GracefulShutdown { diff --git a/crates/trie/trie/Cargo.toml b/crates/trie/trie/Cargo.toml index 665cf51f09ba..99beeff07004 100644 --- a/crates/trie/trie/Cargo.toml +++ b/crates/trie/trie/Cargo.toml @@ -17,6 +17,7 @@ reth-primitives.workspace = true reth-execution-errors.workspace = true reth-db.workspace = true reth-db-api.workspace = true +reth-stages-types.workspace = true reth-trie-types.workspace = true revm.workspace = true diff --git a/crates/trie/trie/src/progress.rs b/crates/trie/trie/src/progress.rs index 916af7f1683f..1594d7f6e084 100644 --- a/crates/trie/trie/src/progress.rs +++ b/crates/trie/trie/src/progress.rs @@ -1,5 +1,6 @@ use crate::{hash_builder::HashBuilder, trie_cursor::CursorSubNode, updates::TrieUpdates}; -use reth_primitives::{stage::MerkleCheckpoint, B256}; +use reth_primitives::B256; +use reth_stages_types::MerkleCheckpoint; /// The progress of the state root computation. #[derive(Debug)] diff --git a/deny.toml b/deny.toml index c6532bbf57aa..4dff1b9ce250 100644 --- a/deny.toml +++ b/deny.toml @@ -89,10 +89,9 @@ unknown-registry = "warn" # in the allow list is encountered unknown-git = "deny" allow-git = [ - # TODO: remove, see ./Cargo.toml + # TODO: Please avoid adding new entries to this list. "https://github.com/alloy-rs/alloy", "https://github.com/foundry-rs/block-explorers", "https://github.com/bluealloy/revm", - "https://github.com/paradigmxyz/evm-inspectors", - "https://github.com/sigp/discv5", + "https://github.com/paradigmxyz/revm-inspectors", ] diff --git a/examples/beacon-api-sidecar-fetcher/Cargo.toml b/examples/beacon-api-sidecar-fetcher/Cargo.toml index 8d7fd39ef70c..3da9788262d3 100644 --- a/examples/beacon-api-sidecar-fetcher/Cargo.toml +++ b/examples/beacon-api-sidecar-fetcher/Cargo.toml @@ -11,10 +11,10 @@ reth-node-ethereum.workspace = true alloy-rpc-types-beacon.workspace = true -serde.workspace = true -serde_json.workspace = true clap.workspace = true -futures-util.workspace = true eyre.workspace = true -thiserror.workspace = true +futures-util.workspace = true reqwest.workspace = true +serde_json.workspace = true +serde.workspace = true +thiserror.workspace = true diff --git a/examples/beacon-api-sse/Cargo.toml b/examples/beacon-api-sse/Cargo.toml index 4582f2598cae..35bc4be0c304 100644 --- a/examples/beacon-api-sse/Cargo.toml +++ b/examples/beacon-api-sse/Cargo.toml @@ -8,10 +8,11 @@ license.workspace = true [dependencies] reth.workspace = true reth-node-ethereum.workspace = true + alloy-rpc-types-beacon.workspace = true clap.workspace = true -tracing.workspace = true futures-util.workspace = true +mev-share-sse = { version = "0.3.0", default-features = false } tokio = { workspace = true, features = ["time"] } -mev-share-sse = { version = "0.2.0" , default-features = false } \ No newline at end of file +tracing.workspace = true diff --git a/examples/exex/in-memory-state/Cargo.toml b/examples/exex/in-memory-state/Cargo.toml index c7fd34ea59ed..a7ae5baee5d5 100644 --- a/examples/exex/in-memory-state/Cargo.toml +++ b/examples/exex/in-memory-state/Cargo.toml @@ -13,3 +13,9 @@ reth-node-ethereum.workspace = true reth-tracing.workspace = true eyre.workspace = true + +[dev-dependencies] +reth-exex-test-utils.workspace = true +reth-testing-utils.workspace = true + +tokio.workspace = true diff --git a/examples/exex/in-memory-state/src/main.rs b/examples/exex/in-memory-state/src/main.rs index 21c8fae858ea..4362e2b65a1d 100644 --- a/examples/exex/in-memory-state/src/main.rs +++ b/examples/exex/in-memory-state/src/main.rs @@ -5,45 +5,145 @@ use reth_exex::{ExExContext, ExExEvent, ExExNotification}; use reth_node_api::FullNodeComponents; use reth_node_ethereum::EthereumNode; use reth_tracing::tracing::info; +use std::{ + future::Future, + pin::Pin, + task::{ready, Context, Poll}, +}; /// An ExEx that keeps track of the entire state in memory -async fn track_state(mut ctx: ExExContext) -> eyre::Result<()> { - // keeps the entire plain execution outcome of the chain in memory - let mut execution_outcome = ExecutionOutcome::default(); - - while let Some(notification) = ctx.notifications.recv().await { - match ¬ification { - ExExNotification::ChainCommitted { new } => { - info!(committed_chain = ?new.range(), "Received commit"); - } - ExExNotification::ChainReorged { old, new } => { - // revert to block before the reorg - execution_outcome.revert_to(new.first().number - 1); - info!(from_chain = ?old.range(), to_chain = ?new.range(), "Received reorg"); - } - ExExNotification::ChainReverted { old } => { - execution_outcome.revert_to(old.first().number - 1); - info!(reverted_chain = ?old.range(), "Received revert"); - } - }; +struct InMemoryStateExEx { + /// The context of the ExEx + ctx: ExExContext, + /// Entire plain state of the chain + state: BundleStateWithReceipts, +} + +impl InMemoryStateExEx { + /// Create a new instance of the ExEx + fn new(ctx: ExExContext) -> Self { + Self { ctx, state: BundleStateWithReceipts::default() } + } +} - if let Some(committed_chain) = notification.committed_chain() { - // extend the execution outcome with the new chain - execution_outcome.extend(committed_chain.execution_outcome().clone()); - ctx.events.send(ExExEvent::FinishedHeight(committed_chain.tip().number))?; +impl Future for InMemoryStateExEx { + type Output = eyre::Result<()>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.get_mut(); + + while let Some(notification) = ready!(this.ctx.notifications.poll_recv(cx)) { + match ¬ification { + ExExNotification::ChainCommitted { new } => { + info!(committed_chain = ?new.range(), "Received commit"); + } + ExExNotification::ChainReorged { old, new } => { + // revert to block before the reorg + this.state.revert_to(new.first().number - 1); + info!(from_chain = ?old.range(), to_chain = ?new.range(), "Received reorg"); + } + ExExNotification::ChainReverted { old } => { + this.state.revert_to(old.first().number - 1); + info!(reverted_chain = ?old.range(), "Received revert"); + } + }; + + if let Some(committed_chain) = notification.committed_chain() { + // extend the state with the new chain + this.state.extend(committed_chain.state().clone()); + this.ctx.events.send(ExExEvent::FinishedHeight(committed_chain.tip().number))?; + } } + + Poll::Ready(Ok(())) } - Ok(()) } fn main() -> eyre::Result<()> { reth::cli::Cli::parse_args().run(|builder, _| async move { let handle = builder .node(EthereumNode::default()) - .install_exex("in-memory-state", |ctx| async move { Ok(track_state(ctx)) }) + .install_exex("in-memory-state", |ctx| async move { Ok(InMemoryStateExEx::new(ctx)) }) .launch() .await?; handle.wait_for_node_exit().await }) } + +#[cfg(test)] +mod tests { + use std::pin::pin; + + use reth::{ + providers::{BundleStateWithReceipts, Chain}, + revm::db::BundleState, + }; + use reth_exex_test_utils::{test_exex_context, PollOnce}; + use reth_testing_utils::generators::{self, random_block, random_receipt}; + + #[tokio::test] + async fn test_exex() -> eyre::Result<()> { + let mut rng = &mut generators::rng(); + + let (ctx, handle) = test_exex_context().await?; + let mut exex = pin!(super::InMemoryStateExEx::new(ctx)); + + let mut expected_state = BundleStateWithReceipts::default(); + + // Generate first block and its state + let block_1 = random_block(&mut rng, 0, None, Some(1), None) + .seal_with_senders() + .ok_or(eyre::eyre!("failed to recover senders"))?; + let block_number_1 = block_1.number; + let state_1 = BundleStateWithReceipts::new( + BundleState::default(), + vec![random_receipt(&mut rng, &block_1.body[0], None)].into(), + block_1.number, + vec![], + ); + // Extend the expected state with the first block + expected_state.extend(state_1.clone()); + + // Send a notification to the Execution Extension that the chain with the first block has + // been committed + handle.send_notification_chain_committed(Chain::new(vec![block_1], state_1, None)).await?; + exex.poll_once().await?; + + // Assert that the state of the first block has been added to the total state + assert_eq!(exex.as_mut().state, expected_state); + + // Generate second block and its state + let block_2 = random_block(&mut rng, 1, None, Some(2), None) + .seal_with_senders() + .ok_or(eyre::eyre!("failed to recover senders"))?; + let state_2 = BundleStateWithReceipts::new( + BundleState::default(), + vec![random_receipt(&mut rng, &block_2.body[0], None)].into(), + block_2.number, + vec![], + ); + // Extend the expected state with the second block + expected_state.extend(state_2.clone()); + + // Send a notification to the Execution Extension that the chain with the second block has + // been committed + let chain_2 = Chain::new(vec![block_2], state_2, None); + handle.send_notification_chain_committed(chain_2.clone()).await?; + exex.poll_once().await?; + + // Assert that the state of the second block has been added to the total state + assert_eq!(exex.as_mut().state, expected_state); + + // Send a notification to the Execution Extension that the chain with the second block has + // been reverted + handle.send_notification_chain_reverted(chain_2).await?; + exex.poll_once().await?; + + // Assert that the state of the second block has been reverted + expected_state.revert_to(block_number_1); + assert_eq!(exex.as_mut().state, expected_state); + + Ok(()) + } +}