Skip to content

Commit

Permalink
state: Implement CREATE address without RLP lib
Browse files Browse the repository at this point in the history
Remove Host's dependency on RLP library by re-implementing
`compute_create_address()`.

Closes #783.
  • Loading branch information
chfast committed Oct 18, 2024
1 parent 817cf06 commit 68eba83
Showing 1 changed file with 28 additions and 5 deletions.
33 changes: 28 additions & 5 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "host.hpp"
#include "precompiles.hpp"
#include "rlp.hpp"
#include <evmone/constants.hpp>
#include <evmone/eof.hpp>

Expand Down Expand Up @@ -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<uint8_t>(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<int>((std::bit_width(sender_nonce) + 7) / 8);
*p++ = static_cast<uint8_t>(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<size_t>(p - buffer);
buffer[0] = static_cast<uint8_t>(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;
}

Expand Down

0 comments on commit 68eba83

Please sign in to comment.