Upgrade to EVMC 7.5.0

One important change: MockedAccount.storage is a map and not unordered_map
This commit is contained in:
Alex Beregszaszi 2021-03-23 23:39:47 +00:00
parent 83213e659d
commit f1aaae36ee
8 changed files with 93 additions and 80 deletions

View File

@ -173,7 +173,7 @@ void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _ben
accounts.erase(_addr); accounts.erase(_addr);
accounts[_beneficiary].balance = balance; accounts[_beneficiary].balance = balance;
// Record self destructs // Record self destructs
recorded_selfdestructs.push_back({_addr, _beneficiary, balance}); recorded_selfdestructs.push_back({_addr, _beneficiary});
} }
void EVMHost::recordCalls(evmc_message const& _message) noexcept void EVMHost::recordCalls(evmc_message const& _message) noexcept
@ -814,8 +814,6 @@ void EVMHostPrinter::selfdestructRecords()
m_stateStream << "SELFDESTRUCT" m_stateStream << "SELFDESTRUCT"
<< " BENEFICIARY " << " BENEFICIARY "
<< m_host.convertFromEVMC(record.beneficiary) << m_host.convertFromEVMC(record.beneficiary)
<< " BALANCE "
<< m_host.convertFromEVMC(record.balance)
<< endl; << endl;
} }

View File

@ -1,3 +1,5 @@
# EVMC # 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.

View File

