From 4d2ac8f2727d30541f9adf1a504c16a60bdfd4a9 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 21 Aug 2023 18:05:15 +0200 Subject: [PATCH] state: Properly use `cumulative_gas_used` in receipt encoding --- test/state/state.cpp | 5 +++-- test/state/state.hpp | 12 ++++++++++++ test/t8n/t8n.cpp | 1 + test/unittests/state_mpt_hash_test.cpp | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/test/state/state.cpp b/test/state/state.cpp index 77e4014eb0..13a2eae40f 100644 --- a/test/state/state.cpp +++ b/test/state/state.cpp @@ -212,7 +212,8 @@ std::variant transition(State& state, const std::erase_if(state.get_accounts(), [](const std::pair& p) noexcept { return p.second.destructed; }); - auto receipt = TransactionReceipt{tx.type, result.status_code, gas_used, host.take_logs(), {}}; + // Cumulative gas used is unknown in this scope. + TransactionReceipt receipt{tx.type, result.status_code, gas_used, {}, host.take_logs(), {}, {}}; // Cannot put it into constructor call because logs are std::moved from host instance. receipt.logs_bloom_filter = compute_bloom_filter(receipt.logs); @@ -275,7 +276,7 @@ std::variant transition(State& state, const { const auto prefix = receipt.type == Transaction::Type::eip1559 ? bytes{0x02} : bytes{}; return prefix + rlp::encode_tuple(receipt.status == EVMC_SUCCESS, - static_cast(receipt.gas_used), + static_cast(receipt.cumulative_gas_used), bytes_view(receipt.logs_bloom_filter), receipt.logs); } diff --git a/test/state/state.hpp b/test/state/state.hpp index 51de86880c..22d9d15627 100644 --- a/test/state/state.hpp +++ b/test/state/state.hpp @@ -134,11 +134,23 @@ struct Log std::vector topics; }; +/// Transaction Receipt +/// +/// This struct is used in two contexts: +/// 1. As the formally specified, RLP-encode transaction receipt included in the Ethereum blocks. +/// 2. As the internal representation of the transaction execution result. +/// These both roles share most, but not all the information. There are some fields that cannot be assigned in the single transaction execution context. There are also fields that are not a part of the RLP-encoded transaction receipts. +/// TODO: Consider splitting the struct into two based on the duality explained above. struct TransactionReceipt { Transaction::Type type = Transaction::Type::legacy; evmc_status_code status = EVMC_INTERNAL_ERROR; + + /// Amount of gas used by this transaction. int64_t gas_used = 0; + + /// Amount of gas used by this and previous transactions in the block. + int64_t cumulative_gas_used = 0; std::vector logs; BloomFilter logs_bloom_filter; }; diff --git a/test/t8n/t8n.cpp b/test/t8n/t8n.cpp index c96dbecf47..2ab753d54c 100644 --- a/test/t8n/t8n.cpp +++ b/test/t8n/t8n.cpp @@ -145,6 +145,7 @@ int main(int argc, const char* argv[]) j_receipt["transactionHash"] = hex0x(computed_tx_hash); j_receipt["gasUsed"] = hex0x(static_cast(receipt.gas_used)); cumulative_gas_used += receipt.gas_used; + receipt.cumulative_gas_used = cumulative_gas_used; 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 2a7d952cac..5fa1ec0c3e 100644 --- a/test/unittests/state_mpt_hash_test.cpp +++ b/test/unittests/state_mpt_hash_test.cpp @@ -188,7 +188,7 @@ TEST(state_mpt_hash, legacy_and_eip1559_receipt_three_logs_no_logs) TransactionReceipt receipt0{}; receipt0.type = evmone::state::Transaction::Type::legacy; receipt0.status = EVMC_SUCCESS; - receipt0.gas_used = 0x24522; + receipt0.cumulative_gas_used = 0x24522; Log l0; l0.addr = 0x84bf5c35c54a994c72ff9d8b4cca8f5034153a2c_address; @@ -238,7 +238,7 @@ TEST(state_mpt_hash, legacy_and_eip1559_receipt_three_logs_no_logs) TransactionReceipt receipt1{}; receipt1.type = evmone::state::Transaction::Type::eip1559; receipt1.status = EVMC_SUCCESS; - receipt1.gas_used = 0x2cd9b; + receipt1.cumulative_gas_used = 0x2cd9b; receipt1.logs_bloom_filter = compute_bloom_filter(receipt1.logs); EXPECT_EQ(mpt_hash(std::array{receipt0, receipt1}),