Skip to content

Commit

Permalink
eof: Return constant hash of EXTCODEHASH of EOF (#1035)
Browse files Browse the repository at this point in the history
Replace runtime evaluated `keccak256("EF00")` with a constant returned
for an account with EOF code.
  • Loading branch information
chfast authored Sep 30, 2024
2 parents 2cd8bf7 + 02b6951 commit 46dc5ee
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 12 deletions.
13 changes: 5 additions & 8 deletions lib/evmone/eof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include <cassert>
#include <limits>
#include <numeric>
#include <ostream>
#include <queue>
#include <unordered_set>
#include <vector>
Expand All @@ -23,8 +22,6 @@ namespace evmone
{
namespace
{
constexpr uint8_t MAGIC_BYTES[] = {0xef, 0x00};
constexpr bytes_view MAGIC{MAGIC_BYTES, std::size(MAGIC_BYTES)};
constexpr uint8_t TERMINATOR = 0x00;
constexpr uint8_t TYPE_SECTION = 0x01;
constexpr uint8_t CODE_SECTION = 0x02;
Expand All @@ -50,7 +47,7 @@ size_t eof_header_size(const EOFSectionHeaders& headers) noexcept
constexpr auto non_code_section_header_size = 3; // (SECTION_ID + SIZE) per each section
constexpr auto section_size_size = 2;

auto header_size = std::size(MAGIC) + 1 + // 1 version byte
auto header_size = std::size(EOF_MAGIC) + 1 + // 1 version byte
non_code_section_count * non_code_section_header_size +
sizeof(CODE_SECTION) + 2 + code_section_count * section_size_size +
sizeof(TERMINATOR);
Expand Down Expand Up @@ -93,7 +90,7 @@ std::variant<EOFSectionHeaders, EOFValidationError> validate_section_headers(byt
uint16_t section_num = 0;
EOFSectionHeaders section_headers{};
const auto container_end = container.end();
auto it = container.begin() + std::size(MAGIC) + 1; // MAGIC + VERSION
auto it = container.begin() + std::size(EOF_MAGIC) + 1; // MAGIC + VERSION
uint8_t expected_section_id = TYPE_SECTION;
while (it != container_end && state != State::terminated)
{
Expand Down Expand Up @@ -719,7 +716,7 @@ size_t EOF1Header::data_size_position() const noexcept
{
const auto num_code_sections = code_sizes.size();
const auto num_container_sections = container_sizes.size();
return std::size(MAGIC) + 1 + // magic + version
return std::size(EOF_MAGIC) + 1 + // magic + version
3 + // type section kind + size
3 + 2 * num_code_sections + // code sections kind + count + sizes
// container sections kind + count + sizes
Expand All @@ -729,7 +726,7 @@ size_t EOF1Header::data_size_position() const noexcept

bool is_eof_container(bytes_view container) noexcept
{
return container.starts_with(MAGIC);
return container.starts_with(EOF_MAGIC);
}

std::variant<EOF1Header, EOFValidationError> validate_header(
Expand Down Expand Up @@ -806,7 +803,7 @@ std::variant<EOF1Header, EOFValidationError> validate_header(
EOF1Header read_valid_eof1_header(bytes_view container)
{
EOFSectionHeaders section_headers;
auto it = container.begin() + std::size(MAGIC) + 1; // MAGIC + VERSION
auto it = container.begin() + std::size(EOF_MAGIC) + 1; // MAGIC + VERSION
while (*it != TERMINATOR)
{
const auto section_id = *it++;
Expand Down
13 changes: 11 additions & 2 deletions lib/evmone/eof.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,28 @@
#pragma once

#include <evmc/bytes.hpp>
#include <evmc/evmc.h>
#include <evmc/evmc.hpp>
#include <evmc/utils.h>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>
#include <variant>
#include <vector>

namespace evmone
{
using evmc::bytes;
using evmc::bytes_view;
using namespace evmc::literals;

constexpr uint8_t EOF_MAGIC_BYTES[] = {0xef, 0x00};
constexpr bytes_view EOF_MAGIC{EOF_MAGIC_BYTES, std::size(EOF_MAGIC_BYTES)};

/// The value returned by EXTCODEHASH of an address with EOF code.
/// See EIP-3540: https://eips.ethereum.org/EIPS/eip-3540#changes-to-execution-semantics.
static constexpr auto EOF_CODE_HASH_SENTINEL =
0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5_bytes32;

struct EOFCodeType
{
Expand Down
8 changes: 6 additions & 2 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ size_t Host::get_code_size(const address& addr) const noexcept

bytes32 Host::get_code_hash(const address& addr) const noexcept
{
// TODO: Cache code hash. It will be needed also to compute the MPT hash.
const auto* const acc = m_state.find(addr);
return (acc != nullptr && !acc->is_empty()) ? keccak256(extcode(acc->code)) : bytes32{};
if (acc == nullptr || acc->is_empty())
return {};
if (is_eof_container(acc->code))
return EOF_CODE_HASH_SENTINEL;
// TODO: Cache code hash. It will be needed also to compute the MPT hash.
return keccak256(acc->code);
}

size_t Host::copy_code(const address& addr, size_t code_offset, uint8_t* buffer_data,
Expand Down
6 changes: 6 additions & 0 deletions test/unittests/eof_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <evmone/eof.hpp>
#include <gtest/gtest.h>
#include <test/state/hash_utils.hpp>
#include <test/utils/bytecode.hpp>
#include <test/utils/utils.hpp>

Expand Down Expand Up @@ -115,3 +116,8 @@ TEST(eof, get_error_message)
// NOLINTNEXTLINE(*.EnumCastOutOfRange)
EXPECT_EQ(evmone::get_error_message(static_cast<EOFValidationError>(-1)), "<unknown>");
}

TEST(eof, extcodehash_sentinel)
{
EXPECT_EQ(keccak256(EOF_MAGIC), EOF_CODE_HASH_SENTINEL);
}

0 comments on commit 46dc5ee

Please sign in to comment.