From d2b9dc28417e9d14de92ae47dd9ea0402c02596a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 18 Oct 2024 11:43:33 +0200 Subject: [PATCH] state: Implement `CREATE` address without RLP lib Remove Host's dependency on RLP library by re-implementing `compute_create_address()`. Closes https://github.com/ethereum/evmone/issues/783. --- test/state/host.cpp | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/test/state/host.cpp b/test/state/host.cpp index a227d09142..975ef16617 100644 --- a/test/state/host.cpp +++ b/test/state/host.cpp @@ -4,7 +4,6 @@ #include "host.hpp" #include "precompiles.hpp" -#include "rlp.hpp" #include #include @@ -179,11 +178,35 @@ bool Host::selfdestruct(const address& addr, const address& beneficiary) noexcep address compute_create_address(const address& sender, uint64_t sender_nonce) noexcept { - // TODO: Compute CREATE address without using RLP library. - const auto rlp_list = rlp::encode_tuple(sender, sender_nonce); - const auto base_hash = keccak256(rlp_list); + static constexpr auto RLP_STR_BASE = 0x80; + static constexpr auto RLP_LIST_BASE = 0xc0; + static constexpr auto ADDRESS_SIZE = sizeof(sender); + static constexpr std::ptrdiff_t MAX_NONCE_SIZE = sizeof(sender_nonce); + + uint8_t buffer[ADDRESS_SIZE + MAX_NONCE_SIZE + 3]; // 3 for RLP prefix bytes. + auto p = &buffer[1]; // Skip RLP list prefix for now. + *p++ = RLP_STR_BASE + ADDRESS_SIZE; // Set RLP string prefix for address. + p = std::copy_n(sender.bytes, ADDRESS_SIZE, p); + + if (sender_nonce < RLP_STR_BASE) // Short integer encoding including 0 as empty string (0x80). + { + *p++ = sender_nonce != 0 ? static_cast(sender_nonce) : RLP_STR_BASE; + } + else // Prefixed integer encoding. + { + // TODO: bit_width returns int after [LWG 3656](https://cplusplus.github.io/LWG/issue3656). + const auto num_nonzero_bytes = static_cast((std::bit_width(sender_nonce) + 7) / 8); + *p++ = static_cast(RLP_STR_BASE + num_nonzero_bytes); + intx::be::unsafe::store(p, sender_nonce); + p = std::shift_left(p, p + MAX_NONCE_SIZE, MAX_NONCE_SIZE - num_nonzero_bytes); + } + + const auto total_size = static_cast(p - buffer); + buffer[0] = static_cast(RLP_LIST_BASE + (total_size - 1)); // Set the RLP list prefix. + + const auto base_hash = keccak256({buffer, total_size}); address addr; - std::copy_n(&base_hash.bytes[sizeof(base_hash) - sizeof(addr)], sizeof(addr), addr.bytes); + std::copy_n(&base_hash.bytes[sizeof(base_hash) - ADDRESS_SIZE], ADDRESS_SIZE, addr.bytes); return addr; }