From 20101808b826f001b0b304091e6bc7a3fabeebb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 21 Nov 2019 16:21:19 +0100 Subject: [PATCH] Use MockedHost from EVMC --- CMakeLists.txt | 2 +- test/CMakeLists.txt | 1 + test/fuzzer/CMakeLists.txt | 2 +- test/fuzzer/fuzzer.cpp | 5 +- test/unittests/CMakeLists.txt | 2 +- test/unittests/evm_fixture.hpp | 5 +- test/unittests/evm_state_test.cpp | 2 +- test/utils/CMakeLists.txt | 1 - test/utils/host_mock.hpp | 251 ------------------------------ 9 files changed, 11 insertions(+), 260 deletions(-) delete mode 100644 test/utils/host_mock.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 970a1b63e3..c592585a08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ endif() hunter_add_package(ethash) find_package(ethash CONFIG REQUIRED) -option(EVMC_TEST_TOOLS "Build EVMC test tools" ${EVMONE_TESTING}) +option(EVMC_TOOLS "Build EVMC test tools" ${EVMONE_TESTING}) add_subdirectory(evmc) cable_configure_compiler() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5e6ec82c60..05f20276c7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,6 +3,7 @@ # Licensed under the Apache License, Version 2.0. include(GoogleTest) +include(${PROJECT_SOURCE_DIR}/evmc/cmake/EVMC.cmake) set(evmone_private_include_dir ${PROJECT_SOURCE_DIR}/lib) diff --git a/test/fuzzer/CMakeLists.txt b/test/fuzzer/CMakeLists.txt index 0aeace9b57..6827c2353b 100644 --- a/test/fuzzer/CMakeLists.txt +++ b/test/fuzzer/CMakeLists.txt @@ -15,7 +15,7 @@ else() endif() add_executable(evmone-fuzzer fuzzer.cpp) -target_link_libraries(evmone-fuzzer PRIVATE evmone testutils) +target_link_libraries(evmone-fuzzer PRIVATE evmone testutils evmc::mocked_host) if(NOT fuzzing_coverage) # TODO: Aleth reports undefined behaviors, disable it for fuzzing. diff --git a/test/fuzzer/fuzzer.cpp b/test/fuzzer/fuzzer.cpp index 70146d2b3d..acdecdf541 100644 --- a/test/fuzzer/fuzzer.cpp +++ b/test/fuzzer/fuzzer.cpp @@ -2,10 +2,11 @@ // Copyright 2019 The evmone Authors. // Licensed under the Apache License, Version 2.0. +#include #include #include -#include #include + #include #include @@ -68,7 +69,7 @@ static evmc::VM external_vms[] = { }; -class FuzzHost : public MockedHost +class FuzzHost : public evmc::MockedHost { public: uint8_t gas_left_factor = 0; diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index f6280edaec..706e7cd7b7 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -13,7 +13,7 @@ add_library(evm-unittests OBJECT evm_state_test.cpp evm_other_test.cpp ) -target_link_libraries(evm-unittests PRIVATE testutils evmc::evmc GTest::gtest) +target_link_libraries(evm-unittests PRIVATE testutils evmc::mocked_host GTest::gtest) target_include_directories(evm-unittests PRIVATE ${evmone_private_include_dir}) # The internal evmone unit tests. The generic EVM ones are also built in. diff --git a/test/unittests/evm_fixture.hpp b/test/unittests/evm_fixture.hpp index da93ce4481..e953a2a029 100644 --- a/test/unittests/evm_fixture.hpp +++ b/test/unittests/evm_fixture.hpp @@ -4,10 +4,11 @@ #pragma once #include "vm_loader.hpp" + +#include #include #include #include -#include #define EXPECT_STATUS(STATUS_CODE) \ EXPECT_EQ(result.status_code, STATUS_CODE); \ @@ -56,7 +57,7 @@ class evm : public testing::Test /// The total amount of gas used during execution. int64_t gas_used = 0; - MockedHost host; + evmc::MockedHost host; evm() noexcept : vm{get_vm()} {} diff --git a/test/unittests/evm_state_test.cpp b/test/unittests/evm_state_test.cpp index 7e2c87f22d..76944b85f3 100644 --- a/test/unittests/evm_state_test.cpp +++ b/test/unittests/evm_state_test.cpp @@ -540,7 +540,7 @@ TEST_F(evm_state, selfdestruct_with_balance) TEST_F(evm_state, blockhash) { - host.blockhash.bytes[13] = 0x13; + host.block_hash.bytes[13] = 0x13; host.tx_context.block_number = 0; auto code = "60004060005260206000f3"; diff --git a/test/utils/CMakeLists.txt b/test/utils/CMakeLists.txt index 07d3f35064..68e94fb01f 100644 --- a/test/utils/CMakeLists.txt +++ b/test/utils/CMakeLists.txt @@ -6,7 +6,6 @@ find_package(intx CONFIG REQUIRED) add_library(testutils STATIC bytecode.hpp - host_mock.hpp utils.cpp utils.hpp ) diff --git a/test/utils/host_mock.hpp b/test/utils/host_mock.hpp deleted file mode 100644 index 7d26e5c39b..0000000000 --- a/test/utils/host_mock.hpp +++ /dev/null @@ -1,251 +0,0 @@ -// evmone: Fast Ethereum Virtual Machine implementation -// Copyright 2019 The evmone Authors. -// Licensed under the Apache License, Version 2.0. -#pragma once - -#include -#include -#include -#include - -using bytes = std::basic_string; - -struct MockedAccount -{ - struct storage_value - { - evmc::bytes32 value; - - /// True means this value has been modified already by the current transaction. - bool dirty{false}; - - storage_value() noexcept = default; - - storage_value(const evmc::bytes32& _value, bool _dirty = false) noexcept // NOLINT - : value{_value}, dirty{_dirty} - {} - }; - - bytes code; - evmc::bytes32 codehash; - evmc::uint256be balance; - std::unordered_map storage; - - /// Helper method for setting balance by numeric type. - /// Might not be needed when intx API is improved, - /// track https://github.com/chfast/intx/issues/105. - void set_balance(uint64_t x) noexcept - { - balance = evmc::uint256be{}; - for (std::size_t i = 0; i < sizeof(x); ++i) - balance.bytes[sizeof(balance) - 1 - i] = static_cast(x >> (8 * i)); - } -}; - -class MockedHost : public evmc::Host -{ -public: - struct log_record - { - evmc::address address; - bytes data; - std::vector topics; - - bool operator==(const log_record& other) const noexcept - { - return address == other.address && data == other.data && - std::equal( - topics.begin(), topics.end(), other.topics.begin(), other.topics.end()); - } - }; - - struct selfdestuct_record - { - evmc::address address; - evmc::address beneficiary; - - bool operator==(const selfdestuct_record& other) const noexcept - { - return address == other.address && beneficiary == other.beneficiary; - } - }; - - std::unordered_map accounts; - - evmc_tx_context tx_context = {}; - - evmc::bytes32 blockhash = {}; - - evmc_result call_result = {}; - - std::vector recorded_blockhashes; - - static constexpr auto max_recorded_account_accesses = 200; - std::vector recorded_account_accesses; - - static constexpr auto max_recorded_calls = 100; - std::vector recorded_calls; - - std::vector recorded_logs; - std::vector recorded_selfdestructs; - -protected: - std::vector m_recorded_calls_inputs; - - void record_account_access(const evmc::address& addr) - { - if (recorded_account_accesses.empty()) - recorded_account_accesses.reserve(max_recorded_account_accesses); - - if (recorded_account_accesses.size() < max_recorded_account_accesses) - recorded_account_accesses.emplace_back(addr); - } - - bool account_exists(const evmc::address& addr) noexcept override - { - record_account_access(addr); - return accounts.count(addr); - } - - evmc::bytes32 get_storage(const evmc::address& addr, const evmc::bytes32& key) noexcept override - { - record_account_access(addr); - const auto ait = accounts.find(addr); - if (ait == accounts.end()) - return {}; - - if (const auto sit = ait->second.storage.find(key); sit != ait->second.storage.end()) - return sit->second.value; - return {}; - } - - evmc_storage_status set_storage(const evmc::address& addr, const evmc::bytes32& key, - const evmc::bytes32& value) noexcept override - { - record_account_access(addr); - const auto it = accounts.find(addr); - if (it == accounts.end()) - return EVMC_STORAGE_UNCHANGED; - - auto& old = it->second.storage[key]; - - // Follow https://eips.ethereum.org/EIPS/eip-1283 specification. - // WARNING! This is not complete implementation as refund is not handled here. - - if (old.value == value) - return EVMC_STORAGE_UNCHANGED; - - evmc_storage_status status; - { - if (!old.dirty) - { - old.dirty = true; - if (!old.value) - status = EVMC_STORAGE_ADDED; - else if (value) - status = EVMC_STORAGE_MODIFIED; - else - status = EVMC_STORAGE_DELETED; - } - else - status = EVMC_STORAGE_MODIFIED_AGAIN; - } - - old.value = value; - return status; - } - - evmc::uint256be get_balance(const evmc::address& addr) noexcept override - { - record_account_access(addr); - const auto it = accounts.find(addr); - if (it == accounts.end()) - return {}; - - return it->second.balance; - } - - size_t get_code_size(const evmc::address& addr) noexcept override - { - record_account_access(addr); - const auto it = accounts.find(addr); - if (it == accounts.end()) - return 0; - return it->second.code.size(); - } - - evmc::bytes32 get_code_hash(const evmc::address& addr) noexcept override - { - record_account_access(addr); - const auto it = accounts.find(addr); - if (it == accounts.end()) - return {}; - return it->second.codehash; - } - - size_t copy_code(const evmc::address& addr, size_t code_offset, uint8_t* buffer_data, - size_t buffer_size) noexcept override - { - record_account_access(addr); - const auto it = accounts.find(addr); - if (it == accounts.end()) - return 0; - - const auto& code = it->second.code; - - if (code_offset >= code.size()) - return 0; - - const auto n = std::min(buffer_size, code.size() - code_offset); - - if (n > 0) - std::copy_n(&code[code_offset], n, buffer_data); - return n; - } - - void selfdestruct(const evmc::address& addr, const evmc::address& beneficiary) noexcept override - { - record_account_access(addr); - recorded_selfdestructs.push_back({addr, beneficiary}); - } - - evmc::result call(const evmc_message& msg) noexcept override - { - record_account_access(msg.destination); - - if (recorded_calls.empty()) - { - recorded_calls.reserve(max_recorded_calls); - m_recorded_calls_inputs.reserve(max_recorded_calls); // Iterators will not invalidate. - } - - if (recorded_calls.size() < max_recorded_calls) - { - auto& call_msg = recorded_calls.emplace_back(msg); - if (call_msg.input_size > 0) - { - const auto& input_copy = - m_recorded_calls_inputs.emplace_back(call_msg.input_data, call_msg.input_size); - call_msg.input_data = input_copy.data(); - } - } - return evmc::result{call_result}; - } - - evmc_tx_context get_tx_context() noexcept override { return tx_context; } - - evmc::bytes32 get_block_hash(int64_t block_number) noexcept override - { - recorded_blockhashes.emplace_back(block_number); - return blockhash; - } - - void emit_log(const evmc::address& addr, const uint8_t* data, size_t data_size, - const evmc::bytes32 topics[], size_t topics_count) noexcept override - { - recorded_logs.push_back({addr, {data, data_size}, {}}); - auto& record_topics = recorded_logs.back().topics; - record_topics.reserve(topics_count); - std::copy_n(topics, topics_count, std::back_inserter(record_topics)); - } -};