diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 586860ec5..157f4e4d3 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -173,7 +173,7 @@ void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _ben accounts.erase(_addr); accounts[_beneficiary].balance = balance; // Record self destructs - recorded_selfdestructs.push_back({_addr, _beneficiary, balance}); + recorded_selfdestructs.push_back({_addr, _beneficiary}); } void EVMHost::recordCalls(evmc_message const& _message) noexcept @@ -814,8 +814,6 @@ void EVMHostPrinter::selfdestructRecords() m_stateStream << "SELFDESTRUCT" << " BENEFICIARY " << m_host.convertFromEVMC(record.beneficiary) - << " BALANCE " - << m_host.convertFromEVMC(record.balance) << endl; } diff --git a/test/evmc/README.md b/test/evmc/README.md index 1d5d55422..655eae4bc 100644 --- a/test/evmc/README.md +++ b/test/evmc/README.md @@ -1,3 +1,5 @@ # EVMC -This is an import of [EVMC](https://github.com/ethereum/evmc) version [7.2.0](https://github.com/ethereum/evmc/releases/tag/v7.2.0). +This is an import of [EVMC](https://github.com/ethereum/evmc) version [7.5.0](https://github.com/ethereum/evmc/releases/tag/v7.5.0). + +Important: The `MockedAccount.storage` is changed to a map from unordered_map as ordering is important for fuzzing. diff --git a/test/evmc/evmc.h b/test/evmc/evmc.h index 51d9f842a..88be51b61 100644 --- a/test/evmc/evmc.h +++ b/test/evmc/evmc.h @@ -28,7 +28,7 @@ #include /* Definition of size_t. */ #include /* Definition of int64_t, uint64_t. */ -#if __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -295,6 +295,9 @@ enum evmc_status_code */ EVMC_WASM_TRAP = 16, + /** The caller does not have enough funds for value transfer. */ + EVMC_INSUFFICIENT_BALANCE = 17, + /** EVM implementation generic internal error. */ EVMC_INTERNAL_ERROR = -1, @@ -914,7 +917,7 @@ struct evmc_vm /* END Python CFFI declarations */ -#if EVMC_DOCUMENTATION +#ifdef EVMC_DOCUMENTATION /** * Example of a function creating an instance of an example EVM implementation. * @@ -933,7 +936,7 @@ struct evmc_vm struct evmc_vm* evmc_create_example_vm(void); #endif -#if __cplusplus +#ifdef __cplusplus } #endif diff --git a/test/evmc/evmc.hpp b/test/evmc/evmc.hpp index 36f9063b3..fe72656ce 100644 --- a/test/evmc/evmc.hpp +++ b/test/evmc/evmc.hpp @@ -1,5 +1,5 @@ /* EVMC: Ethereum Client-VM Connector API. - * Copyright 2018-2019 The EVMC Authors. + * Copyright 2018-2020 The EVMC Authors. * Licensed under the Apache License, Version 2.0. */ #pragma once @@ -53,7 +53,7 @@ struct address : evmc_address {} /// Explicit operator converting to bool. - constexpr inline explicit operator bool() const noexcept; + inline constexpr explicit operator bool() const noexcept; }; /// The fixed size array of 32 bytes for storing 256-bit EVM values. @@ -113,19 +113,34 @@ struct bytes32 : evmc_bytes32 using uint256be = bytes32; -/// Loads 64 bits / 8 bytes of data from the given @p bytes array in big-endian order. -constexpr inline uint64_t load64be(const uint8_t* bytes) noexcept +/// Loads 64 bits / 8 bytes of data from the given @p data array in big-endian order. +inline constexpr uint64_t load64be(const uint8_t* data) noexcept { - return (uint64_t{bytes[0]} << 56) | (uint64_t{bytes[1]} << 48) | (uint64_t{bytes[2]} << 40) | - (uint64_t{bytes[3]} << 32) | (uint64_t{bytes[4]} << 24) | (uint64_t{bytes[5]} << 16) | - (uint64_t{bytes[6]} << 8) | uint64_t{bytes[7]}; + return (uint64_t{data[0]} << 56) | (uint64_t{data[1]} << 48) | (uint64_t{data[2]} << 40) | + (uint64_t{data[3]} << 32) | (uint64_t{data[4]} << 24) | (uint64_t{data[5]} << 16) | + (uint64_t{data[6]} << 8) | uint64_t{data[7]}; } -/// Loads 32 bits / 4 bytes of data from the given @p bytes array in big-endian order. -constexpr inline uint32_t load32be(const uint8_t* bytes) noexcept +/// Loads 64 bits / 8 bytes of data from the given @p data array in little-endian order. +inline constexpr uint64_t load64le(const uint8_t* data) noexcept { - return (uint32_t{bytes[0]} << 24) | (uint32_t{bytes[1]} << 16) | (uint32_t{bytes[2]} << 8) | - uint32_t{bytes[3]}; + return uint64_t{data[0]} | (uint64_t{data[1]} << 8) | (uint64_t{data[2]} << 16) | + (uint64_t{data[3]} << 24) | (uint64_t{data[4]} << 32) | (uint64_t{data[5]} << 40) | + (uint64_t{data[6]} << 48) | (uint64_t{data[7]} << 56); +} + +/// Loads 32 bits / 4 bytes of data from the given @p data array in big-endian order. +inline constexpr uint32_t load32be(const uint8_t* data) noexcept +{ + return (uint32_t{data[0]} << 24) | (uint32_t{data[1]} << 16) | (uint32_t{data[2]} << 8) | + uint32_t{data[3]}; +} + +/// Loads 32 bits / 4 bytes of data from the given @p data array in little-endian order. +inline constexpr uint32_t load32le(const uint8_t* data) noexcept +{ + return uint32_t{data[0]} | (uint32_t{data[1]} << 8) | (uint32_t{data[2]} << 16) | + (uint32_t{data[3]} << 24); } namespace fnv @@ -134,7 +149,7 @@ constexpr auto prime = 0x100000001b3; ///< The 64-bit FNV prime num constexpr auto offset_basis = 0xcbf29ce484222325; ///< The 64-bit FNV offset basis. /// The hashing transformation for 64-bit inputs based on the FNV-1a formula. -constexpr inline uint64_t fnv1a_by64(uint64_t h, uint64_t x) noexcept +inline constexpr uint64_t fnv1a_by64(uint64_t h, uint64_t x) noexcept { return (h ^ x) * prime; } @@ -142,22 +157,21 @@ constexpr inline uint64_t fnv1a_by64(uint64_t h, uint64_t x) noexcept /// The "equal to" comparison operator for the evmc::address type. -constexpr bool operator==(const address& a, const address& b) noexcept +inline constexpr bool operator==(const address& a, const address& b) noexcept { - // TODO: Report bug in clang keeping unnecessary bswap. - return load64be(&a.bytes[0]) == load64be(&b.bytes[0]) && - load64be(&a.bytes[8]) == load64be(&b.bytes[8]) && - load32be(&a.bytes[16]) == load32be(&b.bytes[16]); + return load64le(&a.bytes[0]) == load64le(&b.bytes[0]) && + load64le(&a.bytes[8]) == load64le(&b.bytes[8]) && + load32le(&a.bytes[16]) == load32le(&b.bytes[16]); } /// The "not equal to" comparison operator for the evmc::address type. -constexpr bool operator!=(const address& a, const address& b) noexcept +inline constexpr bool operator!=(const address& a, const address& b) noexcept { return !(a == b); } /// The "less than" comparison operator for the evmc::address type. -constexpr bool operator<(const address& a, const address& b) noexcept +inline constexpr bool operator<(const address& a, const address& b) noexcept { return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) || (load64be(&a.bytes[0]) == load64be(&b.bytes[0]) && @@ -167,40 +181,40 @@ constexpr bool operator<(const address& a, const address& b) noexcept } /// The "greater than" comparison operator for the evmc::address type. -constexpr bool operator>(const address& a, const address& b) noexcept +inline constexpr bool operator>(const address& a, const address& b) noexcept { return b < a; } /// The "less than or equal to" comparison operator for the evmc::address type. -constexpr bool operator<=(const address& a, const address& b) noexcept +inline constexpr bool operator<=(const address& a, const address& b) noexcept { return !(b < a); } /// The "greater than or equal to" comparison operator for the evmc::address type. -constexpr bool operator>=(const address& a, const address& b) noexcept +inline constexpr bool operator>=(const address& a, const address& b) noexcept { return !(a < b); } /// The "equal to" comparison operator for the evmc::bytes32 type. -constexpr bool operator==(const bytes32& a, const bytes32& b) noexcept +inline constexpr bool operator==(const bytes32& a, const bytes32& b) noexcept { - return load64be(&a.bytes[0]) == load64be(&b.bytes[0]) && - load64be(&a.bytes[8]) == load64be(&b.bytes[8]) && - load64be(&a.bytes[16]) == load64be(&b.bytes[16]) && - load64be(&a.bytes[24]) == load64be(&b.bytes[24]); + return load64le(&a.bytes[0]) == load64le(&b.bytes[0]) && + load64le(&a.bytes[8]) == load64le(&b.bytes[8]) && + load64le(&a.bytes[16]) == load64le(&b.bytes[16]) && + load64le(&a.bytes[24]) == load64le(&b.bytes[24]); } /// The "not equal to" comparison operator for the evmc::bytes32 type. -constexpr bool operator!=(const bytes32& a, const bytes32& b) noexcept +inline constexpr bool operator!=(const bytes32& a, const bytes32& b) noexcept { return !(a == b); } /// The "less than" comparison operator for the evmc::bytes32 type. -constexpr bool operator<(const bytes32& a, const bytes32& b) noexcept +inline constexpr bool operator<(const bytes32& a, const bytes32& b) noexcept { return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) || (load64be(&a.bytes[0]) == load64be(&b.bytes[0]) && @@ -212,41 +226,41 @@ constexpr bool operator<(const bytes32& a, const bytes32& b) noexcept } /// The "greater than" comparison operator for the evmc::bytes32 type. -constexpr bool operator>(const bytes32& a, const bytes32& b) noexcept +inline constexpr bool operator>(const bytes32& a, const bytes32& b) noexcept { return b < a; } /// The "less than or equal to" comparison operator for the evmc::bytes32 type. -constexpr bool operator<=(const bytes32& a, const bytes32& b) noexcept +inline constexpr bool operator<=(const bytes32& a, const bytes32& b) noexcept { return !(b < a); } /// The "greater than or equal to" comparison operator for the evmc::bytes32 type. -constexpr bool operator>=(const bytes32& a, const bytes32& b) noexcept +inline constexpr bool operator>=(const bytes32& a, const bytes32& b) noexcept { return !(a < b); } /// Checks if the given address is the zero address. -constexpr inline bool is_zero(const address& a) noexcept +inline constexpr bool is_zero(const address& a) noexcept { return a == address{}; } -constexpr address::operator bool() const noexcept +inline constexpr address::operator bool() const noexcept { return !is_zero(*this); } /// Checks if the given bytes32 object has all zero bytes. -constexpr inline bool is_zero(const bytes32& a) noexcept +inline constexpr bool is_zero(const bytes32& a) noexcept { return a == bytes32{}; } -constexpr bytes32::operator bool() const noexcept +inline constexpr bytes32::operator bool() const noexcept { return !is_zero(*this); } @@ -255,11 +269,6 @@ namespace literals { namespace internal { -constexpr size_t length(const char* s) noexcept -{ - return (*s != '\0') ? length(s + 1) + 1 : 0; -} - constexpr int from_hex(char c) noexcept { return (c >= 'a' && c <= 'f') ? c - ('a' - 10) : @@ -294,28 +303,34 @@ constexpr address from_hex
(const char* s) noexcept byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19)}}}; } -template -constexpr T from_literal(const char* s) +template +constexpr T from_literal() noexcept { - return (s[0] == '0' && s[1] == '\0') ? - T{} : - !(s[0] == '0' && s[1] == 'x') ? - throw "literal must be in hexadecimal notation" : - (length(s + 2) != sizeof(T) * 2) ? throw "literal must match the result type size" : - from_hex(s + 2); + constexpr auto size = sizeof...(c); + constexpr char literal[] = {c...}; + constexpr bool is_simple_zero = size == 1 && literal[0] == '0'; + + static_assert(is_simple_zero || (literal[0] == '0' && literal[1] == 'x'), + "literal must be in hexadecimal notation"); + static_assert(is_simple_zero || size == 2 * sizeof(T) + 2, + "literal must match the result type size"); + + return is_simple_zero ? T{} : from_hex(&literal[2]); } } // namespace internal /// Literal for evmc::address. -constexpr address operator""_address(const char* s) noexcept +template +constexpr address operator""_address() noexcept { - return internal::from_literal
(s); + return internal::from_literal(); } /// Literal for evmc::bytes32. -constexpr bytes32 operator""_bytes32(const char* s) noexcept +template +constexpr bytes32 operator""_bytes32() noexcept { - return internal::from_literal(s); + return internal::from_literal(); } } // namespace literals @@ -641,7 +656,7 @@ public: return (get_capabilities() & static_cast(capability)) != 0; } - /// @copydoc evmc::vm::get_capabilities + /// @copydoc evmc_vm::get_capabilities evmc_capabilities_flagset get_capabilities() const noexcept { return m_instance->get_capabilities(m_instance); @@ -818,8 +833,8 @@ struct hash using namespace evmc; using namespace fnv; return static_cast(fnv1a_by64( - fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64be(&s.bytes[0])), load64be(&s.bytes[8])), - load32be(&s.bytes[16]))); + fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])), load64le(&s.bytes[8])), + load32le(&s.bytes[16]))); } }; @@ -833,10 +848,10 @@ struct hash using namespace evmc; using namespace fnv; return static_cast( - fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64be(&s.bytes[0])), - load64be(&s.bytes[8])), - load64be(&s.bytes[16])), - load64be(&s.bytes[24]))); + fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])), + load64le(&s.bytes[8])), + load64le(&s.bytes[16])), + load64le(&s.bytes[24]))); } }; } // namespace std diff --git a/test/evmc/loader.c b/test/evmc/loader.c index 0cd4834e7..5b8b3c3a2 100644 --- a/test/evmc/loader.c +++ b/test/evmc/loader.c @@ -15,7 +15,7 @@ #if defined(EVMC_LOADER_MOCK) #include "../../test/unittests/loader_mock.h" -#elif _WIN32 +#elif defined(_WIN32) #include #define DLL_HANDLE HMODULE #define DLL_OPEN(filename) LoadLibrary(filename) @@ -136,7 +136,7 @@ evmc_create_fn evmc_load(const char* filename, enum evmc_loader_error_code* erro // Find filename in the path. const char* sep_pos = strrchr(filename, '/'); -#if _WIN32 +#ifdef _WIN32 // On Windows check also Windows classic path separator. const char* sep_pos_windows = strrchr(filename, '\\'); sep_pos = sep_pos_windows > sep_pos ? sep_pos_windows : sep_pos; diff --git a/test/evmc/loader.h b/test/evmc/loader.h index 523139e31..868751652 100644 --- a/test/evmc/loader.h +++ b/test/evmc/loader.h @@ -14,7 +14,7 @@ */ #pragma once -#if __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -161,9 +161,9 @@ struct evmc_vm* evmc_load_and_configure(const char* config, * @return Error message or NULL if no additional information is available. * The returned pointer MUST NOT be freed by the caller. */ -const char* evmc_last_error_msg(); +const char* evmc_last_error_msg(void); -#if __cplusplus +#ifdef __cplusplus } #endif diff --git a/test/evmc/mocked_host.hpp b/test/evmc/mocked_host.hpp index 19ba27657..257de7a7c 100644 --- a/test/evmc/mocked_host.hpp +++ b/test/evmc/mocked_host.hpp @@ -92,15 +92,10 @@ public: /// The address of the beneficiary account. address beneficiary; - /// The balance of the self-destructed account. - uint256be balance; - /// Equal operator. bool operator==(const selfdestuct_record& other) const noexcept { - return selfdestructed == other.selfdestructed && - beneficiary == other.beneficiary && - balance == other.balance; + return selfdestructed == other.selfdestructed && beneficiary == other.beneficiary; } }; @@ -271,7 +266,7 @@ public: void selfdestruct(const address& addr, const address& beneficiary) noexcept override { record_account_access(addr); - recorded_selfdestructs.push_back({addr, beneficiary, get_balance(addr)}); + recorded_selfdestructs.push_back({addr, beneficiary}); } /// Call/create other contract (EVMC host method). diff --git a/test/evmc/utils.h b/test/evmc/utils.h index 03715c0b0..34cf26b2b 100644 --- a/test/evmc/utils.h +++ b/test/evmc/utils.h @@ -27,7 +27,7 @@ * @def EVMC_NOEXCEPT * Safe way of marking a function with `noexcept` C++ specifier. */ -#if __cplusplus +#ifdef __cplusplus #define EVMC_NOEXCEPT noexcept #else #define EVMC_NOEXCEPT