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 85bfb7e commit 7080764
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
34 changes: 28 additions & 6 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 @@ -177,13 +176,36 @@ bool Host::selfdestruct(const address& addr, const address& beneficiary) noexcep
return false;
}

address compute_create_address(const address& sender, uint64_t sender_nonce) noexcept
address compute_create_address(const address& sender, uint64_t 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 NONCE_SIZE = sizeof(nonce);

uint8_t buffer[ADDRESS_SIZE + 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 (nonce < RLP_STR_BASE) // Short integer encoding with handling 0 as empty string (0x80).
{
*p++ = nonce != 0 ? static_cast<uint8_t>(nonce) : RLP_STR_BASE;
}
else // Prefixed integer encoding.
{
const auto num_nonzero_bytes = (std::bit_width(nonce) + 7) / 8;
*p++ = static_cast<uint8_t>(RLP_STR_BASE + num_nonzero_bytes);
intx::be::unsafe::store(p, nonce);
p = std::shift_left(p, p + NONCE_SIZE, NONCE_SIZE - num_nonzero_bytes); // Skip zero 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
8 changes: 4 additions & 4 deletions test/state/host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ using evmc::uint256be;
/// or a create transaction.
/// This is defined by 𝐀𝐃𝐃𝐑 in Yellow Paper, 7. Contract Creation, (88-90), the case for ΞΆ = βˆ….
///
/// @param sender The address of the message sender. YP: 𝑠.
/// @param sender_nonce The sender's nonce before the increase. YP: 𝑛.
/// @return The address computed with the CREATE scheme.
[[nodiscard]] address compute_create_address(const address& sender, uint64_t sender_nonce) noexcept;
/// @param sender The address of the message sender. YP: 𝑠.
/// @param nonce The sender's nonce before the increase. YP: 𝑛.
/// @return The address computed with the CREATE scheme.
[[nodiscard]] address compute_create_address(const address& sender, uint64_t nonce) noexcept;

/// Computes the address of to-be-created contract with the CREATE2 / EOFCREATE scheme.
///
Expand Down

0 comments on commit 7080764

Please sign in to comment.