From 3fd78acb81bab0ba08a2545546c47c70d289a0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 15 Mar 2019 00:49:30 +0100 Subject: [PATCH 1/3] cpp: Add evmc::host - wrapper around Host context / interface --- include/evmc/evmc.hpp | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/include/evmc/evmc.hpp b/include/evmc/evmc.hpp index f391a23..9020883 100644 --- a/include/evmc/evmc.hpp +++ b/include/evmc/evmc.hpp @@ -76,4 +76,92 @@ public: 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 From cf24ccb2acb4f60b0ef4c463b07399fddeff6765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 15 Mar 2019 02:18:02 +0100 Subject: [PATCH 2/3] test: Add basic unit tests for C++ Host wrapper --- test/unittests/CMakeLists.txt | 2 +- test/unittests/test_cpp.cpp | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index 76dce8f..94ccc97 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -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 ..) diff --git a/test/unittests/test_cpp.cpp b/test/unittests/test_cpp.cpp index 937501b..373a725 100644 --- a/test/unittests/test_cpp.cpp +++ b/test/unittests/test_cpp.cpp @@ -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 +#include #include @@ -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); +} From aa3a81de02e201cac051c9f565bd043b2c5265ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 15 Mar 2019 12:10:16 +0100 Subject: [PATCH 3/3] changelog: Add entry about C++ evmc::host --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f566d..46b1e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`.