diff --git a/bindings/go/evmc/host.c b/bindings/go/evmc/host.c index d9975c8..d007fa3 100644 --- a/bindings/go/evmc/host.c +++ b/bindings/go/evmc/host.c @@ -97,8 +97,8 @@ static inline void go_exported_functions_type_checks() tx_context = getTxContext(context); evmc_get_block_hash_fn get_block_hash_fn = NULL; - get_block_hash_fn(uint256be, context, number); - getBlockHash(uint256be, context, number); + status = get_block_hash_fn(uint256be, context, number); + status = getBlockHash(uint256be, context, number); evmc_emit_log_fn emit_log_fn = NULL; emit_log_fn(context, address, data, size, uint256be, size); diff --git a/bindings/go/evmc/host.go b/bindings/go/evmc/host.go index 992bc8d..d9f787f 100644 --- a/bindings/go/evmc/host.go +++ b/bindings/go/evmc/host.go @@ -79,7 +79,7 @@ type HostContext interface { Selfdestruct(addr common.Address, beneficiary common.Address) GetTxContext() (gasPrice common.Hash, origin common.Address, coinbase common.Address, number int64, timestamp int64, gasLimit int64, difficulty common.Hash) - GetBlockHash(number int64) common.Hash + GetBlockHash(number int64) (common.Hash, error) EmitLog(addr common.Address, topics []common.Hash, data []byte) Call(kind CallKind, destination common.Address, sender common.Address, value *big.Int, input []byte, gas int64, depth int, @@ -182,11 +182,17 @@ func getTxContext(pCtx unsafe.Pointer) C.struct_evmc_tx_context { } //export getBlockHash -func getBlockHash(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, number int64) { +func getBlockHash(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, number int64) C.int { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - *pResult = evmcUint256be(ctx.GetBlockHash(number)) + blockhash, err := ctx.GetBlockHash(number) + if err != nil { + return C.int(0) + } + + *pResult = evmcUint256be(blockhash) + return C.int(1) } //export emitLog diff --git a/examples/example_host.cpp b/examples/example_host.cpp index a24a174..105f316 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -9,6 +9,13 @@ #include +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; @@ -107,11 +114,17 @@ static evmc_tx_context get_tx_context(evmc_context* context) return result; } -static void get_block_hash(evmc_uint256be* result, evmc_context* context, int64_t number) +static int get_block_hash(evmc_uint256be* result, evmc_context* context, int64_t number) { - (void)result; - (void)context; - (void)number; + example_host_context* host = static_cast(context); + int64_t current_block_number = host->tx_context.block_number; + + if (number >= current_block_number || number < current_block_number - 256) + return 0; + + evmc_uint256be example_block_hash{}; + *result = example_block_hash; + return 1; } static void emit_log(evmc_context* context, @@ -134,10 +147,7 @@ static const evmc_host_interface interface = { copy_code, selfdestruct, call, get_tx_context, get_block_hash, emit_log, }; -struct example_host_context : evmc_context -{ - example_host_context() : evmc_context{&interface} {} -}; +example_host_context::example_host_context() : evmc_context{&interface} {} extern "C" { diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index fc4b6f1..4d26d34 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -153,17 +153,19 @@ typedef struct evmc_tx_context (*evmc_get_tx_context_fn)(struct evmc_context* co /** * Get block hash callback function. * - * This callback function is used by an EVM to query the block hash of - * a given block. + * This callback function is used by an VM to query the block hash of + * a given block. If the requested block is not found, then an appropriate + * result code is returned. * - * @param[out] result The returned block hash value. + * @param[out] result The returned block hash value. Only written to + * if the return value is 1 (information is avialable). * @param context The pointer to the Host execution context. - * @param number The block number. Must be a value between - * (and including) 0 and 255. + * @param number The block number. + * @return 1 if the information is available, 0 otherwise. */ -typedef void (*evmc_get_block_hash_fn)(struct evmc_uint256be* result, - struct evmc_context* context, - int64_t number); +typedef int (*evmc_get_block_hash_fn)(struct evmc_uint256be* result, + struct evmc_context* context, + int64_t number); /** * The execution status code.