Skip to content

Commit

Permalink
Merge pull request #217 from ethereum/cpp-host
Browse files Browse the repository at this point in the history
cpp: Add evmc::host - wrapper around Host context / interface
  • Loading branch information
chfast committed Mar 15, 2019
2 parents 1b5a67c + aa3a81d commit 9608bab
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## [6.2.0] - Unreleased

- Added: [[#217](https://github.com/ethereum/evmc/pull/217)]
The `evmc::host` C++ wrapper for EVMC host context and interface
to be used by VM implementations.
- Deprecated: [[#196](https://github.com/ethereum/evmc/pull/196)]
The `EVMC_CONSTANTINOPLE2` revision name is deprecated, replaced with `EVMC_PETERSBURG`.

Expand Down
88 changes: 88 additions & 0 deletions include/evmc/evmc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,92 @@ class vm
private:
evmc_instance* const m_instance = nullptr;
};


/// Wrapper around EVMC host context / host interface.
class host
{
evmc_context* context = nullptr;
evmc_tx_context tx_context = {};

public:
host(evmc_context* context) noexcept : context{context} {}

bool account_exists(const evmc_address& address) noexcept
{
return context->host->account_exists(context, &address);
}

evmc_bytes32 get_storage(const evmc_address& address, const evmc_bytes32& key) noexcept
{
return context->host->get_storage(context, &address, &key);
}

evmc_storage_status set_storage(const evmc_address& address,
const evmc_bytes32& key,
const evmc_bytes32& value) noexcept
{
return context->host->set_storage(context, &address, &key, &value);
}

evmc_uint256be get_balance(const evmc_address& address) noexcept
{
return context->host->get_balance(context, &address);
}

size_t get_code_size(const evmc_address& address) noexcept
{
return context->host->get_code_size(context, &address);
}

evmc_bytes32 get_code_hash(const evmc_address& address) noexcept
{
return context->host->get_code_hash(context, &address);
}

size_t copy_code(const evmc_address& address,
size_t code_offset,
uint8_t* buffer_data,
size_t buffer_size) noexcept
{
return context->host->copy_code(context, &address, code_offset, buffer_data, buffer_size);
}

void selfdestruct(const evmc_address& address, const evmc_address& beneficiary)
{
context->host->selfdestruct(context, &address, &beneficiary);
}

result call(const evmc_message& message) noexcept
{
return result{context->host->call(context, &message)};
}

/// Gets the transaction and block context from the Host.
///
/// The implementation caches the received transaction context
/// by assuming that the block timestamp should never be zero.
///
/// @return Reference to the cached transaction context.
const evmc_tx_context& get_tx_context() noexcept
{
if (tx_context.block_timestamp == 0)
tx_context = context->host->get_tx_context(context);
return tx_context;
}

evmc_bytes32 get_block_hash(int64_t number) noexcept
{
return context->host->get_block_hash(context, number);
}

void emit_log(const evmc_address& address,
const uint8_t* data,
size_t data_size,
const evmc_bytes32 topics[],
size_t topics_count) noexcept
{
context->host->emit_log(context, &address, data, data_size, topics, topics_count);
}
};
} // namespace evmc
2 changes: 1 addition & 1 deletion test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ add_executable(
test_loader.cpp
)

target_link_libraries(evmc-test PRIVATE loader-mocked evmc-example-vm-static instructions GTest::gtest GTest::main)
target_link_libraries(evmc-test PRIVATE loader-mocked evmc-example-vm-static evmc-example-host instructions GTest::gtest GTest::main)
set_target_properties(evmc-test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
37 changes: 37 additions & 0 deletions test/unittests/test_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// Copyright 2019 The EVMC Authors.
// Licensed under the Apache License, Version 2.0.

#include "../../examples/example_host.h"
#include "../../examples/example_vm.h"

#include <evmc/evmc.hpp>
#include <evmc/helpers.hpp>

#include <gtest/gtest.h>

Expand Down Expand Up @@ -61,3 +63,38 @@ TEST(cpp, vm_set_option)
auto vm = evmc::vm{&raw_instance};
EXPECT_EQ(vm.set_option("1", "2"), EVMC_SET_OPTION_INVALID_NAME);
}

TEST(cpp, host)
{
// Use example host to execute all methods from the C++ host wrapper.

auto* host_context = example_host_create_context();
auto host = evmc::host{host_context};

auto a = evmc_address{{1}};
auto v = evmc_bytes32{{7, 7, 7}};

EXPECT_FALSE(host.account_exists(a));

EXPECT_EQ(host.set_storage(a, {}, v), EVMC_STORAGE_MODIFIED);
EXPECT_EQ(host.set_storage(a, {}, v), EVMC_STORAGE_UNCHANGED);
EXPECT_EQ(host.get_storage(a, {}), v);

EXPECT_TRUE(is_zero(host.get_balance(a)));

EXPECT_EQ(host.get_code_size(a), 0);
EXPECT_EQ(host.get_code_hash(a), evmc_bytes32{});
EXPECT_EQ(host.copy_code(a, 0, nullptr, 0), 0);

host.selfdestruct(a, a);
EXPECT_EQ(host.call({}).gas_left, 0);

auto* tx = &host.get_tx_context();
EXPECT_EQ(&host.get_tx_context(), tx);

EXPECT_EQ(host.get_block_hash(0), evmc_bytes32{});

host.emit_log(a, nullptr, 0, nullptr, 0);

example_host_destroy_context(host_context);
}

0 comments on commit 9608bab

Please sign in to comment.