Skip to content

Commit

Permalink
Add transaction initcodes support
Browse files Browse the repository at this point in the history
Co-authored-by: pdobacz <[email protected]>
  • Loading branch information
gumb0 and pdobacz committed Mar 13, 2024
1 parent f89284f commit 3a6b2a3
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 3 deletions.
7 changes: 7 additions & 0 deletions bindings/go/evmc/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const struct evmc_host_interface evmc_go_host = {
(evmc_selfdestruct_fn)selfdestruct,
(evmc_call_fn)call,
(evmc_get_tx_context_fn)getTxContext,
(evmc_get_tx_initcode_by_hash_fn)getTxInitcodeByHash,
(evmc_get_block_hash_fn)getBlockHash,
(evmc_emit_log_fn)emitLog,
(evmc_access_account_fn)accessAccount,
Expand All @@ -47,6 +48,8 @@ static inline void go_exported_functions_type_checks()
(void)uint256be;
struct evmc_tx_context tx_context;
(void)tx_context;
struct evmc_tx_initcode tx_initcode;
(void)tx_initcode;
struct evmc_result result;
(void)result;
enum evmc_access_status access_status;
Expand Down Expand Up @@ -96,6 +99,10 @@ static inline void go_exported_functions_type_checks()
tx_context = get_tx_context_fn(context);
tx_context = getTxContext(context);

evmc_get_tx_initcode_by_hash_fn get_tx_initcode_by_hash_fn = NULL;
tx_initcode = get_tx_initcode_by_hash_fn(context, &bytes32);
tx_initcode = getTxInitcodeByHash(context, &bytes32);

evmc_get_block_hash_fn get_block_hash_fn = NULL;
bytes32 = get_block_hash_fn(context, number);
bytes32 = getBlockHash(context, number);
Expand Down
11 changes: 11 additions & 0 deletions bindings/go/evmc/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ type HostContext interface {
GetCode(addr Address) []byte
Selfdestruct(addr Address, beneficiary Address) bool
GetTxContext() TxContext
GetTxInitcodeByHash(hash Hash) []byte
GetBlockHash(number int64) Hash
EmitLog(addr Address, topics []Hash, data []byte)
Call(kind CallKind,
Expand Down Expand Up @@ -191,6 +192,16 @@ func getTxContext(pCtx unsafe.Pointer) C.struct_evmc_tx_context {
}
}

//export getTxInitcodeByHash
func getTxInitcodeByHash(pCtx unsafe.Pointer, pHash *C.evmc_bytes32) C.struct_evmc_tx_initcode {
ctx := getHostContext(uintptr(pCtx))
txInitcode := ctx.GetTxInitcodeByHash(goHash(*pHash))
if txInitcode == nil {
return C.struct_evmc_tx_initcode{(*C.uint8_t)(nil), 0}
}
return C.struct_evmc_tx_initcode{(*C.uint8_t)(&txInitcode[0]), C.size_t(len(txInitcode))}
}

//export getBlockHash
func getBlockHash(pCtx unsafe.Pointer, number int64) C.evmc_bytes32 {
ctx := getHostContext(uintptr(pCtx))
Expand Down
4 changes: 4 additions & 0 deletions bindings/go/evmc/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ func (host *testHostContext) GetTxContext() TxContext {
return txContext
}

func (host *testHostContext) GetTxInitcodeByHash(hash Hash) []byte {
return nil
}

func (host *testHostContext) GetBlockHash(number int64) Hash {
return Hash{}
}
Expand Down
1 change: 1 addition & 0 deletions bindings/rust/evmc-vm/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ mod tests {
selfdestruct: None,
call: None,
get_tx_context: Some(get_dummy_tx_context),
// FIXME(piotr) get_tx_initcode_by_hash
get_block_hash: None,
emit_log: None,
access_account: None,
Expand Down
1 change: 1 addition & 0 deletions bindings/rust/evmc-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,7 @@ mod tests {
selfdestruct: None,
call: Some(execute_call),
get_tx_context: Some(get_dummy_tx_context),
// FIXME(piotr) get_tx_initcode_by_hash
get_block_hash: None,
emit_log: None,
access_account: None,
Expand Down
6 changes: 6 additions & 0 deletions examples/example_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

/// @file
/// Example implementation of an EVMC Host.
/// TODO: Doesn't support TXCREATE transaction initcodes.

#include "example_host.h"

Expand Down Expand Up @@ -140,6 +141,11 @@ class ExampleHost : public evmc::Host

evmc_tx_context get_tx_context() const noexcept final { return tx_context; }

evmc_tx_initcode get_tx_initcode_by_hash(const evmc_bytes32& /* hash */) const noexcept final
{
return {nullptr, 0};
}

// NOLINTNEXTLINE(bugprone-exception-escape)
evmc::bytes32 get_block_hash(int64_t number) const noexcept final
{
Expand Down
30 changes: 27 additions & 3 deletions include/evmc/evmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ struct evmc_message
/**
* The optional value used in new contract address construction.
*
* Needed only for a Host to calculate created address when kind is ::EVMC_CREATE2.
* Ignored in evmc_execute_fn().
* Needed only for a Host to calculate created address when kind is ::EVMC_CREATE2,
* ::EVMC_EOFCREATE. Ignored in evmc_execute_fn().
*/
evmc_bytes32 create2_salt;

Expand All @@ -180,7 +180,7 @@ struct evmc_message
* For ::EVMC_CALLCODE or ::EVMC_DELEGATECALL this may be different from
* the evmc_message::recipient.
* Not required when invoking evmc_execute_fn(), only when invoking evmc_call_fn().
* Ignored if kind is ::EVMC_CREATE or ::EVMC_CREATE2.
* Ignored if kind is ::EVMC_CREATE, ::EVMC_CREATE2, ::EVMC_EOFCREATE.
*
* In case of ::EVMC_CAPABILITY_PRECOMPILES implementation, this fields should be inspected
* to identify the requested precompile.
Expand Down Expand Up @@ -218,6 +218,13 @@ struct evmc_tx_context
size_t blob_hashes_count; /**< The number of blob hashes (EIP-4844). */
};

/** Return value of the get initcode by hash query (TXCREATE). */
struct evmc_tx_initcode
{
const uint8_t* data; /**< Initcode. NULL means no initcode with such hash given. */
size_t size; /**< Size of data. */
};

/**
* @struct evmc_host_context
* The opaque data type representing the Host execution context.
Expand All @@ -236,6 +243,20 @@ struct evmc_host_context;
*/
typedef struct evmc_tx_context (*evmc_get_tx_context_fn)(struct evmc_host_context* context);

/**
* Get transaction initcode by hash callback function.
*
* This callback function is used by an EVM to retrieve an initcode to
* be supplied to a TXCREATE instruction. Should return result with NULL in case there is no
* initcode with such hash.
*
* @param context The pointer to the Host execution context.
* @param hash The hash of the initcode to get.
* @return The initcode.
*/
typedef struct evmc_tx_initcode (
*evmc_get_tx_initcode_by_hash_fn)(struct evmc_host_context* context, const evmc_bytes32* hash);

/**
* Get block hash callback function.
*
Expand Down Expand Up @@ -863,6 +884,9 @@ struct evmc_host_interface
/** Get transaction context callback function. */
evmc_get_tx_context_fn get_tx_context;

/** Get transaction initcode by hash callback function. */
evmc_get_tx_initcode_by_hash_fn get_tx_initcode_by_hash;

/** Get block hash callback function. */
evmc_get_block_hash_fn get_block_hash;

Expand Down
16 changes: 16 additions & 0 deletions include/evmc/evmc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,9 @@ class HostInterface
/// @copydoc evmc_host_interface::get_tx_context
virtual evmc_tx_context get_tx_context() const noexcept = 0;

/// @copydoc evmc_host_interface::get_tx_initcode_by_hash
virtual evmc_tx_initcode get_tx_initcode_by_hash(const evmc_bytes32& hash) const noexcept = 0;

/// @copydoc evmc_host_interface::get_block_hash
virtual bytes32 get_block_hash(int64_t block_number) const noexcept = 0;

Expand Down Expand Up @@ -577,6 +580,12 @@ class HostContext : public HostInterface
/// @copydoc HostInterface::get_tx_context()
evmc_tx_context get_tx_context() const noexcept final { return host->get_tx_context(context); }

/// @copydoc HostInterface::get_tx_initcode_by_hash()
evmc_tx_initcode get_tx_initcode_by_hash(const evmc_bytes32& hash) const noexcept final
{
return host->get_tx_initcode_by_hash(context, &hash);
}

bytes32 get_block_hash(int64_t number) const noexcept final
{
return host->get_block_hash(context, number);
Expand Down Expand Up @@ -838,6 +847,12 @@ inline evmc_tx_context get_tx_context(evmc_host_context* h) noexcept
return Host::from_context(h)->get_tx_context();
}

inline evmc_tx_initcode get_tx_initcode_by_hash(evmc_host_context* h,
const evmc_bytes32* hash) noexcept
{
return Host::from_context(h)->get_tx_initcode_by_hash(*hash);
}

inline evmc_bytes32 get_block_hash(evmc_host_context* h, int64_t block_number) noexcept
{
return Host::from_context(h)->get_block_hash(block_number);
Expand Down Expand Up @@ -895,6 +910,7 @@ inline const evmc_host_interface& Host::get_interface() noexcept
::evmc::internal::selfdestruct,
::evmc::internal::call,
::evmc::internal::get_tx_context,
::evmc::internal::get_tx_initcode_by_hash,
::evmc::internal::get_block_hash,
::evmc::internal::emit_log,
::evmc::internal::access_account,
Expand Down
14 changes: 14 additions & 0 deletions include/evmc/mocked_host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class MockedHost : public Host
/// The EVMC transaction context to be returned by get_tx_context().
evmc_tx_context tx_context = {};

/// The TXCREATE initcodes to be returned by get_tx_initcode_by_hash(hash).
std::unordered_map<bytes32, bytes> tx_initcodes;

/// The block header hash value to be returned by get_block_hash().
bytes32 block_hash = {};

Expand Down Expand Up @@ -407,6 +410,17 @@ class MockedHost : public Host
/// Get transaction context (EVMC host method).
evmc_tx_context get_tx_context() const noexcept override { return tx_context; }

/// Get transaction initcode by hash (EVMC host method).
evmc_tx_initcode get_tx_initcode_by_hash(const evmc_bytes32& hash) const noexcept override
{
if (const auto& it = tx_initcodes.find(hash); it != tx_initcodes.end())
{
return evmc_tx_initcode{it->second.data(), it->second.size()};
}

return evmc_tx_initcode{nullptr, 0};
}

/// Get the block header hash (EVMC host method).
bytes32 get_block_hash(int64_t block_number) const noexcept override
{
Expand Down
5 changes: 5 additions & 0 deletions test/unittests/cpp_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class NullHost : public evmc::Host

evmc_tx_context get_tx_context() const noexcept final { return {}; }

evmc_tx_initcode get_tx_initcode_by_hash(const evmc_bytes32&) const noexcept final
{
return {};
}

evmc::bytes32 get_block_hash(int64_t /*block_number*/) const noexcept final { return {}; }

void emit_log(const evmc::address& /*addr*/,
Expand Down

0 comments on commit 3a6b2a3

Please sign in to comment.