mirror of
https://github.com/status-im/evmc.git
synced 2025-02-24 08:58:12 +00:00
Merge pull request #226 from ethereum/cpp-host-interface
cpp: Add Host interface for the Host side
This commit is contained in:
commit
ea4bf5ccb1
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "example_host.h"
|
#include "example_host.h"
|
||||||
|
|
||||||
#include <evmc/helpers.h>
|
#include <evmc/evmc.hpp>
|
||||||
#include <evmc/helpers.hpp>
|
#include <evmc/helpers.hpp>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -21,153 +21,122 @@ struct account
|
|||||||
std::map<evmc_bytes32, evmc_bytes32> storage;
|
std::map<evmc_bytes32, evmc_bytes32> storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct example_host_context : evmc_context
|
class ExampleHost : public evmc::Host
|
||||||
{
|
{
|
||||||
example_host_context();
|
|
||||||
|
|
||||||
evmc_tx_context tx_context = {};
|
|
||||||
|
|
||||||
std::map<evmc_address, account> accounts;
|
std::map<evmc_address, account> accounts;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool account_exists(const evmc_address& addr) noexcept final
|
||||||
|
{
|
||||||
|
return accounts.find(addr) != accounts.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
evmc_bytes32 get_storage(const evmc_address& addr, const evmc_bytes32& key) noexcept final
|
||||||
|
{
|
||||||
|
auto it = accounts.find(addr);
|
||||||
|
if (it != accounts.end())
|
||||||
|
return it->second.storage[key];
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
evmc_storage_status set_storage(const evmc_address& addr,
|
||||||
|
const evmc_bytes32& key,
|
||||||
|
const evmc_bytes32& value) noexcept final
|
||||||
|
{
|
||||||
|
auto& account = accounts[addr];
|
||||||
|
auto prev_value = account.storage[key];
|
||||||
|
account.storage[key] = value;
|
||||||
|
|
||||||
|
return (prev_value == value) ? EVMC_STORAGE_UNCHANGED : EVMC_STORAGE_MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
evmc_uint256be get_balance(const evmc_address& addr) noexcept final
|
||||||
|
{
|
||||||
|
auto it = accounts.find(addr);
|
||||||
|
if (it != accounts.end())
|
||||||
|
return it->second.balance;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_code_size(const evmc_address& addr) noexcept final
|
||||||
|
{
|
||||||
|
auto it = accounts.find(addr);
|
||||||
|
if (it != accounts.end())
|
||||||
|
return it->second.code_size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
evmc_bytes32 get_code_hash(const evmc_address& addr) noexcept final
|
||||||
|
{
|
||||||
|
auto it = accounts.find(addr);
|
||||||
|
if (it != accounts.end())
|
||||||
|
return it->second.code_hash;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t copy_code(const evmc_address& addr,
|
||||||
|
size_t code_offset,
|
||||||
|
uint8_t* buffer_data,
|
||||||
|
size_t buffer_size) noexcept final
|
||||||
|
{
|
||||||
|
(void)addr;
|
||||||
|
(void)code_offset;
|
||||||
|
(void)buffer_data;
|
||||||
|
(void)buffer_size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void selfdestruct(const evmc_address& addr, const evmc_address& beneficiary) noexcept final
|
||||||
|
{
|
||||||
|
(void)addr;
|
||||||
|
(void)beneficiary;
|
||||||
|
}
|
||||||
|
|
||||||
|
evmc::result call(const evmc_message& msg) noexcept final
|
||||||
|
{
|
||||||
|
(void)msg;
|
||||||
|
// TODO: Improve C++ API for result creation.
|
||||||
|
evmc_result res{};
|
||||||
|
res.status_code = EVMC_FAILURE;
|
||||||
|
return evmc::result{res};
|
||||||
|
}
|
||||||
|
|
||||||
|
evmc_tx_context get_tx_context() noexcept final { return {}; }
|
||||||
|
|
||||||
|
evmc_bytes32 get_block_hash(int64_t number) noexcept final
|
||||||
|
{
|
||||||
|
int64_t current_block_number = get_tx_context().block_number;
|
||||||
|
|
||||||
|
auto example_block_hash = evmc_bytes32{};
|
||||||
|
if (number < current_block_number && number >= current_block_number - 256)
|
||||||
|
example_block_hash = {{1, 1, 1, 1}};
|
||||||
|
return example_block_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_log(const evmc_address& addr,
|
||||||
|
const uint8_t* data,
|
||||||
|
size_t data_size,
|
||||||
|
const evmc_bytes32 topics[],
|
||||||
|
size_t topics_count) noexcept final
|
||||||
|
{
|
||||||
|
(void)addr;
|
||||||
|
(void)data;
|
||||||
|
(void)data_size;
|
||||||
|
(void)topics;
|
||||||
|
(void)topics_count;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool account_exists(evmc_context* context, const evmc_address* address)
|
|
||||||
{
|
|
||||||
auto* host = static_cast<example_host_context*>(context);
|
|
||||||
return host->accounts.find(*address) != host->accounts.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
static evmc_bytes32 get_storage(evmc_context* context,
|
|
||||||
const evmc_address* address,
|
|
||||||
const evmc_bytes32* key)
|
|
||||||
{
|
|
||||||
auto* host = static_cast<example_host_context*>(context);
|
|
||||||
auto it = host->accounts.find(*address);
|
|
||||||
if (it != host->accounts.end())
|
|
||||||
return it->second.storage[*key];
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static evmc_storage_status set_storage(evmc_context* context,
|
|
||||||
const evmc_address* address,
|
|
||||||
const evmc_bytes32* key,
|
|
||||||
const evmc_bytes32* value)
|
|
||||||
{
|
|
||||||
auto* host = static_cast<example_host_context*>(context);
|
|
||||||
auto& account = host->accounts[*address];
|
|
||||||
auto prev_value = account.storage[*key];
|
|
||||||
account.storage[*key] = *value;
|
|
||||||
|
|
||||||
return (prev_value == *value) ? EVMC_STORAGE_UNCHANGED : EVMC_STORAGE_MODIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static evmc_uint256be get_balance(evmc_context* context, const evmc_address* address)
|
|
||||||
{
|
|
||||||
auto* host = static_cast<example_host_context*>(context);
|
|
||||||
auto it = host->accounts.find(*address);
|
|
||||||
if (it != host->accounts.end())
|
|
||||||
return it->second.balance;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t get_code_size(evmc_context* context, const evmc_address* address)
|
|
||||||
{
|
|
||||||
auto* host = static_cast<example_host_context*>(context);
|
|
||||||
auto it = host->accounts.find(*address);
|
|
||||||
if (it != host->accounts.end())
|
|
||||||
return it->second.code_size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static evmc_bytes32 get_code_hash(evmc_context* context, const evmc_address* address)
|
|
||||||
{
|
|
||||||
auto* host = static_cast<example_host_context*>(context);
|
|
||||||
auto it = host->accounts.find(*address);
|
|
||||||
if (it != host->accounts.end())
|
|
||||||
return it->second.code_hash;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t copy_code(evmc_context* context,
|
|
||||||
const evmc_address* address,
|
|
||||||
size_t code_offset,
|
|
||||||
uint8_t* buffer_data,
|
|
||||||
size_t buffer_size)
|
|
||||||
{
|
|
||||||
(void)context;
|
|
||||||
(void)address;
|
|
||||||
(void)code_offset;
|
|
||||||
(void)buffer_data;
|
|
||||||
(void)buffer_size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void selfdestruct(evmc_context* context,
|
|
||||||
const evmc_address* address,
|
|
||||||
const evmc_address* beneficiary)
|
|
||||||
{
|
|
||||||
(void)context;
|
|
||||||
(void)address;
|
|
||||||
(void)beneficiary;
|
|
||||||
}
|
|
||||||
|
|
||||||
static evmc_result call(evmc_context* context, const evmc_message* msg)
|
|
||||||
{
|
|
||||||
(void)context;
|
|
||||||
(void)msg;
|
|
||||||
evmc_result result{};
|
|
||||||
result.status_code = EVMC_FAILURE;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static evmc_tx_context get_tx_context(evmc_context* context)
|
|
||||||
{
|
|
||||||
(void)context;
|
|
||||||
evmc_tx_context result{};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static evmc_bytes32 get_block_hash(evmc_context* context, int64_t number)
|
|
||||||
{
|
|
||||||
auto* host = static_cast<example_host_context*>(context);
|
|
||||||
int64_t current_block_number = host->tx_context.block_number;
|
|
||||||
|
|
||||||
auto example_block_hash = evmc_bytes32{};
|
|
||||||
if (number < current_block_number && number >= current_block_number - 256)
|
|
||||||
example_block_hash = {{1, 1, 1, 1}};
|
|
||||||
return example_block_hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_log(evmc_context* context,
|
|
||||||
const evmc_address* address,
|
|
||||||
const uint8_t* data,
|
|
||||||
size_t data_size,
|
|
||||||
const evmc_bytes32 topics[],
|
|
||||||
size_t topics_count)
|
|
||||||
{
|
|
||||||
(void)context;
|
|
||||||
(void)address;
|
|
||||||
(void)data;
|
|
||||||
(void)data_size;
|
|
||||||
(void)topics;
|
|
||||||
(void)topics_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const evmc_host_interface interface = {
|
|
||||||
account_exists, get_storage, set_storage, get_balance, get_code_size, get_code_hash,
|
|
||||||
copy_code, selfdestruct, call, get_tx_context, get_block_hash, emit_log,
|
|
||||||
};
|
|
||||||
|
|
||||||
example_host_context::example_host_context() : evmc_context{&interface} {}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
evmc_context* example_host_create_context()
|
evmc_context* example_host_create_context()
|
||||||
{
|
{
|
||||||
return new example_host_context;
|
return new ExampleHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
void example_host_destroy_context(evmc_context* context)
|
void example_host_destroy_context(evmc_context* context)
|
||||||
{
|
{
|
||||||
delete context;
|
delete static_cast<ExampleHost*>(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,43 +79,87 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HostInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~HostInterface() noexcept = default;
|
||||||
|
|
||||||
|
virtual bool account_exists(const evmc_address& addr) noexcept = 0;
|
||||||
|
|
||||||
|
virtual evmc_bytes32 get_storage(const evmc_address& addr,
|
||||||
|
const evmc_bytes32& key) noexcept = 0;
|
||||||
|
|
||||||
|
virtual evmc_storage_status set_storage(const evmc_address& addr,
|
||||||
|
const evmc_bytes32& key,
|
||||||
|
const evmc_bytes32& value) noexcept = 0;
|
||||||
|
|
||||||
|
virtual evmc_uint256be get_balance(const evmc_address& addr) noexcept = 0;
|
||||||
|
|
||||||
|
virtual size_t get_code_size(const evmc_address& addr) noexcept = 0;
|
||||||
|
|
||||||
|
virtual evmc_bytes32 get_code_hash(const evmc_address& addr) noexcept = 0;
|
||||||
|
|
||||||
|
virtual size_t copy_code(const evmc_address& addr,
|
||||||
|
size_t code_offset,
|
||||||
|
uint8_t* buffer_data,
|
||||||
|
size_t buffer_size) noexcept = 0;
|
||||||
|
|
||||||
|
virtual void selfdestruct(const evmc_address& addr,
|
||||||
|
const evmc_address& beneficiary) noexcept = 0;
|
||||||
|
|
||||||
|
virtual result call(const evmc_message& msg) noexcept = 0;
|
||||||
|
|
||||||
|
virtual evmc_tx_context get_tx_context() noexcept = 0;
|
||||||
|
|
||||||
|
virtual evmc_bytes32 get_block_hash(int64_t block_number) noexcept = 0;
|
||||||
|
|
||||||
|
virtual void emit_log(const evmc_address& addr,
|
||||||
|
const uint8_t* data,
|
||||||
|
size_t data_size,
|
||||||
|
const evmc_bytes32 topics[],
|
||||||
|
size_t num_topics) noexcept = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Wrapper around EVMC host context / host interface.
|
/// Wrapper around EVMC host context / host interface.
|
||||||
class host
|
///
|
||||||
|
/// To be used by VM implementations as better alternative to using ::evmc_context directly.
|
||||||
|
class HostContext : public HostInterface
|
||||||
{
|
{
|
||||||
evmc_context* context = nullptr;
|
evmc_context* context = nullptr;
|
||||||
evmc_tx_context tx_context = {};
|
evmc_tx_context tx_context = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
host(evmc_context* context) noexcept : context{context} {}
|
HostContext(evmc_context* context) noexcept : context{context} {} // NOLINT
|
||||||
|
|
||||||
bool account_exists(const evmc_address& address) noexcept
|
bool account_exists(const evmc_address& address) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->account_exists(context, &address);
|
return context->host->account_exists(context, &address);
|
||||||
}
|
}
|
||||||
|
|
||||||
evmc_bytes32 get_storage(const evmc_address& address, const evmc_bytes32& key) noexcept
|
evmc_bytes32 get_storage(const evmc_address& address, const evmc_bytes32& key) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->get_storage(context, &address, &key);
|
return context->host->get_storage(context, &address, &key);
|
||||||
}
|
}
|
||||||
|
|
||||||
evmc_storage_status set_storage(const evmc_address& address,
|
evmc_storage_status set_storage(const evmc_address& address,
|
||||||
const evmc_bytes32& key,
|
const evmc_bytes32& key,
|
||||||
const evmc_bytes32& value) noexcept
|
const evmc_bytes32& value) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->set_storage(context, &address, &key, &value);
|
return context->host->set_storage(context, &address, &key, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
evmc_uint256be get_balance(const evmc_address& address) noexcept
|
evmc_uint256be get_balance(const evmc_address& address) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->get_balance(context, &address);
|
return context->host->get_balance(context, &address);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t get_code_size(const evmc_address& address) noexcept
|
size_t get_code_size(const evmc_address& address) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->get_code_size(context, &address);
|
return context->host->get_code_size(context, &address);
|
||||||
}
|
}
|
||||||
|
|
||||||
evmc_bytes32 get_code_hash(const evmc_address& address) noexcept
|
evmc_bytes32 get_code_hash(const evmc_address& address) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->get_code_hash(context, &address);
|
return context->host->get_code_hash(context, &address);
|
||||||
}
|
}
|
||||||
@ -123,17 +167,17 @@ public:
|
|||||||
size_t copy_code(const evmc_address& address,
|
size_t copy_code(const evmc_address& address,
|
||||||
size_t code_offset,
|
size_t code_offset,
|
||||||
uint8_t* buffer_data,
|
uint8_t* buffer_data,
|
||||||
size_t buffer_size) noexcept
|
size_t buffer_size) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->copy_code(context, &address, code_offset, buffer_data, buffer_size);
|
return context->host->copy_code(context, &address, code_offset, buffer_data, buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void selfdestruct(const evmc_address& address, const evmc_address& beneficiary)
|
void selfdestruct(const evmc_address& address, const evmc_address& beneficiary) noexcept final
|
||||||
{
|
{
|
||||||
context->host->selfdestruct(context, &address, &beneficiary);
|
context->host->selfdestruct(context, &address, &beneficiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
result call(const evmc_message& message) noexcept
|
result call(const evmc_message& message) noexcept final
|
||||||
{
|
{
|
||||||
return result{context->host->call(context, &message)};
|
return result{context->host->call(context, &message)};
|
||||||
}
|
}
|
||||||
@ -143,15 +187,15 @@ public:
|
|||||||
/// The implementation caches the received transaction context
|
/// The implementation caches the received transaction context
|
||||||
/// by assuming that the block timestamp should never be zero.
|
/// by assuming that the block timestamp should never be zero.
|
||||||
///
|
///
|
||||||
/// @return Reference to the cached transaction context.
|
/// @return The cached transaction context.
|
||||||
const evmc_tx_context& get_tx_context() noexcept
|
evmc_tx_context get_tx_context() noexcept final
|
||||||
{
|
{
|
||||||
if (tx_context.block_timestamp == 0)
|
if (tx_context.block_timestamp == 0)
|
||||||
tx_context = context->host->get_tx_context(context);
|
tx_context = context->host->get_tx_context(context);
|
||||||
return tx_context;
|
return tx_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
evmc_bytes32 get_block_hash(int64_t number) noexcept
|
evmc_bytes32 get_block_hash(int64_t number) noexcept final
|
||||||
{
|
{
|
||||||
return context->host->get_block_hash(context, number);
|
return context->host->get_block_hash(context, number);
|
||||||
}
|
}
|
||||||
@ -160,9 +204,96 @@ public:
|
|||||||
const uint8_t* data,
|
const uint8_t* data,
|
||||||
size_t data_size,
|
size_t data_size,
|
||||||
const evmc_bytes32 topics[],
|
const evmc_bytes32 topics[],
|
||||||
size_t topics_count) noexcept
|
size_t topics_count) noexcept final
|
||||||
{
|
{
|
||||||
context->host->emit_log(context, &address, data, data_size, topics, topics_count);
|
context->host->emit_log(context, &address, data, data_size, topics, topics_count);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Abstract class to be used by Host implementations.
|
||||||
|
///
|
||||||
|
/// When implementing EVMC Host, you can directly inherit from the evmc::Host class.
|
||||||
|
/// This way your implementation will be simpler by avoiding manual handling
|
||||||
|
/// of the ::evmc_context and the ::evmc_context::host.
|
||||||
|
class Host : public HostInterface, public evmc_context
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline Host() noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
inline bool account_exists(evmc_context* h, const evmc_address* addr) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->account_exists(*addr);
|
||||||
|
}
|
||||||
|
inline evmc_bytes32 get_storage(evmc_context* h,
|
||||||
|
const evmc_address* addr,
|
||||||
|
const evmc_bytes32* key) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->get_storage(*addr, *key);
|
||||||
|
}
|
||||||
|
inline evmc_storage_status set_storage(evmc_context* h,
|
||||||
|
const evmc_address* addr,
|
||||||
|
const evmc_bytes32* key,
|
||||||
|
const evmc_bytes32* value) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->set_storage(*addr, *key, *value);
|
||||||
|
}
|
||||||
|
inline evmc_uint256be get_balance(evmc_context* h, const evmc_address* addr) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->get_balance(*addr);
|
||||||
|
}
|
||||||
|
inline size_t get_code_size(evmc_context* h, const evmc_address* addr) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->get_code_size(*addr);
|
||||||
|
}
|
||||||
|
inline evmc_bytes32 get_code_hash(evmc_context* h, const evmc_address* addr) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->get_code_hash(*addr);
|
||||||
|
}
|
||||||
|
inline size_t copy_code(evmc_context* h,
|
||||||
|
const evmc_address* addr,
|
||||||
|
size_t code_offset,
|
||||||
|
uint8_t* buffer_data,
|
||||||
|
size_t buffer_size) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->copy_code(*addr, code_offset, buffer_data, buffer_size);
|
||||||
|
}
|
||||||
|
inline void selfdestruct(evmc_context* h,
|
||||||
|
const evmc_address* addr,
|
||||||
|
const evmc_address* beneficiary) noexcept
|
||||||
|
{
|
||||||
|
static_cast<Host*>(h)->selfdestruct(*addr, *beneficiary);
|
||||||
|
}
|
||||||
|
inline evmc_result call(evmc_context* h, const evmc_message* msg) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->call(*msg);
|
||||||
|
}
|
||||||
|
inline evmc_tx_context get_tx_context(evmc_context* h) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->get_tx_context();
|
||||||
|
}
|
||||||
|
inline evmc_bytes32 get_block_hash(evmc_context* h, int64_t block_number) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<Host*>(h)->get_block_hash(block_number);
|
||||||
|
}
|
||||||
|
inline void emit_log(evmc_context* h,
|
||||||
|
const evmc_address* addr,
|
||||||
|
const uint8_t* data,
|
||||||
|
size_t data_size,
|
||||||
|
const evmc_bytes32 topics[],
|
||||||
|
size_t num_topics) noexcept
|
||||||
|
{
|
||||||
|
static_cast<Host*>(h)->emit_log(*addr, data, data_size, topics, num_topics);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr evmc_host_interface interface{
|
||||||
|
account_exists, get_storage, set_storage, get_balance, get_code_size, get_code_hash,
|
||||||
|
copy_code, selfdestruct, call, get_tx_context, get_block_hash, emit_log,
|
||||||
|
};
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
inline Host::Host() noexcept : evmc_context{&internal::interface} {}
|
||||||
|
|
||||||
} // namespace evmc
|
} // namespace evmc
|
||||||
|
@ -69,7 +69,7 @@ TEST(cpp, host)
|
|||||||
// Use example host to execute all methods from the C++ host wrapper.
|
// Use example host to execute all methods from the C++ host wrapper.
|
||||||
|
|
||||||
auto* host_context = example_host_create_context();
|
auto* host_context = example_host_create_context();
|
||||||
auto host = evmc::host{host_context};
|
auto host = evmc::HostContext{host_context};
|
||||||
|
|
||||||
auto a = evmc_address{{1}};
|
auto a = evmc_address{{1}};
|
||||||
auto v = evmc_bytes32{{7, 7, 7}};
|
auto v = evmc_bytes32{{7, 7, 7}};
|
||||||
@ -89,8 +89,8 @@ TEST(cpp, host)
|
|||||||
host.selfdestruct(a, a);
|
host.selfdestruct(a, a);
|
||||||
EXPECT_EQ(host.call({}).gas_left, 0);
|
EXPECT_EQ(host.call({}).gas_left, 0);
|
||||||
|
|
||||||
auto* tx = &host.get_tx_context();
|
auto tx = host.get_tx_context();
|
||||||
EXPECT_EQ(&host.get_tx_context(), tx);
|
EXPECT_EQ(host.get_tx_context().block_number, tx.block_number);
|
||||||
|
|
||||||
EXPECT_EQ(host.get_block_hash(0), evmc_bytes32{});
|
EXPECT_EQ(host.get_block_hash(0), evmc_bytes32{});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user