@ -28,7 +28,7 @@
#include <stddef.h> /* Definition of size_t. */ #include <stddef.h> /* Definition of size_t. */
#include <stdint.h> /* Definition of int64_t, uint64_t. */ #include <stdint.h> /* Definition of int64_t, uint64_t. */
#if __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -295,6 +295,9 @@ enum evmc_status_code
*/ */
EVMC_WASM_TRAP = 16, EVMC_WASM_TRAP = 16,
/** The caller does not have enough funds for value transfer. */
EVMC_INSUFFICIENT_BALANCE = 17,
/** EVM implementation generic internal error. */ /** EVM implementation generic internal error. */
EVMC_INTERNAL_ERROR = -1, EVMC_INTERNAL_ERROR = -1,
@ -914,7 +917,7 @@ struct evmc_vm
/* END Python CFFI declarations */ /* END Python CFFI declarations */
#if EVMC_DOCUMENTATION #ifdef EVMC_DOCUMENTATION
/** /**
* Example of a function creating an instance of an example EVM implementation. * 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); struct evmc_vm* evmc_create_example_vm(void);
#endif #endif
#if __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* EVMC: Ethereum Client-VM Connector API. /* 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. * Licensed under the Apache License, Version 2.0.
*/ */
#pragma once #pragma once
@ -53,7 +53,7 @@ struct address : evmc_address
{} {}
/// Explicit operator converting to bool. /// 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. /// The fixed size array of 32 bytes for storing 256-bit EVM values.
@ -113,19 +113,34 @@ struct bytes32 : evmc_bytes32
using uint256be = bytes32; using uint256be = bytes32;
/// Loads 64 bits / 8 bytes of data from the given @p bytes array in big-endian order. /// Loads 64 bits / 8 bytes of data from the given @p data array in big-endian order.
constexpr inline uint64_t load64be(const uint8_t* bytes) noexcept 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) | return (uint64_t{data[0]} << 56) | (uint64_t{data[1]} << 48) | (uint64_t{data[2]} << 40) |
(uint64_t{bytes[3]} << 32) | (uint64_t{bytes[4]} << 24) | (uint64_t{bytes[5]} << 16) | (uint64_t{data[3]} << 32) | (uint64_t{data[4]} << 24) | (uint64_t{data[5]} << 16) |
(uint64_t{bytes[6]} << 8) | uint64_t{bytes[7]}; (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. /// Loads 64 bits / 8 bytes of data from the given @p data array in little-endian order.
constexpr inline uint32_t load32be(const uint8_t* bytes) noexcept 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) | return uint64_t{data[0]} | (uint64_t{data[1]} << 8) | (uint64_t{data[2]} << 16) |
uint32_t{bytes[3]}; (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 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. constexpr auto offset_basis = 0xcbf29ce484222325; ///< The 64-bit FNV offset basis.
/// The hashing transformation for 64-bit inputs based on the FNV-1a formula. /// 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; 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. /// 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 load64le(&a.bytes[0]) == load64le(&b.bytes[0]) &&
return load64be(&a.bytes[0]) == load64be(&b.bytes[0]) && load64le(&a.bytes[8]) == load64le(&b.bytes[8]) &&
load64be(&a.bytes[8]) == load64be(&b.bytes[8]) && load32le(&a.bytes[16]) == load32le(&b.bytes[16]);
load32be(&a.bytes[16]) == load32be(&b.bytes[16]);
} }
/// The "not equal to" comparison operator for the evmc::address type. /// 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); return !(a == b);
} }
/// The "less than" comparison operator for the evmc::address type. /// 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]) || return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) ||
(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. /// 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; return b < a;
} }
/// The "less than or equal to" comparison operator for the evmc::address type. /// 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); return !(b < a);
} }
/// The "greater than or equal to" comparison operator for the evmc::address type. /// 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); return !(a < b);
} }
/// The "equal to" comparison operator for the evmc::bytes32 type. /// 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]) && return load64le(&a.bytes[0]) == load64le(&b.bytes[0]) &&
load64be(&a.bytes[8]) == load64be(&b.bytes[8]) && load64le(&a.bytes[8]) == load64le(&b.bytes[8]) &&
load64be(&a.bytes[16]) == load64be(&b.bytes[16]) && load64le(&a.bytes[16]) == load64le(&b.bytes[16]) &&
load64be(&a.bytes[24]) == load64be(&b.bytes[24]); load64le(&a.bytes[24]) == load64le(&b.bytes[24]);
} }
/// The "not equal to" comparison operator for the evmc::bytes32 type. /// 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); return !(a == b);
} }
/// The "less than" comparison operator for the evmc::bytes32 type. /// 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]) || return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) ||
(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. /// 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; return b < a;
} }
/// The "less than or equal to" comparison operator for the evmc::bytes32 type. /// 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); return !(b < a);
} }
/// The "greater than or equal to" comparison operator for the evmc::bytes32 type. /// 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); return !(a < b);
} }
/// Checks if the given address is the zero address. /// 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{}; return a == address{};
} }
constexpr address::operator bool() const noexcept inline constexpr address::operator bool() const noexcept
{ {
return !is_zero(*this); return !is_zero(*this);
} }
/// Checks if the given bytes32 object has all zero bytes. /// 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{}; return a == bytes32{};
} }
constexpr bytes32::operator bool() const noexcept inline constexpr bytes32::operator bool() const noexcept
{ {
return !is_zero(*this); return !is_zero(*this);
} }
@ -255,11 +269,6 @@ namespace literals
{ {
namespace internal 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 constexpr int from_hex(char c) noexcept
{ {
return (c >= 'a' && c <= 'f') ? c - ('a' - 10) : return (c >= 'a' && c <= 'f') ? c - ('a' - 10) :
@ -294,28 +303,34 @@ constexpr address from_hex<address>(const char* s) noexcept
byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19)}}}; byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19)}}};
} }
template <typename T> template <typename T, char... c>
constexpr T from_literal(const char* s) constexpr T from_literal() noexcept
{ {
return (s[0] == '0' && s[1] == '\0') ? constexpr auto size = sizeof...(c);
T{} : constexpr char literal[] = {c...};
!(s[0] == '0' && s[1] == 'x') ? constexpr bool is_simple_zero = size == 1 && literal[0] == '0';
throw "literal must be in hexadecimal notation" :
(length(s + 2) != sizeof(T) * 2) ? throw "literal must match the result type size" : static_assert(is_simple_zero || (literal[0] == '0' && literal[1] == 'x'),
from_hex<T>(s + 2); "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<T>(&literal[2]);
} }
} // namespace internal } // namespace internal
/// Literal for evmc::address. /// Literal for evmc::address.
constexpr address operator""_address(const char* s) noexcept template <char... c>
constexpr address operator""_address() noexcept
{ {
return internal::from_literal<address>(s); return internal::from_literal<address, c...>();
} }
/// Literal for evmc::bytes32. /// Literal for evmc::bytes32.
constexpr bytes32 operator""_bytes32(const char* s) noexcept template <char... c>
constexpr bytes32 operator""_bytes32() noexcept
{ {
return internal::from_literal<bytes32>(s); return internal::from_literal<bytes32, c...>();
} }
} // namespace literals } // namespace literals
@ -641,7 +656,7 @@ public:
return (get_capabilities() & static_cast<evmc_capabilities_flagset>(capability)) != 0; return (get_capabilities() & static_cast<evmc_capabilities_flagset>(capability)) != 0;
} }
/// @copydoc evmc::vm::get_capabilities /// @copydoc evmc_vm::get_capabilities
evmc_capabilities_flagset get_capabilities() const noexcept evmc_capabilities_flagset get_capabilities() const noexcept
{ {
return m_instance->get_capabilities(m_instance); return m_instance->get_capabilities(m_instance);
@ -818,8 +833,8 @@ struct hash<evmc::address>
using namespace evmc; using namespace evmc;
using namespace fnv; using namespace fnv;
return static_cast<size_t>(fnv1a_by64( return static_cast<size_t>(fnv1a_by64(
fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64be(&s.bytes[0])), load64be(&s.bytes[8])), fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])), load64le(&s.bytes[8])),
load32be(&s.bytes[16]))); load32le(&s.bytes[16])));
} }
}; };
@ -833,10 +848,10 @@ struct hash<evmc::bytes32>
using namespace evmc; using namespace evmc;
using namespace fnv; using namespace fnv;
return static_cast<size_t>( return static_cast<size_t>(
fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64be(&s.bytes[0])), fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])),
load64be(&s.bytes[8])), load64le(&s.bytes[8])),
load64be(&s.bytes[16])), load64le(&s.bytes[16])),
load64be(&s.bytes[24]))); load64le(&s.bytes[24])));
} }
}; };
} // namespace std } // namespace std

