2018-08-30 15:38:14 +00:00
|
|
|
// EVMC: Ethereum Client-VM Connector API
|
2018-08-21 07:44:18 +00:00
|
|
|
// Copyright 2018 The EVMC Authors.
|
2018-08-22 11:57:25 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
2018-04-10 22:37:03 +00:00
|
|
|
|
2018-08-30 16:16:15 +00:00
|
|
|
#include "../../examples/example_host.h"
|
2018-04-10 22:37:03 +00:00
|
|
|
#include "vmtester.hpp"
|
|
|
|
|
2018-08-13 16:42:20 +00:00
|
|
|
#include <evmc/helpers.h>
|
|
|
|
|
2018-08-27 14:33:16 +00:00
|
|
|
#include <array>
|
2018-04-17 09:11:07 +00:00
|
|
|
#include <cstring>
|
|
|
|
|
2018-04-17 09:05:54 +00:00
|
|
|
// Compile time checks:
|
|
|
|
|
2018-09-06 22:08:13 +00:00
|
|
|
static_assert(sizeof(evmc_bytes32) == 32, "evmc_bytes32 is too big");
|
2018-04-17 09:05:54 +00:00
|
|
|
static_assert(sizeof(evmc_address) == 20, "evmc_address is too big");
|
2018-06-25 14:02:24 +00:00
|
|
|
static_assert(sizeof(evmc_result) <= 64, "evmc_result does not fit cache line");
|
2018-04-17 09:05:54 +00:00
|
|
|
static_assert(sizeof(evmc_instance) <= 64, "evmc_instance does not fit cache line");
|
2018-09-03 14:32:16 +00:00
|
|
|
static_assert(offsetof(evmc_message, value) % 8 == 0, "evmc_message.value not aligned");
|
2018-04-17 09:05:54 +00:00
|
|
|
|
|
|
|
// Check enums match int size.
|
|
|
|
// On GCC/clang the underlying type should be unsigned int, on MSVC int
|
2018-05-11 11:24:33 +00:00
|
|
|
static_assert(sizeof(evmc_call_kind) == sizeof(int),
|
|
|
|
"Enum `evmc_call_kind` is not the size of int");
|
2018-04-17 09:05:54 +00:00
|
|
|
static_assert(sizeof(evmc_revision) == sizeof(int), "Enum `evmc_revision` is not the size of int");
|
|
|
|
|
|
|
|
static constexpr size_t optionalDataSize =
|
|
|
|
sizeof(evmc_result) - offsetof(evmc_result, create_address);
|
2018-08-13 16:42:20 +00:00
|
|
|
static_assert(optionalDataSize == sizeof(evmc_result_optional_storage), "");
|
2018-04-17 09:05:54 +00:00
|
|
|
|
2018-08-28 14:42:30 +00:00
|
|
|
|
2018-04-10 22:37:03 +00:00
|
|
|
TEST_F(evmc_vm_test, abi_version_match)
|
|
|
|
{
|
|
|
|
ASSERT_EQ(vm->abi_version, EVMC_ABI_VERSION);
|
|
|
|
}
|
|
|
|
|
2018-08-27 14:33:16 +00:00
|
|
|
TEST_F(evmc_vm_test, execute)
|
|
|
|
{
|
2018-08-30 13:15:39 +00:00
|
|
|
evmc_context* context = example_host_create_context();
|
2018-08-27 14:33:16 +00:00
|
|
|
evmc_message msg{};
|
|
|
|
std::array<uint8_t, 2> code = {{0xfe, 0x00}};
|
|
|
|
|
|
|
|
evmc_result result =
|
2019-01-18 13:17:19 +00:00
|
|
|
vm->execute(vm, context, EVMC_MAX_REVISION, &msg, code.data(), code.size());
|
2018-08-27 14:33:16 +00:00
|
|
|
|
|
|
|
// Validate some constraints
|
|
|
|
if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_REVERT)
|
2018-08-29 20:56:55 +00:00
|
|
|
{
|
2018-08-27 14:33:16 +00:00
|
|
|
EXPECT_EQ(result.gas_left, 0);
|
2018-08-29 20:56:55 +00:00
|
|
|
}
|
2018-08-27 14:33:16 +00:00
|
|
|
|
|
|
|
if (result.output_data == NULL)
|
2018-08-29 20:56:55 +00:00
|
|
|
{
|
2018-08-27 14:33:16 +00:00
|
|
|
EXPECT_EQ(result.output_size, 0);
|
2018-08-29 20:56:55 +00:00
|
|
|
}
|
2018-08-27 14:33:16 +00:00
|
|
|
|
|
|
|
if (result.release)
|
|
|
|
result.release(&result);
|
2018-08-30 13:15:39 +00:00
|
|
|
|
|
|
|
example_host_destroy_context(context);
|
2018-08-27 14:33:16 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 13:44:59 +00:00
|
|
|
TEST_F(evmc_vm_test, set_option_unknown_name)
|
2018-04-10 22:37:03 +00:00
|
|
|
{
|
|
|
|
if (vm->set_option)
|
|
|
|
{
|
2018-09-06 13:44:59 +00:00
|
|
|
evmc_set_option_result r = vm->set_option(vm, "unknown_option_csk9twq", "v");
|
2018-09-05 17:24:02 +00:00
|
|
|
EXPECT_EQ(r, EVMC_SET_OPTION_INVALID_NAME);
|
2018-04-10 22:37:03 +00:00
|
|
|
r = vm->set_option(vm, "unknown_option_csk9twq", "x");
|
2018-09-05 17:24:02 +00:00
|
|
|
EXPECT_EQ(r, EVMC_SET_OPTION_INVALID_NAME);
|
2018-04-10 22:37:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(evmc_vm_test, set_option_empty_value)
|
|
|
|
{
|
|
|
|
if (vm->set_option)
|
|
|
|
{
|
2018-09-06 13:44:59 +00:00
|
|
|
evmc_set_option_result r = vm->set_option(vm, "unknown_option_csk9twq", nullptr);
|
2018-09-05 17:24:02 +00:00
|
|
|
EXPECT_EQ(r, EVMC_SET_OPTION_INVALID_NAME);
|
2018-04-10 22:37:03 +00:00
|
|
|
}
|
2018-04-17 09:11:07 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 13:44:59 +00:00
|
|
|
TEST_F(evmc_vm_test, set_option_unknown_value)
|
|
|
|
{
|
|
|
|
auto r = evmc_set_option(vm, "verbose", "1");
|
|
|
|
|
|
|
|
// Execute more tests if the VM supports "verbose" option.
|
|
|
|
if (r != EVMC_SET_OPTION_INVALID_NAME)
|
|
|
|
{
|
|
|
|
// The VM supports "verbose" option. Try dummy value for it.
|
|
|
|
auto r2 = evmc_set_option(vm, "verbose", "GjNOONsbUl");
|
|
|
|
EXPECT_EQ(r2, EVMC_SET_OPTION_INVALID_VALUE);
|
|
|
|
|
|
|
|
// For null the behavior should be the same.
|
|
|
|
auto r3 = evmc_set_option(vm, "verbose", nullptr);
|
|
|
|
EXPECT_EQ(r3, EVMC_SET_OPTION_INVALID_VALUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 09:11:07 +00:00
|
|
|
TEST_F(evmc_vm_test, name)
|
|
|
|
{
|
|
|
|
ASSERT_NE(vm->name, nullptr);
|
|
|
|
EXPECT_GT(std::strlen(vm->name), 0) << "VM name cannot be empty";
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(evmc_vm_test, version)
|
|
|
|
{
|
|
|
|
ASSERT_NE(vm->version, nullptr);
|
|
|
|
EXPECT_GT(std::strlen(vm->version), 0) << "VM name cannot be empty";
|
2018-06-18 12:18:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(evmc_vm_test, set_tracer)
|
|
|
|
{
|
2018-07-25 16:17:06 +00:00
|
|
|
static const auto tracer_callback = [](evmc_tracer_context*, size_t, evmc_status_code, int64_t,
|
|
|
|
size_t, const evmc_uint256be*, size_t, size_t, size_t,
|
|
|
|
const uint8_t*) noexcept {};
|
2018-06-18 12:22:16 +00:00
|
|
|
if (vm->set_tracer)
|
|
|
|
vm->set_tracer(vm, tracer_callback, nullptr);
|
2018-06-18 12:18:39 +00:00
|
|
|
}
|
2018-09-08 16:23:27 +00:00
|
|
|
|
|
|
|
TEST_F(evmc_vm_test, capabilities)
|
|
|
|
{
|
|
|
|
// The VM should have at least one of EVM1 or EWASM capabilities.
|
|
|
|
EXPECT_TRUE(evmc_vm_has_capability(vm, EVMC_CAPABILITY_EVM1) ||
|
|
|
|
evmc_vm_has_capability(vm, EVMC_CAPABILITY_EWASM));
|
|
|
|
}
|