Skip to content

Commit

Permalink
Clarify evmc_message::code_address usage
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Sep 7, 2021
1 parent 54bf895 commit f3b9d78
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 21 deletions.
10 changes: 5 additions & 5 deletions examples/example_precompiles_vm/example_precompiles_vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ static evmc_result execute(evmc_vm*,
{
// The EIP-1352 (https://eips.ethereum.org/EIPS/eip-1352) defines
// the range 0 - 0xffff (2 bytes) of addresses reserved for precompiled contracts.
// Check if the destination address is within the reserved range.
// Check if the code address is within the reserved range.

constexpr auto prefix_size = sizeof(evmc_address) - 2;
const auto& dst = msg->destination;
const auto& addr = msg->code_address;
// Check if the address prefix is all zeros.
if (std::any_of(&dst.bytes[0], &dst.bytes[prefix_size], [](uint8_t x) { return x != 0; }))
if (std::any_of(&addr.bytes[0], &addr.bytes[prefix_size], [](uint8_t x) { return x != 0; }))
{
// If not, reject the execution request.
auto result = evmc_result{};
result.status_code = EVMC_REJECTED;
return result;
}

// Extract the precompiled contract id from last 2 bytes of the destination address.
const auto id = (dst.bytes[prefix_size] << 8) | dst.bytes[prefix_size + 1];
// Extract the precompiled contract id from last 2 bytes of the code address.
const auto id = (addr.bytes[prefix_size] << 8) | addr.bytes[prefix_size + 1];
switch (id)
{
case 0x0001: // ECDSARECOVER
Expand Down
54 changes: 44 additions & 10 deletions include/evmc/evmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ enum evmc_flags
};

/**
* The message describing an EVM call,
* including a zero-depth calls from a transaction origin.
* The message describing an EVM call, including a zero-depth calls from a transaction origin.
*
* Most of the fields are modelled by the section 8. Message Call of the Ethereum Yellow Paper.
*/
struct evmc_message
{
Expand All @@ -103,21 +104,48 @@ struct evmc_message
*/
uint32_t flags;

/** The call depth. */
/**
* The present depth of the message call stack.
*
* Defined as `e` in the Yellow Paper.
*/
int32_t depth;

/** The amount of gas for message execution. */
/**
* The amount of gas available to the message execution.
*
* Defined as `g` in the Yellow Paper.
*/
int64_t gas;

/** The destination (recipient) of the message. */
/**
* The recipient of the message.
*
* This is the address of the account which storage/balance/nonce is going to be modified
* by the message execution. In case of ::EVMC_CALL, this is also the account where the
* message value evmc_message::value is going to be transferred.
* For ::EVMC_CALLCODE or ::EVMC_DELEGATECALL, this may be different from
* the evmc_message::code_address.
*
* Defined as `r` in the Yellow Paper.
*/
evmc_address destination;

/** The sender of the message. */
/**
* The sender of the message.
*
* The address of the sender of a message call defined as `s` in the Yellow Paper.
* This must be the message recipient of the message at the previous (lower) depth,
* except for the ::EVMC_DELEGATECALL where recipient is the 2 levels above the present depth.
* At the depth 0 this must be the transaction origin.
*/
evmc_address sender;

/**
* The message input data.
*
* The arbitrary length byte array of the input data of the call,
* defined as `d` in the Yellow Paper.
* This MAY be NULL.
*/
const uint8_t* input_data;
Expand All @@ -131,6 +159,9 @@ struct evmc_message

/**
* The amount of Ether transferred with the message.
*
* This is transferred value for ::EVMC_CALL or apparent value for ::EVMC_DELEGATECALL.
* Defined as `v` or `v~` in the Yellow Paper.
*/
evmc_uint256be value;

Expand All @@ -145,12 +176,15 @@ struct evmc_message
/**
* The address of the code to be executed.
*
* May be different from the evmc_message::destination (recipient) in case of
* ::EVMC_CALLCODE or ::EVMC_DELEGATECALL.
* See Section 8 "Message Call" of the Yellow Paper for detail.
*
* For ::EVMC_CALLCODE or ::EVMC_DELEGATECALL this may be different from
* the evmc_message::destination (recipient).
* Not required when invoking evmc_execute_fn(), only when invoking evmc_call_fn().
* Ignored if kind is ::EVMC_CREATE or ::EVMC_CREATE2.
*
* In case of ::EVMC_CAPABILITY_PRECOMPILES implementation, this fields should be inspected
* to identify the requested precompile.
*
* Defined as `c` in the Yellow Paper.
*/
evmc_address code_address;
};
Expand Down
2 changes: 1 addition & 1 deletion test/unittests/cpp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ TEST(cpp, vm_execute_precompiles)
constexpr std::array<uint8_t, 3> input{{1, 2, 3}};

evmc_message msg{};
msg.destination.bytes[19] = 4; // Call Identify precompile at address 0x4.
msg.code_address.bytes[19] = 4; // Call Identify precompile at address 0x4.
msg.input_data = input.data();
msg.input_size = input.size();
msg.gas = 18;
Expand Down
10 changes: 5 additions & 5 deletions tools/vmtester/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,21 +174,21 @@ TEST_F(evmc_vm_test, precompile_test)
// Iterate every address (as per EIP-1352)
for (size_t i = 0; i < 0xffff; i++)
{
auto destination = evmc_address{};
destination.bytes[18] = static_cast<uint8_t>(i >> 8);
destination.bytes[19] = static_cast<uint8_t>(i & 0xff);
auto addr = evmc_address{};
addr.bytes[18] = static_cast<uint8_t>(i >> 8);
addr.bytes[19] = static_cast<uint8_t>(i & 0xff);

evmc_message msg{EVMC_CALL,
0,
0,
65536,
destination,
evmc_address{},
evmc_address{},
nullptr,
0,
evmc_uint256be{},
evmc_bytes32{},
evmc_address{}};
addr};

evmc_result result = vm->execute(vm, nullptr, nullptr, EVMC_MAX_REVISION, &msg, nullptr, 0);

Expand Down

0 comments on commit f3b9d78

Please sign in to comment.