View File

@ -15,7 +15,7 @@
#if defined(EVMC_LOADER_MOCK) #if defined(EVMC_LOADER_MOCK)
#include "../../test/unittests/loader_mock.h" #include "../../test/unittests/loader_mock.h"
#elif _WIN32 #elif defined(_WIN32)
#include <Windows.h> #include <Windows.h>
#define DLL_HANDLE HMODULE #define DLL_HANDLE HMODULE
#define DLL_OPEN(filename) LoadLibrary(filename) #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. // Find filename in the path.
const char* sep_pos = strrchr(filename, '/'); const char* sep_pos = strrchr(filename, '/');
#if _WIN32 #ifdef _WIN32
// On Windows check also Windows classic path separator. // On Windows check also Windows classic path separator.
const char* sep_pos_windows = strrchr(filename, '\\'); const char* sep_pos_windows = strrchr(filename, '\\');
sep_pos = sep_pos_windows > sep_pos ? sep_pos_windows : sep_pos; sep_pos = sep_pos_windows > sep_pos ? sep_pos_windows : sep_pos;

View File

@ -14,7 +14,7 @@
*/ */
#pragma once #pragma once
#if __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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. * @return Error message or NULL if no additional information is available.
* The returned pointer MUST NOT be freed by the caller. * 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 #endif

View File

@ -92,15 +92,10 @@ public:
/// The address of the beneficiary account. /// The address of the beneficiary account.
address beneficiary; address beneficiary;
/// The balance of the self-destructed account.
uint256be balance;
/// Equal operator. /// Equal operator.
bool operator==(const selfdestuct_record& other) const noexcept bool operator==(const selfdestuct_record& other) const noexcept
{ {
return selfdestructed == other.selfdestructed && return selfdestructed == other.selfdestructed && beneficiary == other.beneficiary;
beneficiary == other.beneficiary &&
balance == other.balance;
} }
}; };
@ -271,7 +266,7 @@ public:
void selfdestruct(const address& addr, const address& beneficiary) noexcept override void selfdestruct(const address& addr, const address& beneficiary) noexcept override
{ {
record_account_access(addr); 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). /// Call/create other contract (EVMC host method).

View File

@ -27,7 +27,7 @@
* @def EVMC_NOEXCEPT * @def EVMC_NOEXCEPT
* Safe way of marking a function with `noexcept` C++ specifier. * Safe way of marking a function with `noexcept` C++ specifier.
*/ */
#if __cplusplus #ifdef __cplusplus
#define EVMC_NOEXCEPT noexcept #define EVMC_NOEXCEPT noexcept
#else #else
#define EVMC_NOEXCEPT #define EVMC_NOEXCEPT