Skip to content

Drop evmc::bytes alias, migrate internal byte_string usage to std types#2215

Draft
Baltoli wants to merge 4 commits intomainfrom
bruce/byte-string-drop-evmc-alias
Draft

Drop evmc::bytes alias, migrate internal byte_string usage to std types#2215
Baltoli wants to merge 4 commits intomainfrom
bruce/byte-string-drop-evmc-alias

Conversation

@Baltoli
Copy link
Copy Markdown
Contributor

@Baltoli Baltoli commented Apr 20, 2026

Summary

Third step in removing evmc types from internal code, following daa26346c (bytes32_t) and 3b2f1247e (Address).

  • Redefine monad::byte_string / byte_string_view as std::basic_string<uint8_t> / std::basic_string_view<uint8_t> in category/core/byte_string.hpp and drop the <evmc/bytes.hpp> include. Previously these were using-aliases for evmc::bytes / evmc::bytes_view.
  • Migrate call sites that stayed purely within monad-owned types: delegation.{hpp,cpp}, precompiles_test's internal test_case struct, test_validation's Transaction.data, reserve_balance_contract_test.

evmone state-API boundary

evmc::bytes uses a custom char_traits (evmc::byte_traits) that zero-initializes storage — it is not std::basic_string<uint8_t> with default traits. The new monad::byte_string is therefore a distinct type and does not implicitly convert.

evmone's TestState, StateDiff::Entry, and MockedAccount all store code as evmc::bytes, and evmone::baseline::analyze takes evmc::bytes_view. Tests that set up evmone state or invoke evmone APIs continue to use evmc::bytes directly (data_tests.cpp, fixture.cpp, evm_fixture.hpp, micro_benchmarks/main.cpp, fuzzer.cpp). Replacing those would require either mirroring evmc::byte_traits in monad or modifying the evmone fork, neither of which is in scope here.

Net: 31 evmc::bytes/bytes_view occurrences → 7 remaining, all at the evmone boundary.

Test plan

  • GCC 15 / gcc-avx2 toolchain build passes (cmake --build build --parallel)
  • ctest --test-dir build passes
  • /format and /lint clean

🤖 Generated with Claude Code

Third step in removing evmc types from internal code (following
daa2634 bytes32_t and 3b2f124 Address).

Redefine monad::byte_string / byte_string_view as
std::basic_string<uint8_t> / std::basic_string_view<uint8_t>,
dropping the <evmc/bytes.hpp> include from category/core/byte_string.hpp.
Previously these were using-aliases for evmc::bytes / evmc::bytes_view.

Call sites that stayed purely within monad-owned types are migrated
to the new names (delegation, precompiles_test's internal test_case
struct, test_validation's Transaction.data, reserve_balance_contract_test).

evmc::bytes / bytes_view usage is preserved at the evmone state-API
boundary. evmc::bytes uses a custom char_traits (evmc::byte_traits)
that zero-initializes storage; the std-typed monad::byte_string is
a distinct type and will not implicitly convert. evmone's TestState,
StateDiff::Entry, and MockedAccount all store code as evmc::bytes, and
evmone::baseline::analyze takes evmc::bytes_view, so tests that set up
evmone state or invoke evmone APIs continue to use evmc::bytes directly
(data_tests.cpp, fixture.cpp, evm_fixture.hpp, micro_benchmarks/main.cpp,
fuzzer.cpp). Replacing these would require either mirroring
evmc::byte_traits in monad or modifying the evmone fork, neither of
which is in scope here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Baltoli Baltoli force-pushed the bruce/byte-string-drop-evmc-alias branch from d1f7077 to 436a79c Compare April 20, 2026 15:39
Baltoli and others added 3 commits April 20, 2026 11:51
The sole remaining evmc::literals reference was in do_proposal, where
evmc::literals::parse<bytes32_t>(input) was used to decode a CLI-supplied
block id. Replace with monad::from_hex<bytes32_t>(input).value_or(bytes32_t{}),
which integrates with the existing "is zero?" check to report malformed
input rather than terminating on it (the former parse path called
std::terminate via std::optional::value() on bad hex).

This completes the removal of evmc::literals references from internal
code; monad::literals already provides _bytes32 / _address equivalents.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The uint256_be_t alias (bytes32_t, inheriting from evmc_bytes32) was
introduced in daa2634 but not rolled out at all call sites. Migrate
the three remaining internal usages:

- EvmcHostBase::get_balance body: intx::be::store<uint256_be_t>(...)
  (the declared virtual return type stays evmc::uint256be to match
  the evmc::Host base-class contract; uint256_be_t implicitly slices
  to evmc_bytes32 for the return)
- execution_benchmarks: intx::be::store<monad::uint256_be_t>(tx.value)
  when building an evmc_message
- evmc_host_test: uint256_be_t{10'000'000u} for block_prev_randao

evmc::uint256be usage remaining is limited to the evmc::Host virtual
signatures (evmc_host.hpp:75, evmc_host.cpp:73) and one VM test that
overrides evmc::Host mocks directly (monad_vm_interface_tests.cpp);
both are base-class contracts we can't change without modifying the
evmc fork.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The runtime bridge code (SLOAD/SSTORE, TLOAD/TSTORE, LOG0..4, CALL,
CREATE, CREATE2) was round-tripping monad::bytes32_t through an
evmc::bytes32 temporary before passing to the evmc_host_interface C
callbacks:

    bytes32_t  ─(slice)─▶  evmc_bytes32  ─(wrap)─▶  evmc::bytes32
                                                         │
                     evmc_bytes32*  ◀─(pointer upcast)───┘

The middle wrapping step buys nothing: bytes32_t already inherits from
evmc_bytes32, and taking &bytes32_t upcasts directly to the
evmc_bytes32* the host callbacks take. Assigning a bytes32_t to an
evmc_message field of type evmc_bytes32 slices to the base with no
conversion needed.

Drop ~22 static_cast<evmc::bytes32>/static_cast<bytes32_t> calls across
storage.{hpp,cpp}, log.cpp, call.cpp, create.cpp, and change
log_impl's parameter from std::span<evmc::bytes32 const> to
std::span<bytes32_t const>. No behavior change; these were purely
textual.

Remaining evmc:: usage in category/vm/runtime/ is limited to
evmc::Result (RAII wrapper over evmc_result), which is a load-bearing
return type and out of scope here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant