Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

state: Refactor compute_new_account_address() #575

Merged
merged 2 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions test/state/host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,27 +110,26 @@ bool Host::selfdestruct(const address& addr, const address& beneficiary) noexcep
return !std::exchange(acc.destructed, true);
}

address compute_new_account_address(const evmc_message& msg, uint64_t sender_nonce) noexcept
address compute_new_account_address(const address& sender, uint64_t sender_nonce,
const std::optional<bytes32>& salt, bytes_view init_code) noexcept
{
hash256 addr_base_hash;
if (msg.kind == EVMC_CREATE)
if (!salt.has_value()) // CREATE
{
// TODO: Compute CREATE address without using RLP library.
const auto rlp_list = rlp::encode_tuple(address{msg.sender}, sender_nonce);
const auto rlp_list = rlp::encode_tuple(sender, sender_nonce);
addr_base_hash = keccak256(rlp_list);
}
else
else // CREATE2
{
assert(msg.kind == EVMC_CREATE2);
const auto init_code_hash = keccak256({msg.input_data, msg.input_size});
uint8_t buffer[1 + sizeof(msg.sender) + sizeof(msg.create2_salt) + sizeof(init_code_hash)];
const auto init_code_hash = keccak256(init_code);
uint8_t buffer[1 + sizeof(sender) + sizeof(*salt) + sizeof(init_code_hash)];
static_assert(std::size(buffer) == 85);
buffer[0] = 0xff;
std::copy_n(msg.sender.bytes, sizeof(msg.sender), &buffer[1]);
std::copy_n(
msg.create2_salt.bytes, sizeof(msg.create2_salt), &buffer[1 + sizeof(msg.sender)]);
std::copy_n(sender.bytes, sizeof(sender), &buffer[1]);
std::copy_n(salt->bytes, sizeof(salt->bytes), &buffer[1 + sizeof(sender)]);
std::copy_n(init_code_hash.bytes, sizeof(init_code_hash),
&buffer[1 + sizeof(msg.sender) + sizeof(msg.create2_salt)]);
&buffer[1 + sizeof(sender) + sizeof(salt->bytes)]);
addr_base_hash = keccak256({buffer, std::size(buffer)});
}
evmc_address new_addr{};
Expand All @@ -156,7 +155,9 @@ std::optional<evmc_message> Host::prepare_message(evmc_message msg)
// Compute and fill create address.
assert(msg.recipient == address{});
assert(msg.code_address == address{});
msg.recipient = compute_new_account_address(msg, sender_nonce);
msg.recipient = compute_new_account_address(msg.sender, sender_nonce,
(msg.kind == EVMC_CREATE2) ? std::optional{msg.create2_salt} : std::nullopt,
{msg.input_data, msg.input_size});

// By EIP-2929, the access to new created address is never reverted.
access_account(msg.recipient);
Expand Down
11 changes: 9 additions & 2 deletions test/state/host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ inline constexpr size_t max_initcode_size = 2 * max_code_size;
/// Computes the address of to-be-created contract.
///
/// Computes the new account address for the contract creation context
/// as defined by `ADDR()` in Yellow Paper, 7. Contract Creation, (86).
address compute_new_account_address(const evmc_message& msg, uint64_t sender_nonce) noexcept;
/// as defined by 𝐀𝐃𝐃𝐑 in Yellow Paper, 7. Contract Creation, (86).
///
/// @param sender The address of the message sender. YP: 𝑠.
/// @param sender_nonce The sender's nonce before the increase. YP: 𝑛.
/// @param salt The salt for CREATE2. If null, CREATE address is computed. YP: ζ.
/// @param init_code The contract creation init code. Value only affects CREATE2. YP: 𝐢.
/// @return The computed address for CREATE or CREATE2 scheme.
address compute_new_account_address(const address& sender, uint64_t sender_nonce,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have two overloads:

address compute_new_account_address(const evmc_message& msg, uint64_t sender_nonce) noexcept;
address compute_new_account_address(const address& sender, bytes32& salt, bytes_view init_code) noexcept;

The sender_nonce is irrelevant for create2 and this separation makes it clear which values are used in which.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly so that a user don't need to know which overload to select. Now it only needs to provide arguments (sometimes redundantly) and will get the right answer. Non-functional change from what we had.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it still makes sense to separate and I'd aim for that later, but it is debatable.

const std::optional<bytes32>& salt, bytes_view init_code) noexcept;

