16#include "example_vm.h"
40 delete static_cast<ExampleVM*
>(instance);
55 auto* vm =
static_cast<ExampleVM*
>(instance);
56 if (std::strcmp(name,
"verbose") == 0)
59 return EVMC_SET_OPTION_INVALID_VALUE;
62 auto v = std::strtol(value, &end, 0);
64 return EVMC_SET_OPTION_INVALID_VALUE;
66 return EVMC_SET_OPTION_INVALID_VALUE;
67 vm->verbose =
static_cast<int>(v);
68 return EVMC_SET_OPTION_SUCCESS;
71 return EVMC_SET_OPTION_INVALID_NAME;
91 uint8_t data[1024] = {};
98 uint8_t* expand(uint32_t offset, uint32_t region_size)
100 uint32_t new_size = offset + region_size;
101 if (new_size >
sizeof(data))
107 return &data[offset];
113 bool store(uint32_t offset,
const uint8_t* value_data, uint32_t value_size)
115 uint8_t* p = expand(offset, value_size);
119 std::memcpy(p, value_data, value_size);
128 value.
bytes[31] =
static_cast<uint8_t
>(x);
129 value.
bytes[30] =
static_cast<uint8_t
>(x >> 8);
130 value.
bytes[29] =
static_cast<uint8_t
>(x >> 16);
131 value.
bytes[28] =
static_cast<uint8_t
>(x >> 24);
139 size_t offset =
sizeof(value) -
sizeof(address);
140 std::memcpy(&value.
bytes[offset], address.
bytes,
sizeof(address.
bytes));
147 return (uint32_t{value.
bytes[28]} << 24) | (uint32_t{value.
bytes[29]} << 16) |
148 (uint32_t{value.
bytes[30]} << 8) | (uint32_t{value.
bytes[31]});
155 size_t offset =
sizeof(value) -
sizeof(address);
156 std::memcpy(address.
bytes, &value.
bytes[offset],
sizeof(address.
bytes));
170 auto* vm =
static_cast<ExampleVM*
>(instance);
173 std::puts(
"execution started\n");
175 int64_t gas_left = msg->
gas;
179 for (
size_t pc = 0; pc < code_size; ++pc)
196 uint32_t a = to_uint32(stack.pop());
197 uint32_t b = to_uint32(stack.pop());
198 uint32_t sum = a + b;
199 stack.push(to_uint256(sum));
210 case OP_CALLDATALOAD:
212 uint32_t offset = to_uint32(stack.pop());
215 if (offset < msg->input_size)
217 size_t copy_size = std::min(msg->
input_size - offset,
sizeof(value));
228 to_uint256(
static_cast<uint32_t
>(host->
get_tx_context(context).block_number));
235 uint32_t index = to_uint32(stack.pop());
237 if (!memory.store(index, value.
bytes,
sizeof(value)))
299 size_t num_push_bytes =
size_t{code[pc]} - OP_PUSH1 + 1;
300 size_t offset =
sizeof(value) - num_push_bytes;
301 std::memcpy(&value.
bytes[offset], &code[pc + 1], num_push_bytes);
302 pc += num_push_bytes;
318 call_msg.
gas = to_uint32(stack.pop());
319 call_msg.
recipient = to_address(stack.pop());
320 call_msg.
value = stack.pop();
322 uint32_t call_input_offset = to_uint32(stack.pop());
323 uint32_t call_input_size = to_uint32(stack.pop());
324 call_msg.
input_data = memory.expand(call_input_offset, call_input_size);
327 uint32_t call_output_offset = to_uint32(stack.pop());
328 uint32_t call_output_size = to_uint32(stack.pop());
329 uint8_t* call_output_ptr = memory.expand(call_output_offset, call_output_size);
331 if (call_msg.
input_data ==
nullptr || call_output_ptr ==
nullptr)
340 call_output_size =
static_cast<uint32_t
>(call_result.
output_size);
341 memory.store(call_output_offset, call_result.
output_data, call_output_size);
343 if (call_result.
release !=
nullptr)
344 call_result.
release(&call_result);
350 uint32_t output_offset = to_uint32(stack.pop());
351 uint32_t output_size = to_uint32(stack.pop());
352 uint8_t* output_ptr = memory.expand(output_offset, output_size);
353 if (output_ptr ==
nullptr)
364 uint32_t output_offset = to_uint32(stack.pop());
365 uint32_t output_size = to_uint32(stack.pop());
366 uint8_t* output_ptr = memory.expand(output_offset, output_size);
367 if (output_ptr ==
nullptr)
380#if !defined(PROJECT_VERSION)
382#define PROJECT_VERSION "0.0.0"
386ExampleVM::ExampleVM()
388 ::execute, ::get_capabilities, ::set_option}
394 return new ExampleVM;
evmc_set_option_result
Possible outcomes of evmc_set_option.
evmc_vm * evmc_create_example_vm()
Example of a function creating an instance of an example EVM implementation.
uint32_t evmc_capabilities_flagset
Alias for unsigned integer representing a set of bit flags of EVMC capabilities.
evmc_revision
EVM revision.
@ EVMC_ABI_VERSION
The EVMC ABI version number of the interface declared in this file.
@ EVMC_CAPABILITY_EVM1
The VM is capable of executing EVM1 bytecode.
@ EVMC_UNDEFINED_INSTRUCTION
An undefined instruction has been encountered.
@ EVMC_SUCCESS
Execution finished with success.
@ EVMC_OUT_OF_GAS
The execution has run out of gas.
@ EVMC_FAILURE
Generic execution failure.
@ EVMC_REVERT
Execution terminated with REVERT opcode.
@ EVMC_BYZANTIUM
The Byzantium revision.
static struct evmc_result evmc_make_result(enum evmc_status_code status_code, int64_t gas_left, int64_t gas_refund, const uint8_t *output_data, size_t output_size)
Creates the result from the provided arguments.
Big-endian 160-bit hash suitable for keeping an Ethereum address.
uint8_t bytes[20]
The 20 bytes of the hash.
The fixed size array of 32 bytes.
uint8_t bytes[32]
The 32 bytes.
The opaque data type representing the Host execution context.
evmc_call_fn call
Call callback function.
evmc_get_storage_fn get_storage
Get storage callback function.
evmc_set_storage_fn set_storage
Set storage callback function.
evmc_get_tx_context_fn get_tx_context
Get transaction context callback function.
The message describing an EVM call, including a zero-depth calls from a transaction origin.
const uint8_t * input_data
The message input data.
size_t input_size
The size of the message input data.
evmc_address recipient
The recipient of the message.
evmc_uint256be value
The amount of Ether transferred with the message.
int64_t gas
The amount of gas available to the message execution.
The EVM code execution result.
const uint8_t * output_data
The reference to output data.
enum evmc_status_code status_code
The execution status code.
evmc_release_result_fn release
The method releasing all resources associated with the result object.
size_t output_size
The size of the output data.