From ca85b77f57c349068b55297adeb380fada66657e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Sep 2018 08:48:19 +0200 Subject: [PATCH 1/4] Return bool from evmc_get_balance_fn() --- bindings/go/evmc/host.c | 4 ++-- bindings/go/evmc/host.go | 10 +++++++--- examples/example_host.cpp | 3 ++- include/evmc/evmc.h | 19 ++++++++++++------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/bindings/go/evmc/host.c b/bindings/go/evmc/host.c index dc2cce26b..c2bf70d98 100644 --- a/bindings/go/evmc/host.c +++ b/bindings/go/evmc/host.c @@ -69,8 +69,8 @@ static inline void go_exported_functions_type_checks() storage_status = setStorage(context, address, uint256be, uint256be); evmc_get_balance_fn get_balance_fn = NULL; - get_balance_fn(uint256be, context, address); - getBalance(uint256be, context, address); + bool_flag = get_balance_fn(uint256be, context, address); + bool_flag = getBalance(uint256be, context, address); evmc_get_code_size_fn get_code_size_fn = NULL; size = get_code_size_fn(context, address); diff --git a/bindings/go/evmc/host.go b/bindings/go/evmc/host.go index aca9d9d84..b83ddc1d9 100644 --- a/bindings/go/evmc/host.go +++ b/bindings/go/evmc/host.go @@ -73,7 +73,7 @@ type HostContext interface { AccountExists(addr common.Address) bool GetStorage(addr common.Address, key common.Hash) common.Hash SetStorage(addr common.Address, key common.Hash, value common.Hash) StorageStatus - GetBalance(addr common.Address) common.Hash + GetBalance(addr common.Address) (common.Hash, error) GetCodeSize(addr common.Address) int GetCodeHash(addr common.Address) common.Hash GetCode(addr common.Address) []byte @@ -110,11 +110,15 @@ func setStorage(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.struc } //export getBalance -func getBalance(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) { +func getBalance(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.bool { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - balance := ctx.GetBalance(goAddress(*pAddr)) + balance, err := ctx.GetBalance(goAddress(*pAddr)) + if err != nil { + return false + } *pResult = evmcUint256be(balance) + return true } //export getCodeSize diff --git a/examples/example_host.cpp b/examples/example_host.cpp index 4974df472..d98c6d9b9 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -54,9 +54,10 @@ static enum evmc_storage_status set_storage(evmc_context* context, return EVMC_STORAGE_UNCHANGED; } -static void get_balance(evmc_uint256be* result, evmc_context* context, const evmc_address* address) +static bool get_balance(evmc_uint256be* result, evmc_context* context, const evmc_address* address) { *result = balance(context, address); + return true; } static size_t get_code_size(evmc_context* context, const evmc_address* address) diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index 50aa6836a..5d54b2e04 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -475,14 +475,19 @@ typedef enum evmc_storage_status (*evmc_set_storage_fn)(struct evmc_context* con /** * Get balance callback function. * - * This callback function is used by an EVM to query the balance of the given - * address. - * @param[out] result The returned balance value. - * @param context The pointer to the Host execution context. - * @see ::evmc_context. - * @param address The address. + * This callback function is used by a VM to query the balance of the given address. + * + * @param[out] result The pointer to the place where to put the result balance. + * The pointed memory is only modified when the function returns true. + * The pointer MUST NOT be null. + * @param context The pointer to the Host execution context. + * @param address The address of the account. + * @return If the account exists its balance is put at the location + * pointed by @p result and true is returned. + * If the account does not exist false is returned without + * modifying the memory pointed by @p result. */ -typedef void (*evmc_get_balance_fn)(struct evmc_uint256be* result, +typedef bool (*evmc_get_balance_fn)(struct evmc_uint256be* result, struct evmc_context* context, const struct evmc_address* address); From d6ef55154106022ef62b7cd24a6ebce25426e8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Sep 2018 11:46:00 +0200 Subject: [PATCH 2/4] Return bool from evmc_get_code_hash_fn() --- bindings/go/evmc/host.c | 4 ++-- bindings/go/evmc/host.go | 11 ++++++++--- examples/example_host.cpp | 3 ++- include/evmc/evmc.h | 19 ++++++++++++++----- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/bindings/go/evmc/host.c b/bindings/go/evmc/host.c index c2bf70d98..9852325b1 100644 --- a/bindings/go/evmc/host.c +++ b/bindings/go/evmc/host.c @@ -77,8 +77,8 @@ static inline void go_exported_functions_type_checks() size = getCodeSize(context, address); evmc_get_code_hash_fn get_code_hash_fn = NULL; - get_code_hash_fn(uint256be, context, address); - getCodeHash(uint256be, context, address); + bool_flag = get_code_hash_fn(uint256be, context, address); + bool_flag = getCodeHash(uint256be, context, address); evmc_copy_code_fn copy_code_fn = NULL; size = copy_code_fn(context, address, size, data, size); diff --git a/bindings/go/evmc/host.go b/bindings/go/evmc/host.go index b83ddc1d9..47ddae913 100644 --- a/bindings/go/evmc/host.go +++ b/bindings/go/evmc/host.go @@ -75,7 +75,7 @@ type HostContext interface { SetStorage(addr common.Address, key common.Hash, value common.Hash) StorageStatus GetBalance(addr common.Address) (common.Hash, error) GetCodeSize(addr common.Address) int - GetCodeHash(addr common.Address) common.Hash + GetCodeHash(addr common.Address) (common.Hash, error) GetCode(addr common.Address) []byte Selfdestruct(addr common.Address, beneficiary common.Address) GetTxContext() (gasPrice common.Hash, origin common.Address, coinbase common.Address, number int64, timestamp int64, @@ -129,10 +129,15 @@ func getCodeSize(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.size_t { } //export getCodeHash -func getCodeHash(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) { +func getCodeHash(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.bool { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - *pResult = evmcUint256be(ctx.GetCodeHash(goAddress(*pAddr))) + codeHash, err := ctx.GetCodeHash(goAddress(*pAddr)) + if err != nil { + return false + } + *pResult = evmcUint256be(codeHash) + return true } //export copyCode diff --git a/examples/example_host.cpp b/examples/example_host.cpp index d98c6d9b9..98e073d71 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -67,13 +67,14 @@ static size_t get_code_size(evmc_context* context, const evmc_address* address) return 0; } -static void get_code_hash(evmc_uint256be* result, +static bool get_code_hash(evmc_uint256be* result, evmc_context* context, const evmc_address* address) { (void)result; (void)context; (void)address; + return false; } static size_t copy_code(evmc_context* context, diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index 5d54b2e04..8c389933a 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -504,12 +504,21 @@ typedef size_t (*evmc_get_code_size_fn)(struct evmc_context* context, /** * Get code size callback function. * - * This callback function is used by an EVM to get the keccak256 hash of the code stored - * in the account at the given address. For accounts not having a code, this - * function returns keccak256 hash of empty data. For accounts not existing in the state, - * this function returns 0. + * This callback function is used by a VM to get the keccak256 hash of the code stored + * in the account at the given address. For existing accounts not having a code, this + * function returns keccak256 hash of empty data. + * + * @param[out] result The pointer to the place where to put the result code hash. + * The pointed memory is only modified when the function returns true. + * The pointer MUST NOT be null. + * @param context The pointer to the Host execution context. + * @param address The address of the account. + * @return If the account exists the hash of its code is put at the location + * pointed by @p result and true is returned. + * If the account does not exist false is returned without + * modifying the memory pointed by @p result. */ -typedef void (*evmc_get_code_hash_fn)(struct evmc_uint256be* result, +typedef bool (*evmc_get_code_hash_fn)(struct evmc_uint256be* result, struct evmc_context* context, const struct evmc_address* address); From b8b3719fb912711214260f9274893364cdc7b15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Sep 2018 11:57:34 +0200 Subject: [PATCH 3/4] Return bool from evmc_get_code_size_fn() --- bindings/go/evmc/host.c | 4 ++-- bindings/go/evmc/host.go | 11 ++++++++--- examples/example_host.cpp | 5 +++-- include/evmc/evmc.h | 20 +++++++++++++++----- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/bindings/go/evmc/host.c b/bindings/go/evmc/host.c index 9852325b1..6b75cbc0d 100644 --- a/bindings/go/evmc/host.c +++ b/bindings/go/evmc/host.c @@ -73,8 +73,8 @@ static inline void go_exported_functions_type_checks() bool_flag = getBalance(uint256be, context, address); evmc_get_code_size_fn get_code_size_fn = NULL; - size = get_code_size_fn(context, address); - size = getCodeSize(context, address); + bool_flag = get_code_size_fn(&size, context, address); + bool_flag = getCodeSize(&size, context, address); evmc_get_code_hash_fn get_code_hash_fn = NULL; bool_flag = get_code_hash_fn(uint256be, context, address); diff --git a/bindings/go/evmc/host.go b/bindings/go/evmc/host.go index 47ddae913..0a97aa844 100644 --- a/bindings/go/evmc/host.go +++ b/bindings/go/evmc/host.go @@ -74,7 +74,7 @@ type HostContext interface { GetStorage(addr common.Address, key common.Hash) common.Hash SetStorage(addr common.Address, key common.Hash, value common.Hash) StorageStatus GetBalance(addr common.Address) (common.Hash, error) - GetCodeSize(addr common.Address) int + GetCodeSize(addr common.Address) (int, error) GetCodeHash(addr common.Address) (common.Hash, error) GetCode(addr common.Address) []byte Selfdestruct(addr common.Address, beneficiary common.Address) @@ -122,10 +122,15 @@ func getBalance(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C. } //export getCodeSize -func getCodeSize(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.size_t { +func getCodeSize(pResult *C.size_t, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.bool { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - return C.size_t(ctx.GetCodeSize(goAddress(*pAddr))) + codeSize, err := ctx.GetCodeSize(goAddress(*pAddr)) + if err != nil { + return false + } + *pResult = C.size_t(codeSize) + return true } //export getCodeHash diff --git a/examples/example_host.cpp b/examples/example_host.cpp index 98e073d71..23e46c97b 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -60,11 +60,12 @@ static bool get_balance(evmc_uint256be* result, evmc_context* context, const evm return true; } -static size_t get_code_size(evmc_context* context, const evmc_address* address) +static bool get_code_size(size_t* result, evmc_context* context, const evmc_address* address) { + (void)result; (void)context; (void)address; - return 0; + return false; } static bool get_code_hash(evmc_uint256be* result, diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index 8c389933a..bb8b08468 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -494,12 +494,22 @@ typedef bool (*evmc_get_balance_fn)(struct evmc_uint256be* result, /** * Get code size callback function. * - * This callback function is used by an EVM to get the size of the code stored - * in the account at the given address. For accounts not having a code, this - * function returns 0. + * This callback function is used by a VM to get the size of the code stored + * in the account at the given address. + * + * @param[out] result The pointer to the place where to put the result code size. + * The pointed memory is only modified when the function returns true. + * The pointer MUST NOT be null. + * @param context The pointer to the Host execution context. + * @param address The address of the account. + * @return If the account exists the size of its code is put at the location + * pointed by @p result and true is returned. + * If the account does not exist false is returned without + * modifying the memory pointed by @p result. */ -typedef size_t (*evmc_get_code_size_fn)(struct evmc_context* context, - const struct evmc_address* address); +typedef bool (*evmc_get_code_size_fn)(size_t* result, + struct evmc_context* context, + const struct evmc_address* address); /** * Get code size callback function. From 8ea48035ead5c192f615f0880f9542b603d5a33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Sep 2018 12:20:19 +0200 Subject: [PATCH 4/4] examples: Make some example Host methods a bit more interesting --- examples/example_host.cpp | 68 ++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/examples/example_host.cpp b/examples/example_host.cpp index 23e46c97b..e675f8689 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -9,26 +9,42 @@ #include +#include +#include + +/// The comparator for std::map. +bool operator<(const evmc_address& a, const evmc_address& b) +{ + return std::memcmp(a.bytes, b.bytes, sizeof(a)) < 0; +} + +/// The comparator for std::map. +bool operator<(const evmc_uint256be& a, const evmc_uint256be& b) +{ + return std::memcmp(a.bytes, b.bytes, sizeof(a)) < 0; +} + +struct account +{ + evmc_uint256be balance = {}; + size_t code_size = 0; + evmc_uint256be code_hash = {}; + std::map storage; +}; + struct example_host_context : evmc_context { example_host_context(); evmc_tx_context tx_context = {}; -}; -static evmc_uint256be balance(evmc_context* context, const evmc_address* address) -{ - (void)context; - (void)address; - evmc_uint256be ret = {{1, 2, 3, 4}}; - return ret; -} + std::map accounts; +}; static bool account_exists(evmc_context* context, const evmc_address* address) { - (void)context; - (void)address; - return false; + example_host_context* host = static_cast(context); + return host->accounts.find(*address) != host->accounts.end(); } static void get_storage(evmc_uint256be* result, @@ -56,15 +72,25 @@ static enum evmc_storage_status set_storage(evmc_context* context, static bool get_balance(evmc_uint256be* result, evmc_context* context, const evmc_address* address) { - *result = balance(context, address); - return true; + example_host_context* host = static_cast(context); + auto it = host->accounts.find(*address); + if (it != host->accounts.end()) + { + *result = it->second.balance; + return true; + } + return false; } static bool get_code_size(size_t* result, evmc_context* context, const evmc_address* address) { - (void)result; - (void)context; - (void)address; + example_host_context* host = static_cast(context); + auto it = host->accounts.find(*address); + if (it != host->accounts.end()) + { + *result = it->second.code_size; + return true; + } return false; } @@ -72,9 +98,13 @@ static bool get_code_hash(evmc_uint256be* result, evmc_context* context, const evmc_address* address) { - (void)result; - (void)context; - (void)address; + example_host_context* host = static_cast(context); + auto it = host->accounts.find(*address); + if (it != host->accounts.end()) + { + *result = it->second.code_hash; + return true; + } return false; }