class Host : public evmc::Host
{
Expand Down
69 changes: 24 additions & 45 deletions test/unittests/state_new_account_address_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,63 +18,42 @@ inline constexpr bytes32 salts[] = {

TEST(state_new_account_address, create)
{
evmc_message msg{};
msg.kind = EVMC_CREATE;

for (const auto& ic : init_codes) // Init-code doesn't affect CREATE.
{
msg.input_data = ic.data();
msg.input_size = ic.size();

msg.sender = senders[0];
EXPECT_EQ(addr(msg, nonces[0]), 0xbd770416a3345f91e4b34576cb804a576fa48eb1_address);
EXPECT_EQ(addr(msg, nonces[3]), 0x1262d73ea59d3a661bf8751d16cf1a5377149e75_address);

msg.sender = senders[1];
EXPECT_EQ(addr(msg, nonces[0]), 0x522b3294e6d06aa25ad0f1b8891242e335d3b459_address);
EXPECT_EQ(addr(msg, nonces[1]), 0x535b3d7a252fa034ed71f0c53ec0c6f784cb64e1_address);
EXPECT_EQ(addr(msg, nonces[2]), 0x09c1ef8f55c61b94e8b92a55d0891d408a991e18_address);
EXPECT_EQ(addr(msg, nonces[3]), 0x001567239734aeadea21023c2a7c0d9bb9ae4af9_address);

msg.sender = senders[2];
EXPECT_EQ(addr(msg, nonces[0]), 0x3cb1045aee4a06f522ea2b69e4f3d21ed3c135d1_address);
EXPECT_EQ(addr(msg, nonces[3]), 0xe1aa03e4a7b6991d69aff8ece53ceafdf347082e_address);

msg.sender = 0xb20a608c624Ca5003905aA834De7156C68b2E1d0_address;
const auto beacon_deposit_address = addr(msg, 0);
auto s = senders[0];
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0xbd770416a3345f91e4b34576cb804a576fa48eb1_address);
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0x1262d73ea59d3a661bf8751d16cf1a5377149e75_address);

s = senders[1];
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0x522b3294e6d06aa25ad0f1b8891242e335d3b459_address);
EXPECT_EQ(addr(s, nonces[1], {}, ic), 0x535b3d7a252fa034ed71f0c53ec0c6f784cb64e1_address);
EXPECT_EQ(addr(s, nonces[2], {}, ic), 0x09c1ef8f55c61b94e8b92a55d0891d408a991e18_address);
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0x001567239734aeadea21023c2a7c0d9bb9ae4af9_address);

s = senders[2];
EXPECT_EQ(addr(s, nonces[0], {}, ic), 0x3cb1045aee4a06f522ea2b69e4f3d21ed3c135d1_address);
EXPECT_EQ(addr(s, nonces[3], {}, ic), 0xe1aa03e4a7b6991d69aff8ece53ceafdf347082e_address);

const auto beacon_deposit_address =
addr(0xb20a608c624Ca5003905aA834De7156C68b2E1d0_address, 0, {}, ic);
EXPECT_EQ(beacon_deposit_address, 0x00000000219ab540356cbb839cbe05303d7705fa_address);
}
}

TEST(state_new_account_address, create2)
{
evmc_message msg{};
msg.kind = EVMC_CREATE2;

for (const auto n : nonces) // Nonce doesn't affect CREATE2.
{
msg.sender = senders[0];
msg.input_data = init_codes[0].data();
msg.input_size = init_codes[0].size();
msg.create2_salt = salts[0];
EXPECT_EQ(addr(msg, n), 0xe33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0_address);
EXPECT_EQ(addr(senders[0], n, salts[0], init_codes[0]),
0xe33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0_address);

msg.sender = senders[2];
msg.input_data = init_codes[1].data();
msg.input_size = init_codes[1].size();
msg.create2_salt = salts[0];
EXPECT_EQ(addr(msg, n), 0x3517dea701ed18fc4a99dc111c5946e1f1541dad_address);
EXPECT_EQ(addr(senders[2], n, salts[0], init_codes[1]),
0x3517dea701ed18fc4a99dc111c5946e1f1541dad_address);

msg.sender = senders[1];
msg.input_data = init_codes[0].data();
msg.input_size = init_codes[0].size();
msg.create2_salt = salts[1];
EXPECT_EQ(addr(msg, n), 0x7be1c1cb3b8298f21c56add66defce03e2d32604_address);
EXPECT_EQ(addr(senders[1], n, salts[1], init_codes[0]),
0x7be1c1cb3b8298f21c56add66defce03e2d32604_address);

msg.sender = senders[2];
msg.input_data = init_codes[1].data();
msg.input_size = init_codes[1].size();
msg.create2_salt = salts[1];
EXPECT_EQ(addr(msg, n), 0x8f459e65c8f00a9c0c0493de7b0c61c3c27f7384_address);
EXPECT_EQ(addr(senders[2], n, salts[1], init_codes[1]),
0x8f459e65c8f00a9c0c0493de7b0c61c3c27f7384_address);
}
}