mirror of https://github.com/status-im/evmc.git
Merge pull request #187 from ethereum/cpp
Add C++ wrappers/bindings for VM
This commit is contained in:
commit
600143690e
|
@ -1,6 +1,6 @@
|
|||
/* EVMC: Ethereum Client-VM Connector API.
|
||||
* Copyright 2018 The EVMC Authors.
|
||||
* Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
* Copyright 2019 The EVMC Authors.
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
/// @file
|
||||
|
@ -158,6 +158,7 @@ static void set_tracer(struct evmc_instance* instance,
|
|||
|
||||
/// Stringify the argument.
|
||||
#define STR(x) #x
|
||||
#define XSTR(x) STR(x)
|
||||
|
||||
#if !defined(PROJECT_VERSION)
|
||||
/// The dummy project version if not provided by the build system.
|
||||
|
@ -171,7 +172,7 @@ struct evmc_instance* evmc_create_example_vm()
|
|||
struct evmc_instance init = {
|
||||
.abi_version = EVMC_ABI_VERSION,
|
||||
.name = "example_vm",
|
||||
.version = STR(PROJECT_VERSION),
|
||||
.version = XSTR(PROJECT_VERSION),
|
||||
.destroy = destroy,
|
||||
.execute = execute,
|
||||
.get_capabilities = get_capabilities,
|
||||
|
|
|
@ -8,7 +8,15 @@
|
|||
#include <evmc/evmc.h>
|
||||
#include <evmc/utils.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Creates EVMC Example VM.
|
||||
*/
|
||||
EVMC_EXPORT struct evmc_instance* evmc_create_example_vm(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/* EVMC: Ethereum Client-VM Connector API.
|
||||
* Copyright 2019 The EVMC Authors.
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
*/
|
||||
|
||||
/// @file
|
||||
/// EVMC C++ API - wrappers and bindings for C++.
|
||||
|
||||
#include <evmc/evmc.h>
|
||||
#include <evmc/helpers.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
|
||||
namespace evmc
|
||||
{
|
||||
class result : public evmc_result
|
||||
{
|
||||
public:
|
||||
explicit result(evmc_result const& res) noexcept : evmc_result{res} {}
|
||||
|
||||
~result() noexcept
|
||||
{
|
||||
if (release)
|
||||
release(this);
|
||||
}
|
||||
|
||||
result(result&& other) noexcept : evmc_result{other}
|
||||
{
|
||||
// Disable releaser of the rvalue object.
|
||||
other.release = nullptr;
|
||||
}
|
||||
|
||||
result(result const&) = delete;
|
||||
|
||||
result& operator=(result other) noexcept
|
||||
{
|
||||
std::swap(*this, other);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class vm
|
||||
{
|
||||
public:
|
||||
explicit vm(evmc_instance* instance) noexcept : m_instance{instance} {}
|
||||
~vm() noexcept { m_instance->destroy(m_instance); }
|
||||
|
||||
vm(evmc_instance* instance, std::initializer_list<std::pair<const char*, const char*>> options)
|
||||
: m_instance{instance}
|
||||
{
|
||||
for (auto option : options)
|
||||
set_option(option.first, option.second);
|
||||
}
|
||||
|
||||
bool is_abi_compatible() const noexcept { return m_instance->abi_version == EVMC_ABI_VERSION; }
|
||||
|
||||
char const* name() const noexcept { return m_instance->name; }
|
||||
|
||||
char const* version() const noexcept { return m_instance->version; }
|
||||
|
||||
evmc_set_option_result set_option(const char name[], const char value[]) noexcept
|
||||
{
|
||||
return evmc_set_option(m_instance, name, value);
|
||||
}
|
||||
|
||||
result execute(evmc_context& ctx,
|
||||
evmc_revision rev,
|
||||
const evmc_message& msg,
|
||||
const uint8_t* code,
|
||||
size_t code_size) noexcept
|
||||
{
|
||||
return result{m_instance->execute(m_instance, &ctx, rev, &msg, code, code_size)};
|
||||
}
|
||||
|
||||
private:
|
||||
evmc_instance* const m_instance = nullptr;
|
||||
};
|
||||
} // namespace evmc
|
|
@ -1,6 +1,6 @@
|
|||
# EVMC: Ethereum Client-VM Connector API.
|
||||
# Copyright 2018 The EVMC Authors.
|
||||
# Licensed under the Apache License, Version 2.0. See the LICENSE file.
|
||||
# Copyright 2019 The EVMC Authors.
|
||||
# Licensed under the Apache License, Version 2.0.
|
||||
|
||||
add_subdirectory(instructions)
|
||||
add_subdirectory(loader)
|
||||
|
|
|
@ -39,11 +39,12 @@ add_custom_command(
|
|||
|
||||
add_executable(
|
||||
evmc-test
|
||||
test_cpp.cpp
|
||||
test_helpers.cpp
|
||||
test_instructions.cpp
|
||||
test_loader.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(evmc-test PRIVATE instructions loader GTest::gtest GTest::main)
|
||||
target_link_libraries(evmc-test PRIVATE evmc-example-vm instructions loader GTest::gtest GTest::main)
|
||||
set_target_properties(evmc-test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
|
||||
add_dependencies(evmc-test vm-mock)
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// EVMC: Ethereum Client-VM Connector API.
|
||||
// Copyright 2019 The EVMC Authors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
||||
|
||||
#include "../../examples/example_vm.h"
|
||||
|
||||
#include <evmc/evmc.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
TEST(cpp, result)
|
||||
{
|
||||
static int release_called = 0;
|
||||
release_called = 0;
|
||||
|
||||
{
|
||||
EXPECT_EQ(release_called, 0);
|
||||
auto raw_result = evmc_result{};
|
||||
raw_result.output_data = static_cast<uint8_t*>(std::malloc(13));
|
||||
raw_result.release = [](const evmc_result* r) {
|
||||
std::free(const_cast<uint8_t*>(r->output_data));
|
||||
++release_called;
|
||||
};
|
||||
|
||||
auto res1 = evmc::result{raw_result};
|
||||
auto res2 = std::move(res1);
|
||||
|
||||
EXPECT_EQ(release_called, 0);
|
||||
|
||||
[](evmc::result) {}(std::move(res2));
|
||||
|
||||
EXPECT_EQ(release_called, 1);
|
||||
}
|
||||
EXPECT_EQ(release_called, 1);
|
||||
}
|
||||
|
||||
TEST(cpp, vm)
|
||||
{
|
||||
auto vm = evmc::vm{evmc_create_example_vm()};
|
||||
EXPECT_TRUE(vm.is_abi_compatible());
|
||||
|
||||
auto r = vm.set_option("verbose", "3");
|
||||
EXPECT_EQ(r, EVMC_SET_OPTION_SUCCESS);
|
||||
|
||||
EXPECT_EQ(vm.name(), std::string{"example_vm"});
|
||||
EXPECT_NE(vm.version()[0], 0);
|
||||
|
||||
auto ctx = evmc_context{};
|
||||
auto res = vm.execute(ctx, EVMC_MAX_REVISION, {}, nullptr, 0);
|
||||
EXPECT_EQ(res.status_code, EVMC_FAILURE);
|
||||
}
|
||||
|
||||
TEST(cpp, vm_set_option)
|
||||
{
|
||||
evmc_instance raw_instance = {EVMC_ABI_VERSION, "", "", nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr};
|
||||
raw_instance.destroy = [](evmc_instance*) {};
|
||||
|
||||
auto vm = evmc::vm{&raw_instance};
|
||||
EXPECT_EQ(vm.set_option("1", "2"), EVMC_SET_OPTION_INVALID_NAME);
|
||||
}
|
Loading…
Reference in New Issue