diff --git a/Cargo.lock b/Cargo.lock index d1daec56a1..05da312241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ff99651d46cef43767b5e8262ea228cd05287409ccb0c947cc25e70a952f9" +checksum = "3ac62771adeba3957d5612481cce02e99c3faa2c62f4fc0539fa22e023bb58ec" dependencies = [ "alloy-eips", "alloy-primitives", @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0701b0eda8051a2398591113e7862f807ccdd3315d0b441f06c2a0865a379b" +checksum = "e3a8d617f7ccd3d93d44c7e30a9a3bfae209883b9c59a4b91b9168066742a888" dependencies = [ "alloy-consensus", "alloy-eips", @@ -164,9 +164,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c83c7a3c4e1151e8cac383d0a67ddf358f37e5ea51c95a1283d897c9de0a5a" +checksum = "f7b80d98a1e93bc7437fdf2cee6bbb27adb2623db96790d5fdab646fab2ceb63" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -262,9 +262,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def1626eea28d48c6cc0a6f16f34d4af0001906e4f889df6c660b39c86fd044d" +checksum = "fc41cef32ed4225d5ce5429d17acd9cfe0bf7cf1bc206571c78e6985486a2da7" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -311,9 +311,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55d9d1aba3f914f0e8db9e4616ae37f3d811426d95bdccf44e47d0605ab202f6" +checksum = "2c4e42af8ba0d266565a185cb7249509049edc95a719761fd1f939079f6fbd65" dependencies = [ "alloy-eips", "alloy-primitives", @@ -365,9 +365,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57586581f2008933241d16c3e3f633168b3a5d2738c5c42ea5246ec5e0ef17a" +checksum = "e4239d7a1dd9e6c2ee7c126681bfb14e96ba62492f7870e3a1340ecd9eb507d7" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -380,9 +380,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b36c2a0ed74e48851f78415ca5b465211bd678891ba11e88fee09eac534bab1" +checksum = "d8db418e7a3664e44f17888dae0deab83815e69ff0c3035e786a8227190a580e" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -406,9 +406,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636c8051da58802e757b76c3b65af610b95799f72423dc955737dec73de234fd" +checksum = "e0c122ad8fe501326e73786f3bc778fbe9399a48513a0657e4ba33a60a5d502a" dependencies = [ "alloy-consensus", "alloy-eips", @@ -484,9 +484,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3dd56e2eafe8b1803e325867ac2c8a4c73c9fb5f341ffd8347f9344458c5922" +checksum = "02e853a33d674476c2d9305c4f0ce2aadee2e473b51168fd0bcd2cb2cdd66343" dependencies = [ "alloy-chains", "alloy-consensus", @@ -529,9 +529,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eebf54983d4fccea08053c218ee5c288adf2e660095a243d0532a8070b43955" +checksum = "8626237b5b2665e18bc6a35a547ec2ea41712c1d7e060d96ce1cb3222a64ac66" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -573,9 +573,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91577235d341a1bdbee30a463655d08504408a4d51e9f72edbfc5a622829f402" +checksum = "8f3cfcfec14d694e3201c760a25c5c080bc37ef5f7edf21132b26e79f067d67b" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -599,9 +599,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cff039bf01a17d76c0aace3a3a773d5f895eb4c68baaae729ec9da9e86c99c" +checksum = "80a879af27313f5b97ff61674aa36c2b5ea092d932a27d089e00aa4d858b04c2" dependencies = [ "alloy-primitives", "alloy-rpc-types-engine", @@ -612,9 +612,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-admin" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "564afceae126df73b95f78c81eb46e2ef689a45ace0fcdaf5c9a178693a5ccca" +checksum = "4311dcd4777732fc4b1b29963563c98e24d1bd8a9d03ce5d412efc289e320662" dependencies = [ "alloy-genesis", "alloy-primitives", @@ -624,9 +624,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22250cf438b6a3926de67683c08163bfa1fd1efa47ee9512cbcd631b6b0243c" +checksum = "e26eac56a2908a0b847f4606c3e519e9fd576a571aee929d0a74222bd01e9e01" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73234a141ecce14e2989748c04fcac23deee67a445e2c4c167cfb42d4dacd1b6" +checksum = "f375243e3ce50309b52bc5516cf9ec29235259357b58783c251d06f4679621cf" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -647,9 +647,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625af0c3ebd3c31322edb1fb6b8e3e518acc39e164ed07e422eaff05310ff2fa" +checksum = "08e69e48ea882b9f852e34a34c80440d8300f418fb9b41bf321de915d5d75a75" dependencies = [ "alloy-eips", "alloy-primitives", @@ -667,9 +667,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779f70ab16a77e305571881b07a9bc6b0068ae6f962497baf5762825c5b839fb" +checksum = "2c55187c9162b8f2bcddc444046b50a227029af89876ab6e5db2c600a3a989b7" dependencies = [ "alloy-primitives", "derive_more", @@ -679,9 +679,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10620d600cc46538f613c561ac9a923843c6c74c61f054828dcdb8dd18c72ec4" +checksum = "622934088b592f05ef3870d67ec37689ee402f5900a0a730b37dbcaaf9c31eaf" dependencies = [ "alloy-consensus", "alloy-eips", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "010e101dbebe0c678248907a2545b574a87d078d82c2f6f5d0e8e7c9a6149a10" +checksum = "544d4b49ed745cf9b712b7b244a176752149ee7a82dcf84c90eb64dfeea64e43" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -722,9 +722,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-mev" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375e4bf001135fe4f344db6197fafed8c2b61e99fa14d3597f44cd413f79e45b" +checksum = "9437141664df8a0643054340c337d3f99cedbdaaa490d11f2b6a94824465e56f" dependencies = [ "alloy-consensus", "alloy-eips", @@ -737,9 +737,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be096f74d85e1f927580b398bf7bc5b4aa62326f149680ec0867e3c040c9aced" +checksum = "cbcf0a427056ee12d9fd713c17275526e52e806d866d613169bc2f67f40d7432" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -751,9 +751,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14ab75189fbc29c5dd6f0bc1529bccef7b00773b458763f4d9d81a77ae4a1a2d" +checksum = "d9da21a07fa522597ef6cb339594cbb7420f82794f9ddc3ed715ab2bda0de03b" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -763,9 +763,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e6d631f8b975229361d8af7b2c749af31c73b3cf1352f90e144ddb06227105e" +checksum = "e7da7b302b464e666856fefaed3f85a3cfb8ba73df064e6ca4abbd8809f9a816" dependencies = [ "alloy-primitives", "arbitrary", @@ -775,9 +775,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97f40010b5e8f79b70bf163b38cd15f529b18ca88c4427c0e43441ee54e4ed82" +checksum = "aaedc76636029c936f2374824d1c0c24b9041e7a496e1c984755c6ad99cf098b" dependencies = [ "alloy-primitives", "async-trait", @@ -790,9 +790,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c4ec1cc27473819399a3f0da83bc1cef0ceaac8c1c93997696e46dc74377a58" +checksum = "2884f4d92e9f2e97a78e15c7d251502b0fbd162c20c8fa69babcfc0e39e17c38" dependencies = [ "alloy-consensus", "alloy-network", @@ -879,9 +879,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a03bb3f02b9a7ab23dacd1822fa7f69aa5c8eefcdcf57fad085e0b8d76fb4334" +checksum = "d9f745ea15b72fdf80f9788a56dfeffa0a418c4aa555f712e1de3d926bc95aef" dependencies = [ "alloy-json-rpc", "auto_impl", @@ -902,9 +902,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce599598ef8ebe067f3627509358d9faaa1ef94f77f834a7783cd44209ef55c" +checksum = "2219ca0a55410886f0b2020aa9116290f7d849795f6bde20d0800818b5c98243" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -918,9 +918,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49963a2561ebd439549915ea61efb70a7b13b97500ec16ca507721c9d9957d07" +checksum = "5c854e8092cce775d93f3d587aa76df88dc899089e16e31820964cfa8a41887e" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -938,9 +938,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ed38ea573c6658e0c2745af9d1f1773b1ed83aa59fbd9c286358ad469c3233a" +checksum = "d104c7ff76a1bac3b650eea676ca09fd0d8d5d368eca864de8fe472918a6a22f" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -976,9 +976,9 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.6.3" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397406cf04b11ca2a48e6f81804c70af3f40a36abf648e11dc7416043eb0834d" +checksum = "0b2e24e8235af401185f477c2be85d6dda4386d6bc6e18249198b14252b795df" dependencies = [ "darling 0.21.3", "proc-macro2", @@ -8710,9 +8710,7 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-serde", "arbitrary", - "bincode 1.3.3", "derive_more", - "modular-bitfield", "proptest", "proptest-arbitrary-interop", "rand 0.8.5", diff --git a/Cargo.toml b/Cargo.toml index 3eea7485f3..a570d63e85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -459,33 +459,33 @@ alloy-trie = { version = "0.9.4", default-features = false } alloy-hardforks = "0.4.5" -alloy-consensus = { version = "1.6.3", default-features = false } -alloy-contract = { version = "1.6.3", default-features = false } -alloy-eips = { version = "1.6.3", default-features = false } -alloy-genesis = { version = "1.6.3", default-features = false } -alloy-json-rpc = { version = "1.6.3", default-features = false } -alloy-network = { version = "1.6.3", default-features = false } -alloy-network-primitives = { version = "1.6.3", default-features = false } -alloy-provider = { version = "1.6.3", features = ["reqwest", "debug-api"], default-features = false } -alloy-pubsub = { version = "1.6.3", default-features = false } -alloy-rpc-client = { version = "1.6.3", default-features = false } -alloy-rpc-types = { version = "1.6.3", features = ["eth"], default-features = false } -alloy-rpc-types-admin = { version = "1.6.3", default-features = false } -alloy-rpc-types-anvil = { version = "1.6.3", default-features = false } -alloy-rpc-types-beacon = { version = "1.6.3", default-features = false } -alloy-rpc-types-debug = { version = "1.6.3", default-features = false } -alloy-rpc-types-engine = { version = "1.6.3", default-features = false } -alloy-rpc-types-eth = { version = "1.6.3", default-features = false } -alloy-rpc-types-mev = { version = "1.6.3", default-features = false } -alloy-rpc-types-trace = { version = "1.6.3", default-features = false } -alloy-rpc-types-txpool = { version = "1.6.3", default-features = false } -alloy-serde = { version = "1.6.3", default-features = false } -alloy-signer = { version = "1.6.3", default-features = false } -alloy-signer-local = { version = "1.6.3", default-features = false } -alloy-transport = { version = "1.6.3" } -alloy-transport-http = { version = "1.6.3", features = ["reqwest-rustls-tls"], default-features = false } -alloy-transport-ipc = { version = "1.6.3", default-features = false } -alloy-transport-ws = { version = "1.6.3", default-features = false } +alloy-consensus = { version = "1.7.1", default-features = false } +alloy-contract = { version = "1.7.1", default-features = false } +alloy-eips = { version = "1.7.1", default-features = false } +alloy-genesis = { version = "1.7.1", default-features = false } +alloy-json-rpc = { version = "1.7.1", default-features = false } +alloy-network = { version = "1.7.1", default-features = false } +alloy-network-primitives = { version = "1.7.1", default-features = false } +alloy-provider = { version = "1.7.1", features = ["reqwest", "debug-api"], default-features = false } +alloy-pubsub = { version = "1.7.1", default-features = false } +alloy-rpc-client = { version = "1.7.1", default-features = false } +alloy-rpc-types = { version = "1.7.1", features = ["eth"], default-features = false } +alloy-rpc-types-admin = { version = "1.7.1", default-features = false } +alloy-rpc-types-anvil = { version = "1.7.1", default-features = false } +alloy-rpc-types-beacon = { version = "1.7.1", default-features = false } +alloy-rpc-types-debug = { version = "1.7.1", default-features = false } +alloy-rpc-types-engine = { version = "1.7.1", default-features = false } +alloy-rpc-types-eth = { version = "1.7.1", default-features = false } +alloy-rpc-types-mev = { version = "1.7.1", default-features = false } +alloy-rpc-types-trace = { version = "1.7.1", default-features = false } +alloy-rpc-types-txpool = { version = "1.7.1", default-features = false } +alloy-serde = { version = "1.7.1", default-features = false } +alloy-signer = { version = "1.7.1", default-features = false } +alloy-signer-local = { version = "1.7.1", default-features = false } +alloy-transport = { version = "1.7.1" } +alloy-transport-http = { version = "1.7.1", features = ["reqwest-rustls-tls"], default-features = false } +alloy-transport-ipc = { version = "1.7.1", default-features = false } +alloy-transport-ws = { version = "1.7.1", default-features = false } # op alloy-op-evm = { version = "0.27.2", default-features = false } diff --git a/crates/ethereum/primitives/Cargo.toml b/crates/ethereum/primitives/Cargo.toml index 3bf9e8f3a4..74d1de3e0c 100644 --- a/crates/ethereum/primitives/Cargo.toml +++ b/crates/ethereum/primitives/Cargo.toml @@ -15,35 +15,31 @@ workspace = true # reth reth-codecs = { workspace = true, optional = true } reth-primitives-traits.workspace = true -reth-zstd-compressors = { workspace = true, optional = true } # ethereum alloy-eips = { workspace = true, features = ["k256"] } alloy-primitives.workspace = true alloy-consensus = { workspace = true, features = ["serde"] } -alloy-serde = { workspace = true, optional = true } alloy-rpc-types-eth = { workspace = true, optional = true } -alloy-rlp.workspace = true # misc -arbitrary = { workspace = true, optional = true, features = ["derive"] } -modular-bitfield = { workspace = true, optional = true } serde = { workspace = true, optional = true } -serde_with = { workspace = true, optional = true } [dev-dependencies] +alloy-serde.workspace = true derive_more.workspace = true arbitrary.workspace = true -bincode.workspace = true proptest.workspace = true proptest-arbitrary-interop.workspace = true rand_08.workspace = true rand.workspace = true +alloy-rlp.workspace = true reth-codecs = { workspace = true, features = ["test-utils"] } reth-zstd-compressors.workspace = true secp256k1 = { workspace = true, features = ["rand"] } alloy-consensus = { workspace = true, features = ["serde", "arbitrary"] } serde_json.workspace = true +serde_with.workspace = true [features] default = ["std"] @@ -54,27 +50,24 @@ test-utils = [ std = [ "alloy-consensus/std", "alloy-primitives/std", - "alloy-rlp/std", "reth-primitives-traits/std", - "reth-zstd-compressors?/std", "serde?/std", "alloy-eips/std", - "derive_more/std", - "serde_with?/std", - "secp256k1/std", "alloy-rpc-types-eth?/std", - "alloy-serde?/std", + "alloy-rlp/std", + "alloy-serde/std", + "derive_more/std", + "reth-zstd-compressors/std", + "secp256k1/std", "serde_json/std", + "serde_with/std", ] reth-codec = [ "std", "dep:reth-codecs", - "dep:modular-bitfield", - "dep:reth-zstd-compressors", ] arbitrary = [ "std", - "dep:arbitrary", "alloy-consensus/arbitrary", "alloy-consensus/k256", "alloy-primitives/arbitrary", @@ -82,10 +75,9 @@ arbitrary = [ "reth-primitives-traits/arbitrary", "alloy-eips/arbitrary", "alloy-rpc-types-eth?/arbitrary", - "alloy-serde?/arbitrary", + "alloy-serde/arbitrary", ] serde-bincode-compat = [ - "dep:serde_with", "alloy-consensus/serde-bincode-compat", "alloy-eips/serde-bincode-compat", "reth-primitives-traits/serde-bincode-compat", @@ -93,15 +85,14 @@ serde-bincode-compat = [ ] serde = [ "dep:serde", - "dep:alloy-serde", "alloy-consensus/serde", "alloy-eips/serde", "alloy-primitives/serde", "reth-codecs?/serde", "reth-primitives-traits/serde", - "rand/serde", - "rand_08/serde", - "secp256k1/serde", "alloy-rpc-types-eth?/serde", + "rand_08/serde", + "rand/serde", + "secp256k1/serde", ] rpc = ["dep:alloy-rpc-types-eth"] diff --git a/crates/ethereum/primitives/src/lib.rs b/crates/ethereum/primitives/src/lib.rs index 09e7ef7add..6e8f03aad6 100644 --- a/crates/ethereum/primitives/src/lib.rs +++ b/crates/ethereum/primitives/src/lib.rs @@ -9,7 +9,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(feature = "std"), no_std)] -extern crate alloc; +// Feature-only dep: activated by `reth-codec` feature for downstream consumers. +#[cfg(feature = "reth-codec")] +use reth_codecs as _; mod receipt; pub use receipt::*; @@ -35,8 +37,7 @@ pub type PooledTransactionVariant = /// Bincode-compatible serde implementations. #[cfg(all(feature = "serde", feature = "serde-bincode-compat"))] pub mod serde_bincode_compat { - pub use super::receipt::serde_bincode_compat::*; - pub use alloy_consensus::serde_bincode_compat::transaction::*; + pub use alloy_consensus::serde_bincode_compat::{transaction::*, EthereumReceipt as Receipt}; } /// Type alias for the ethereum block diff --git a/crates/ethereum/primitives/src/receipt.rs b/crates/ethereum/primitives/src/receipt.rs index 8172a5f1bd..f916620f6f 100644 --- a/crates/ethereum/primitives/src/receipt.rs +++ b/crates/ethereum/primitives/src/receipt.rs @@ -1,42 +1,8 @@ -use core::fmt::Debug; - -use alloc::vec::Vec; -use alloy_consensus::{ - Eip2718DecodableReceipt, Eip2718EncodableReceipt, Eip658Value, ReceiptEnvelope, - ReceiptWithBloom, RlpDecodableReceipt, RlpEncodableReceipt, TxReceipt, TxType, Typed2718, -}; -use alloy_eips::eip2718::{Eip2718Error, Eip2718Result, Encodable2718, IsTyped2718}; -use alloy_primitives::{Bloom, Log, B256}; -use alloy_rlp::{BufMut, Decodable, Encodable, Header, RlpDecodable, RlpEncodable}; -use reth_primitives_traits::{proofs::ordered_trie_root_with_encoder, InMemorySize}; - -/// Helper trait alias with requirements for transaction type generic to be used within [`Receipt`]. -pub trait TxTy: - Debug - + Copy - + Eq - + Send - + Sync - + InMemorySize - + Typed2718 - + TryFrom - + Decodable - + 'static -{ -} -impl TxTy for T where - T: Debug - + Copy - + Eq - + Send - + Sync - + InMemorySize - + Typed2718 - + TryFrom - + Decodable - + 'static -{ -} +use alloy_consensus::TxType; +pub use alloy_consensus::{EthereumReceipt, TxTy}; +use alloy_eips::eip2718::Encodable2718; +use alloy_primitives::B256; +use reth_primitives_traits::proofs::ordered_trie_root_with_encoder; /// Raw ethereum receipt. pub type Receipt = EthereumReceipt; @@ -45,528 +11,25 @@ pub type Receipt = EthereumReceipt; /// Receipt representation for RPC. pub type RpcReceipt = EthereumReceipt; -/// Typed ethereum transaction receipt. -/// Receipt containing result of transaction execution. -#[derive(Clone, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[cfg_attr(feature = "reth-codec", reth_codecs::add_arbitrary_tests(compact, rlp))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] -pub struct EthereumReceipt { - /// Receipt type. - #[cfg_attr(feature = "serde", serde(rename = "type"))] - pub tx_type: T, - /// If transaction is executed successfully. - /// - /// This is the `statusCode` - #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity", rename = "status"))] - pub success: bool, - /// Gas used - #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] - pub cumulative_gas_used: u64, - /// Log send from contracts. - pub logs: Vec, +/// Calculates the receipt root for a header for the reference type of [`Receipt`]. +/// +/// NOTE: Prefer `proofs::calculate_receipt_root` if you have log blooms memoized. +pub fn calculate_receipt_root_no_memo(receipts: &[Receipt]) -> B256 { + ordered_trie_root_with_encoder(receipts, |r, buf| { + alloy_consensus::TxReceipt::with_bloom_ref(r).encode_2718(buf) + }) } -#[cfg(feature = "rpc")] -impl Receipt { - /// Converts the logs of the receipt to RPC logs. - pub fn into_rpc( - self, - next_log_index: usize, - meta: alloy_consensus::transaction::TransactionMeta, - ) -> RpcReceipt { - let Self { tx_type, success, cumulative_gas_used, logs } = self; - let logs = alloy_rpc_types_eth::Log::collect_for_receipt(next_log_index, meta, logs); - RpcReceipt { tx_type, success, cumulative_gas_used, logs } - } -} - -impl Receipt { - /// Returns length of RLP-encoded receipt fields with the given [`Bloom`] without an RLP header. - pub fn rlp_encoded_fields_length(&self, bloom: &Bloom) -> usize { - self.success.length() + - self.cumulative_gas_used.length() + - bloom.length() + - self.logs.length() - } - - /// RLP-encodes receipt fields with the given [`Bloom`] without an RLP header. - pub fn rlp_encode_fields(&self, bloom: &Bloom, out: &mut dyn BufMut) { - self.success.encode(out); - self.cumulative_gas_used.encode(out); - bloom.encode(out); - self.logs.encode(out); - } - - /// Returns RLP header for inner encoding. - pub fn rlp_header_inner(&self, bloom: &Bloom) -> Header { - Header { list: true, payload_length: self.rlp_encoded_fields_length(bloom) } - } - - /// RLP-decodes the receipt from the provided buffer. This does not expect a type byte or - /// network header. - pub fn rlp_decode_inner( - buf: &mut &[u8], - tx_type: T, - ) -> alloy_rlp::Result> { - let header = Header::decode(buf)?; - if !header.list { - return Err(alloy_rlp::Error::UnexpectedString); - } - - let remaining = buf.len(); - - let success = Decodable::decode(buf)?; - let cumulative_gas_used = Decodable::decode(buf)?; - let logs_bloom = Decodable::decode(buf)?; - let logs = Decodable::decode(buf)?; - - if buf.len() + header.payload_length != remaining { - return Err(alloy_rlp::Error::UnexpectedLength); - } - - Ok(ReceiptWithBloom { - receipt: Self { cumulative_gas_used, tx_type, success, logs }, - logs_bloom, - }) - } - - /// Calculates the receipt root for a header for the reference type of [Receipt]. - /// - /// NOTE: Prefer `proofs::calculate_receipt_root` if you have log blooms memoized. - pub fn calculate_receipt_root_no_memo(receipts: &[Self]) -> B256 { - ordered_trie_root_with_encoder(receipts, |r, buf| r.with_bloom_ref().encode_2718(buf)) - } -} - -impl Eip2718EncodableReceipt for Receipt { - fn eip2718_encoded_length_with_bloom(&self, bloom: &Bloom) -> usize { - !self.tx_type.is_legacy() as usize + self.rlp_header_inner(bloom).length_with_payload() - } - - fn eip2718_encode_with_bloom(&self, bloom: &Bloom, out: &mut dyn BufMut) { - if !self.tx_type.is_legacy() { - out.put_u8(self.tx_type.ty()); - } - self.rlp_header_inner(bloom).encode(out); - self.rlp_encode_fields(bloom, out); - } -} - -impl Eip2718DecodableReceipt for Receipt { - fn typed_decode_with_bloom(ty: u8, buf: &mut &[u8]) -> Eip2718Result> { - Ok(Self::rlp_decode_inner(buf, T::try_from(ty)?)?) - } - - fn fallback_decode_with_bloom(buf: &mut &[u8]) -> Eip2718Result> { - Ok(Self::rlp_decode_inner(buf, T::try_from(0)?)?) - } -} - -impl RlpEncodableReceipt for Receipt { - fn rlp_encoded_length_with_bloom(&self, bloom: &Bloom) -> usize { - let mut len = self.eip2718_encoded_length_with_bloom(bloom); - if !self.tx_type.is_legacy() { - len += Header { - list: false, - payload_length: self.eip2718_encoded_length_with_bloom(bloom), - } - .length(); - } - - len - } - - fn rlp_encode_with_bloom(&self, bloom: &Bloom, out: &mut dyn BufMut) { - if !self.tx_type.is_legacy() { - Header { list: false, payload_length: self.eip2718_encoded_length_with_bloom(bloom) } - .encode(out); - } - self.eip2718_encode_with_bloom(bloom, out); - } -} - -impl RlpDecodableReceipt for Receipt { - fn rlp_decode_with_bloom(buf: &mut &[u8]) -> alloy_rlp::Result> { - let header_buf = &mut &**buf; - let header = Header::decode(header_buf)?; - - // Legacy receipt, reuse initial buffer without advancing - if header.list { - return Self::rlp_decode_inner(buf, T::try_from(0)?) - } - - // Otherwise, advance the buffer and try decoding type flag followed by receipt - *buf = *header_buf; - - let remaining = buf.len(); - let tx_type = T::decode(buf)?; - let this = Self::rlp_decode_inner(buf, tx_type)?; - - if buf.len() + header.payload_length != remaining { - return Err(alloy_rlp::Error::UnexpectedLength); - } - - Ok(this) - } -} - -impl TxReceipt for EthereumReceipt -where - T: TxTy, - L: Send + Sync + Clone + Debug + Eq + AsRef, -{ - type Log = L; - - fn status_or_post_state(&self) -> Eip658Value { - self.success.into() - } - - fn status(&self) -> bool { - self.success - } - - fn bloom(&self) -> Bloom { - alloy_primitives::logs_bloom(self.logs.iter().map(|l| l.as_ref())) - } - - fn cumulative_gas_used(&self) -> u64 { - self.cumulative_gas_used - } - - fn logs(&self) -> &[L] { - &self.logs - } - - fn into_logs(self) -> Vec { - self.logs - } -} - -impl Typed2718 for Receipt { - fn ty(&self) -> u8 { - self.tx_type.ty() - } -} - -impl IsTyped2718 for Receipt { - fn is_type(type_id: u8) -> bool { - ::is_type(type_id) - } -} - -impl InMemorySize for Receipt { - fn size(&self) -> usize { - size_of::() + self.logs.iter().map(|log| log.size()).sum::() - } -} - -impl From> for Receipt -where - T: Into, -{ - fn from(value: ReceiptEnvelope) -> Self { - let value = value.into_primitives_receipt(); - Self { - tx_type: value.tx_type(), - success: value.is_success(), - cumulative_gas_used: value.cumulative_gas_used(), - logs: value.into_logs(), - } - } -} - -impl From> for alloy_consensus::Receipt { - fn from(value: EthereumReceipt) -> Self { - Self { - status: value.success.into(), - cumulative_gas_used: value.cumulative_gas_used, - logs: value.logs, - } - } -} - -impl From> for ReceiptEnvelope -where - L: Send + Sync + Clone + Debug + Eq + AsRef, -{ - fn from(value: EthereumReceipt) -> Self { - let tx_type = value.tx_type; - let receipt = value.into_with_bloom().map_receipt(Into::into); - match tx_type { - TxType::Legacy => Self::Legacy(receipt), - TxType::Eip2930 => Self::Eip2930(receipt), - TxType::Eip1559 => Self::Eip1559(receipt), - TxType::Eip4844 => Self::Eip4844(receipt), - TxType::Eip7702 => Self::Eip7702(receipt), - } - } -} - -#[cfg(all(feature = "serde", feature = "serde-bincode-compat"))] -pub(super) mod serde_bincode_compat { - use alloc::{borrow::Cow, vec::Vec}; - use alloy_consensus::TxType; - use alloy_eips::eip2718::Eip2718Error; - use alloy_primitives::{Log, U8}; - use core::fmt::Debug; - use serde::{Deserialize, Deserializer, Serialize, Serializer}; - use serde_with::{DeserializeAs, SerializeAs}; - - /// Bincode-compatible [`super::Receipt`] serde implementation. - /// - /// Intended to use with the [`serde_with::serde_as`] macro in the following way: - /// ```rust - /// use alloy_consensus::TxType; - /// use reth_ethereum_primitives::{serde_bincode_compat, Receipt}; - /// use serde::{de::DeserializeOwned, Deserialize, Serialize}; - /// use serde_with::serde_as; - /// - /// #[serde_as] - /// #[derive(Serialize, Deserialize)] - /// struct Data { - /// #[serde_as(as = "serde_bincode_compat::Receipt<'_>")] - /// receipt: Receipt, - /// } - /// ``` - #[derive(Debug, Serialize, Deserialize)] - #[serde(bound(deserialize = "T: TryFrom"))] - pub struct Receipt<'a, T = TxType> { - /// Receipt type. - #[serde(deserialize_with = "deserde_txtype")] - pub tx_type: T, - /// If transaction is executed successfully. - /// - /// This is the `statusCode` - pub success: bool, - /// Gas used - pub cumulative_gas_used: u64, - /// Log send from contracts. - pub logs: Cow<'a, Vec>, - } - - /// Ensures that txtype is deserialized symmetrically as U8 - fn deserde_txtype<'de, D, T>(deserializer: D) -> Result - where - D: Deserializer<'de>, - T: TryFrom, - { - U8::deserialize(deserializer)?.to::().try_into().map_err(serde::de::Error::custom) - } - - impl<'a, T: Copy> From<&'a super::Receipt> for Receipt<'a, T> { - fn from(value: &'a super::Receipt) -> Self { - Self { - tx_type: value.tx_type, - success: value.success, - cumulative_gas_used: value.cumulative_gas_used, - logs: Cow::Borrowed(&value.logs), - } - } - } - - impl<'a, T> From> for super::Receipt { - fn from(value: Receipt<'a, T>) -> Self { - Self { - tx_type: value.tx_type, - success: value.success, - cumulative_gas_used: value.cumulative_gas_used, - logs: value.logs.into_owned(), - } - } - } - - impl SerializeAs> for Receipt<'_, T> { - fn serialize_as(source: &super::Receipt, serializer: S) -> Result - where - S: Serializer, - { - Receipt::<'_>::from(source).serialize(serializer) - } - } - - impl<'de, T: TryFrom> DeserializeAs<'de, super::Receipt> - for Receipt<'de, T> - { - fn deserialize_as(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - Receipt::<'_, T>::deserialize(deserializer).map(Into::into) - } - } - - impl reth_primitives_traits::serde_bincode_compat::SerdeBincodeCompat for super::Receipt - where - T: Copy + Serialize + TryFrom + Debug + 'static, - { - type BincodeRepr<'a> = Receipt<'a, T>; - - fn as_repr(&self) -> Self::BincodeRepr<'_> { - self.into() - } - - fn from_repr(repr: Self::BincodeRepr<'_>) -> Self { - repr.into() - } - } - - #[cfg(test)] - mod tests { - use crate::{receipt::serde_bincode_compat, Receipt}; - use alloy_consensus::TxType; - use arbitrary::Arbitrary; - use rand::Rng; - use serde_with::serde_as; - - #[test] - fn test_receipt_bincode_roundtrip() { - #[serde_as] - #[derive(Debug, PartialEq, Eq)] - #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] - struct Data { - #[serde_as(as = "serde_bincode_compat::Receipt<'_, TxType>")] - receipt: Receipt, - } - - let mut bytes = [0u8; 1024]; - rand::rng().fill(bytes.as_mut_slice()); - let data = Data { - receipt: Receipt::arbitrary(&mut arbitrary::Unstructured::new(&bytes)).unwrap(), - }; - let encoded = bincode::serialize(&data).unwrap(); - let decoded: Data = bincode::deserialize(&encoded).unwrap(); - assert_eq!(decoded, data); - } - } -} - -#[cfg(feature = "reth-codec")] -mod compact { - use super::*; - use reth_codecs::{ - Compact, - __private::{modular_bitfield::prelude::*, Buf}, - }; - - impl Receipt { - #[doc = "Used bytes by [`ReceiptFlags`]"] - pub const fn bitflag_encoded_bytes() -> usize { - 1u8 as usize - } - #[doc = "Unused bits for new fields by [`ReceiptFlags`]"] - pub const fn bitflag_unused_bits() -> usize { - 0u8 as usize - } - } - - #[allow(non_snake_case, unused_parens)] - mod flags { - use super::*; - - #[doc = "Fieldset that facilitates compacting the parent type. Used bytes: 1 | Unused bits: 0"] - #[bitfield] - #[derive(Clone, Copy, Debug, Default)] - pub struct ReceiptFlags { - pub tx_type_len: B2, - pub success_len: B1, - pub cumulative_gas_used_len: B4, - pub __zstd: B1, - } - - impl ReceiptFlags { - #[doc = r" Deserializes this fieldset and returns it, alongside the original slice in an advanced position."] - pub fn from(mut buf: &[u8]) -> (Self, &[u8]) { - (Self::from_bytes([buf.get_u8()]), buf) - } - } - } - - pub use flags::ReceiptFlags; - - impl Compact for Receipt { - fn to_compact(&self, buf: &mut B) -> usize - where - B: reth_codecs::__private::bytes::BufMut + AsMut<[u8]>, - { - let mut flags = ReceiptFlags::default(); - let mut total_length = 0; - let mut buffer = reth_codecs::__private::bytes::BytesMut::new(); - - let tx_type_len = self.tx_type.to_compact(&mut buffer); - flags.set_tx_type_len(tx_type_len as u8); - let success_len = self.success.to_compact(&mut buffer); - flags.set_success_len(success_len as u8); - let cumulative_gas_used_len = self.cumulative_gas_used.to_compact(&mut buffer); - flags.set_cumulative_gas_used_len(cumulative_gas_used_len as u8); - self.logs.to_compact(&mut buffer); - - let zstd = buffer.len() > 7; - if zstd { - flags.set___zstd(1); - } - - let flags = flags.into_bytes(); - total_length += flags.len() + buffer.len(); - buf.put_slice(&flags); - if zstd { - reth_zstd_compressors::with_receipt_compressor(|compressor| { - let compressed = compressor.compress(&buffer).expect("Failed to compress."); - buf.put(compressed.as_slice()); - }); - } else { - buf.put(buffer); - } - total_length - } - - fn from_compact(buf: &[u8], _len: usize) -> (Self, &[u8]) { - let (flags, mut buf) = ReceiptFlags::from(buf); - if flags.__zstd() != 0 { - reth_zstd_compressors::with_receipt_decompressor(|decompressor| { - let decompressed = decompressor.decompress(buf); - let original_buf = buf; - let mut buf: &[u8] = decompressed; - let (tx_type, new_buf) = T::from_compact(buf, flags.tx_type_len() as usize); - buf = new_buf; - let (success, new_buf) = bool::from_compact(buf, flags.success_len() as usize); - buf = new_buf; - let (cumulative_gas_used, new_buf) = - u64::from_compact(buf, flags.cumulative_gas_used_len() as usize); - buf = new_buf; - let (logs, _) = Vec::from_compact(buf, buf.len()); - (Self { tx_type, success, cumulative_gas_used, logs }, original_buf) - }) - } else { - let (tx_type, new_buf) = T::from_compact(buf, flags.tx_type_len() as usize); - buf = new_buf; - let (success, new_buf) = bool::from_compact(buf, flags.success_len() as usize); - buf = new_buf; - let (cumulative_gas_used, new_buf) = - u64::from_compact(buf, flags.cumulative_gas_used_len() as usize); - buf = new_buf; - let (logs, new_buf) = Vec::from_compact(buf, buf.len()); - buf = new_buf; - let obj = Self { tx_type, success, cumulative_gas_used, logs }; - (obj, buf) - } - } - } -} - -#[cfg(feature = "reth-codec")] -pub use compact::*; - #[cfg(test)] mod tests { use super::*; use crate::TransactionSigned; + use alloy_consensus::{ReceiptWithBloom, TxReceipt, TxType}; use alloy_eips::eip2718::Encodable2718; use alloy_primitives::{ - address, b256, bloom, bytes, hex_literal::hex, Address, Bytes, Log, LogData, + address, b256, bloom, bytes, hex_literal::hex, Address, Bloom, Bytes, Log, LogData, }; - use alloy_rlp::Decodable; + use alloy_rlp::{Decodable, Encodable}; use reth_codecs::Compact; use reth_primitives_traits::proofs::{ calculate_receipt_root, calculate_transaction_root, calculate_withdrawals_root, @@ -784,6 +247,8 @@ mod tests { #[test] #[cfg(feature = "rpc")] fn test_receipt_serde() { + use alloy_consensus::ReceiptEnvelope; + let input = r#"{"status":"0x1","cumulativeGasUsed":"0x175cc0e","logs":[{"address":"0xa18b9ca2a78660d44ab38ae72e72b18792ffe413","topics":["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925","0x000000000000000000000000e7e7d8006cbff47bc6ac2dabf592c98e97502708","0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d"],"data":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","blockHash":"0xbf9e6a368a399f996a0f0b27cab4191c028c3c99f5f76ea08a5b70b961475fcb","blockNumber":"0x164b59f","blockTimestamp":"0x68c9a713","transactionHash":"0x533aa9e57865675bb94f41aa2895c0ac81eee69686c77af16149c301e19805f1","transactionIndex":"0x14d","logIndex":"0x238","removed":false}],"logsBloom":"0x00000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000400000040000000000000004000000000000000000000000000000000000000000000020000000000000000000000000080000000000000000000000000200000020000000000000000000000000000000000000000000000000000000000000020000010000000000000000000000000000000000000000000000000000000000000","type":"0x2","transactionHash":"0x533aa9e57865675bb94f41aa2895c0ac81eee69686c77af16149c301e19805f1","transactionIndex":"0x14d","blockHash":"0xbf9e6a368a399f996a0f0b27cab4191c028c3c99f5f76ea08a5b70b961475fcb","blockNumber":"0x164b59f","gasUsed":"0xb607","effectiveGasPrice":"0x4a3ee768","from":"0xe7e7d8006cbff47bc6ac2dabf592c98e97502708","to":"0xa18b9ca2a78660d44ab38ae72e72b18792ffe413","contractAddress":null}"#; let receipt: RpcReceipt = serde_json::from_str(input).unwrap(); let envelope: ReceiptEnvelope = diff --git a/crates/ethereum/primitives/src/transaction.rs b/crates/ethereum/primitives/src/transaction.rs index 45c9075b1d..a575b21b60 100644 --- a/crates/ethereum/primitives/src/transaction.rs +++ b/crates/ethereum/primitives/src/transaction.rs @@ -1,6 +1,8 @@ //! This file contains the legacy reth `TransactionSigned` type that has been replaced with //! alloy's TxEnvelope To test for consistency this is kept +extern crate alloc; + use alloc::vec::Vec; use alloy_consensus::{ transaction::{RlpEcdsaDecodableTx, RlpEcdsaEncodableTx, SignerRecoverable, TxHashRef}, diff --git a/crates/evm/execution-types/src/execution_outcome.rs b/crates/evm/execution-types/src/execution_outcome.rs index 573fee0e5f..333834574e 100644 --- a/crates/evm/execution-types/src/execution_outcome.rs +++ b/crates/evm/execution-types/src/execution_outcome.rs @@ -411,7 +411,7 @@ impl ExecutionOutcome { pub fn ethereum_receipts_root(&self, block_number: BlockNumber) -> Option { self.generic_receipts_root_slow( block_number, - reth_ethereum_primitives::Receipt::calculate_receipt_root_no_memo, + reth_ethereum_primitives::calculate_receipt_root_no_memo, ) } } diff --git a/crates/primitives-traits/src/serde_bincode_compat.rs b/crates/primitives-traits/src/serde_bincode_compat.rs index 5169f945b8..0c9adf16ef 100644 --- a/crates/primitives-traits/src/serde_bincode_compat.rs +++ b/crates/primitives-traits/src/serde_bincode_compat.rs @@ -346,6 +346,18 @@ mod block_bincode { } } + impl super::SerdeBincodeCompat for alloy_consensus::EthereumReceipt { + type BincodeRepr<'a> = alloy_consensus::serde_bincode_compat::EthereumReceipt<'a>; + + fn as_repr(&self) -> Self::BincodeRepr<'_> { + self.into() + } + + fn from_repr(repr: Self::BincodeRepr<'_>) -> Self { + repr.into() + } + } + #[cfg(feature = "op")] impl super::SerdeBincodeCompat for op_alloy_consensus::OpReceipt { type BincodeRepr<'a> = op_alloy_consensus::serde_bincode_compat::OpReceipt<'a>; diff --git a/crates/primitives-traits/src/size.rs b/crates/primitives-traits/src/size.rs index e2343cfb95..ad0e5f9c14 100644 --- a/crates/primitives-traits/src/size.rs +++ b/crates/primitives-traits/src/size.rs @@ -78,6 +78,12 @@ impl InMemorySize for alloy_consensus::Receipt { } } +impl InMemorySize for alloy_consensus::EthereumReceipt { + fn size(&self) -> usize { + core::mem::size_of::() + self.logs.iter().map(|log| log.size()).sum::() + } +} + impl InMemorySize for LogData { fn size(&self) -> usize { self.data.len() + core::mem::size_of_val(self.topics()) diff --git a/crates/rpc/rpc-eth-types/src/receipt.rs b/crates/rpc/rpc-eth-types/src/receipt.rs index 48dbf1e5ad..97e888d7a9 100644 --- a/crates/rpc/rpc-eth-types/src/receipt.rs +++ b/crates/rpc/rpc-eth-types/src/receipt.rs @@ -78,8 +78,24 @@ impl EthReceiptConverter { pub const fn new(chain_spec: Arc) -> Self { Self { chain_spec, - build_rpc_receipt: |receipt, next_log_index, meta| { - receipt.into_rpc(next_log_index, meta).into() + build_rpc_receipt: |receipt: Receipt, next_log_index, meta: TransactionMeta| { + let mut log_index = next_log_index; + receipt + .map_logs(|log| { + let idx = log_index; + log_index += 1; + Log { + inner: log, + block_hash: Some(meta.block_hash), + block_number: Some(meta.block_number), + block_timestamp: Some(meta.timestamp), + transaction_hash: Some(meta.tx_hash), + transaction_index: Some(meta.index), + log_index: Some(idx as u64), + removed: false, + } + }) + .into() }, } } diff --git a/crates/storage/codecs/src/alloy/mod.rs b/crates/storage/codecs/src/alloy/mod.rs index 9081fad098..e75ebef335 100644 --- a/crates/storage/codecs/src/alloy/mod.rs +++ b/crates/storage/codecs/src/alloy/mod.rs @@ -18,6 +18,7 @@ cond_mod!( genesis_account, header, log, + receipt, signature, trie, txkind, diff --git a/crates/storage/codecs/src/alloy/receipt.rs b/crates/storage/codecs/src/alloy/receipt.rs new file mode 100644 index 0000000000..0feb74737e --- /dev/null +++ b/crates/storage/codecs/src/alloy/receipt.rs @@ -0,0 +1,122 @@ +//! Compact implementation for [`AlloyEthereumReceipt`] + +use crate::Compact; +use alloc::vec::Vec; +use alloy_consensus::EthereumReceipt as AlloyEthereumReceipt; +use alloy_primitives::Log; +use bytes::Buf; +use modular_bitfield::prelude::*; + +#[allow(non_snake_case)] +mod flags { + use super::*; + + /// Bitflag fieldset for receipt compact encoding. + /// + /// Used bytes: 1 | Unused bits: 0 + #[bitfield] + #[derive(Clone, Copy, Debug, Default)] + pub struct ReceiptFlags { + pub tx_type_len: B2, + pub success_len: B1, + pub cumulative_gas_used_len: B4, + pub __zstd: B1, + } + + impl ReceiptFlags { + /// Deserializes this fieldset and returns it, alongside the original slice in an advanced + /// position. + pub fn from(mut buf: &[u8]) -> (Self, &[u8]) { + (Self::from_bytes([buf.get_u8()]), buf) + } + } +} + +pub(crate) use flags::ReceiptFlags; + +impl Compact for AlloyEthereumReceipt { + fn to_compact(&self, buf: &mut B) -> usize + where + B: bytes::BufMut + AsMut<[u8]>, + { + let mut flags = ReceiptFlags::default(); + let mut total_length = 0; + let mut buffer = bytes::BytesMut::new(); + + let tx_type_len = self.tx_type.to_compact(&mut buffer); + flags.set_tx_type_len(tx_type_len as u8); + let success_len = self.success.to_compact(&mut buffer); + flags.set_success_len(success_len as u8); + let cumulative_gas_used_len = self.cumulative_gas_used.to_compact(&mut buffer); + flags.set_cumulative_gas_used_len(cumulative_gas_used_len as u8); + self.logs.to_compact(&mut buffer); + + let zstd = buffer.len() > 7; + if zstd { + flags.set___zstd(1); + } + + let flags = flags.into_bytes(); + total_length += flags.len() + buffer.len(); + buf.put_slice(&flags); + if zstd { + reth_zstd_compressors::with_receipt_compressor(|compressor| { + let compressed = compressor.compress(&buffer).expect("Failed to compress."); + buf.put(compressed.as_slice()); + }); + } else { + buf.put(buffer); + } + total_length + } + + fn from_compact(buf: &[u8], _len: usize) -> (Self, &[u8]) { + let (flags, mut buf) = ReceiptFlags::from(buf); + if flags.__zstd() != 0 { + reth_zstd_compressors::with_receipt_decompressor(|decompressor| { + let decompressed = decompressor.decompress(buf); + let original_buf = buf; + let mut buf: &[u8] = decompressed; + let (tx_type, new_buf) = T::from_compact(buf, flags.tx_type_len() as usize); + buf = new_buf; + let (success, new_buf) = bool::from_compact(buf, flags.success_len() as usize); + buf = new_buf; + let (cumulative_gas_used, new_buf) = + u64::from_compact(buf, flags.cumulative_gas_used_len() as usize); + buf = new_buf; + let (logs, _) = Vec::::from_compact(buf, buf.len()); + (Self { tx_type, success, cumulative_gas_used, logs }, original_buf) + }) + } else { + let (tx_type, new_buf) = T::from_compact(buf, flags.tx_type_len() as usize); + buf = new_buf; + let (success, new_buf) = bool::from_compact(buf, flags.success_len() as usize); + buf = new_buf; + let (cumulative_gas_used, new_buf) = + u64::from_compact(buf, flags.cumulative_gas_used_len() as usize); + buf = new_buf; + let (logs, new_buf) = Vec::::from_compact(buf, buf.len()); + buf = new_buf; + let obj = Self { tx_type, success, cumulative_gas_used, logs }; + (obj, buf) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy_consensus::TxType; + use proptest::proptest; + use proptest_arbitrary_interop::arb; + + proptest! { + #[test] + fn roundtrip_receipt(receipt in arb::>()) { + let mut compacted_receipt = Vec::::new(); + let len = receipt.to_compact(&mut compacted_receipt); + let (decoded, _) = AlloyEthereumReceipt::::from_compact(&compacted_receipt, len); + assert_eq!(receipt, decoded) + } + } +} diff --git a/crates/storage/db-api/src/models/mod.rs b/crates/storage/db-api/src/models/mod.rs index 523c17ef43..12e6c46c46 100644 --- a/crates/storage/db-api/src/models/mod.rs +++ b/crates/storage/db-api/src/models/mod.rs @@ -343,7 +343,6 @@ mod tests { assert_eq!(PruneCheckpoint::bitflag_encoded_bytes(), 1); assert_eq!(PruneMode::bitflag_encoded_bytes(), 1); assert_eq!(PruneSegment::bitflag_encoded_bytes(), 1); - assert_eq!(Receipt::bitflag_encoded_bytes(), 1); assert_eq!(StageCheckpoint::bitflag_encoded_bytes(), 1); assert_eq!(StageUnitCheckpoint::bitflag_encoded_bytes(), 1); assert_eq!(StoredBlockBodyIndices::bitflag_encoded_bytes(), 1); @@ -363,7 +362,6 @@ mod tests { validate_bitflag_backwards_compat!(PruneCheckpoint, UnusedBits::NotZero); validate_bitflag_backwards_compat!(PruneMode, UnusedBits::Zero); validate_bitflag_backwards_compat!(PruneSegment, UnusedBits::Zero); - validate_bitflag_backwards_compat!(Receipt, UnusedBits::Zero); validate_bitflag_backwards_compat!(StageCheckpoint, UnusedBits::NotZero); validate_bitflag_backwards_compat!(StageUnitCheckpoint, UnusedBits::Zero); validate_bitflag_backwards_compat!(StoredBlockBodyIndices, UnusedBits::Zero);