From 70f083fdca49eba1ead4ee833fa4b76b8f8e5956 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 21 Aug 2023 18:11:58 +0200 Subject: [PATCH] state: Support pre-Byzantium receipt format --- test/state/state.cpp | 23 ++++++++++++++--- test/state/state.hpp | 3 +++ test/t8n/t8n.cpp | 2 ++ test/unittests/state_mpt_hash_test.cpp | 35 ++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/test/state/state.cpp b/test/state/state.cpp index 13a2eae40f..150ba9214c 100644 --- a/test/state/state.cpp +++ b/test/state/state.cpp @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "state.hpp" +#include "../utils/stdx/utility.hpp" #include "errors.hpp" #include "host.hpp" #include "rlp.hpp" @@ -274,10 +275,24 @@ std::variant transition(State& state, const [[nodiscard]] bytes rlp_encode(const TransactionReceipt& receipt) { - const auto prefix = receipt.type == Transaction::Type::eip1559 ? bytes{0x02} : bytes{}; - return prefix + rlp::encode_tuple(receipt.status == EVMC_SUCCESS, - static_cast(receipt.cumulative_gas_used), - bytes_view(receipt.logs_bloom_filter), receipt.logs); + if (receipt.post_state.has_value()) + { + assert(receipt.type == Transaction::Type::legacy); + + return rlp::encode_tuple(receipt.post_state.value(), + static_cast(receipt.cumulative_gas_used), + bytes_view(receipt.logs_bloom_filter), receipt.logs); + } + else + { + const auto prefix = receipt.type == Transaction::Type::legacy ? + bytes{} : + bytes{stdx::to_underlying(receipt.type)}; + + return prefix + rlp::encode_tuple(receipt.status == EVMC_SUCCESS, + static_cast(receipt.cumulative_gas_used), + bytes_view(receipt.logs_bloom_filter), receipt.logs); + } } } // namespace evmone::state diff --git a/test/state/state.hpp b/test/state/state.hpp index 75409d699b..8cb9571a7a 100644 --- a/test/state/state.hpp +++ b/test/state/state.hpp @@ -155,6 +155,9 @@ struct TransactionReceipt int64_t cumulative_gas_used = 0; std::vector logs; BloomFilter logs_bloom_filter; + + /// Root hash of the state after this transaction. Used only in old pre-Byzantium transactions. + std::optional post_state; }; /// Finalize state after applying a "block" of transactions. diff --git a/test/t8n/t8n.cpp b/test/t8n/t8n.cpp index 2ab753d54c..80e15d1531 100644 --- a/test/t8n/t8n.cpp +++ b/test/t8n/t8n.cpp @@ -146,6 +146,8 @@ int main(int argc, const char* argv[]) j_receipt["gasUsed"] = hex0x(static_cast(receipt.gas_used)); cumulative_gas_used += receipt.gas_used; receipt.cumulative_gas_used = cumulative_gas_used; + if (rev < EVMC_BYZANTIUM) + receipt.post_state = state::mpt_hash(state.get_accounts()); j_receipt["cumulativeGasUsed"] = hex0x(cumulative_gas_used); j_receipt["blockHash"] = hex0x(bytes32{}); diff --git a/test/unittests/state_mpt_hash_test.cpp b/test/unittests/state_mpt_hash_test.cpp index 5fa1ec0c3e..b7c1728cf6 100644 --- a/test/unittests/state_mpt_hash_test.cpp +++ b/test/unittests/state_mpt_hash_test.cpp @@ -244,3 +244,38 @@ TEST(state_mpt_hash, legacy_and_eip1559_receipt_three_logs_no_logs) EXPECT_EQ(mpt_hash(std::array{receipt0, receipt1}), 0x7199a3a86010634dc205a1cdd6ec609f70b954167583cb3acb6a2e3057916016_bytes32); } + +TEST(state_mpt_hash, pre_byzantium_receipt) +{ + // Block taken from Ethereum mainnet + // https://etherscan.io/txs?block=4276370 + + using namespace evmone::state; + + TransactionReceipt receipt0{ + .type = Transaction::Type::legacy, + .cumulative_gas_used = 0x8323, + .logs = {}, + .logs_bloom_filter = compute_bloom_filter(receipt0.logs), + .post_state = 0x4a8f9db452b100f9ec85830785b2d1744c3e727561c334c4f18022daa113290a_bytes32, + }; + + TransactionReceipt receipt1{ + .type = Transaction::Type::legacy, + .cumulative_gas_used = 0x10646, + .logs = {}, + .logs_bloom_filter = compute_bloom_filter(receipt1.logs), + .post_state = 0xb14ab7c32b3e126591731850976a15e2359c1f3628f1b0ff37776c210b9cadb8_bytes32, + }; + + TransactionReceipt receipt2{ + .type = Transaction::Type::legacy, + .cumulative_gas_used = 0x1584e, + .logs = {}, + .logs_bloom_filter = compute_bloom_filter(receipt2.logs), + .post_state = 0x7bda915deb201cae321d31028d322877e8fb98264db3ffcbfec7ea7b9b2106b1_bytes32, + }; + + EXPECT_EQ(mpt_hash(std::array{receipt0, receipt1, receipt2}), + 0x8a4fa43a95939b06ad13ce8cd08e026ae6e79ea3c5fc80c732d252e2769ce778_bytes32); +}