From 2aa1623203c677cd9b9408a493139aa036e3a9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 7 Aug 2017 18:44:43 +0200 Subject: [PATCH 1/5] EVM-C: Move balance query to separated callback function --- examples/capi.c | 14 ++++++++++---- include/evm.h | 19 +++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/examples/capi.c b/examples/capi.c index dad8e34..8d6cb27 100644 --- a/examples/capi.c +++ b/examples/capi.c @@ -35,10 +35,6 @@ static void query(union evm_variant* result, result->data_size = 0; break; - case EVM_BALANCE: - result->uint256be = balance(env, address); - break; - case EVM_ACCOUNT_EXISTS: result->int64 = 0; break; @@ -68,6 +64,15 @@ static void set_storage(struct evm_env* env, printf("\n"); } +static void get_balance(struct evm_uint256be* result, + struct evm_env* env, + const struct evm_uint160be* address) +{ + printf("EVM-C: BALANCE @"); + print_address(address); + printf("\n"); +} + static void selfdestruct(struct evm_env* env, const struct evm_uint160be* address, const struct evm_uint160be* beneficiary) @@ -112,6 +117,7 @@ static const struct evm_host example_host = { query, get_storage, set_storage, + get_balance, selfdestruct, call, get_tx_context, diff --git a/include/evm.h b/include/evm.h index 6706ff0..a4ddc68 100644 --- a/include/evm.h +++ b/include/evm.h @@ -194,7 +194,6 @@ struct evm_result { enum evm_query_key { EVM_CODE_BY_ADDRESS = 10, ///< Code by an address for EXTCODECOPY. EVM_CODE_SIZE = 11, ///< Code size by an address for EXTCODESIZE. - EVM_BALANCE = 12, ///< Balance of a given address for BALANCE. EVM_ACCOUNT_EXISTS = 14, ///< Check if an account exists. }; @@ -241,9 +240,6 @@ union evm_variant { /// - ::EVM_CODE_SIZE /// @result evm_variant::int64 The appropriate code size for the given address or 0 if not found. /// -/// - ::EVM_BALANCE -/// @result evm_variant::uint256be The appropriate balance for the given address or 0 if not found. -/// /// - ::EVM_ACCOUNT_EXISTS /// @result evm_variant::int64 1 if exists, 0 if not. /// @@ -286,6 +282,18 @@ typedef void (*evm_set_storage_fn)(struct evm_env* env, const struct evm_uint256be* key, const struct evm_uint256be* value); +/// 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 env Pointer to execution environment managed by the host +/// application. +/// @param address The address. +typedef void (*evm_get_balance_fn)(struct evm_uint256be* result, + struct evm_env* env, + const struct evm_uint160be* address); + /// Selfdestruct callback function. /// /// This callback function is used by an EVM to SELFDESTRUCT given contract. @@ -334,10 +342,13 @@ typedef void (*evm_call_fn)( /// realisation of OOP interface (only virtual methods, no data). /// Host implementations SHOULD create constant singletons of this (similar /// to vtables) to lower the maintenance and memory management cost. +/// +/// @todo Merge evm_host with evm_env? struct evm_host { evm_query_state_fn query; evm_get_storage_fn get_storage; evm_set_storage_fn set_storage; + evm_get_balance_fn get_balance; evm_selfdestruct_fn selfdestruct; evm_call_fn call; evm_get_tx_context_fn get_tx_context; From 2d2adcb868d524d42047b7b0445a149f3ac9401a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 7 Aug 2017 20:44:05 +0200 Subject: [PATCH 2/5] EVM-C: Move code query to separated callback function --- examples/capi.c | 16 +++++++++++----- include/evm.h | 24 ++++++++++++++++-------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/examples/capi.c b/examples/capi.c index 8d6cb27..8250901 100644 --- a/examples/capi.c +++ b/examples/capi.c @@ -30,11 +30,6 @@ static void query(union evm_variant* result, const struct evm_uint160be* address) { printf("EVM-C: QUERY %d\n", key); switch (key) { - case EVM_CODE_BY_ADDRESS: - result->data = NULL; - result->data_size = 0; - break; - case EVM_ACCOUNT_EXISTS: result->int64 = 0; break; @@ -73,6 +68,16 @@ static void get_balance(struct evm_uint256be* result, printf("\n"); } +static size_t get_code(const uint8_t** code, + struct evm_env* env, + const struct evm_uint160be* address) +{ + printf("EVM-C: CODE @"); + print_address(address); + printf("\n"); + return 0; +} + static void selfdestruct(struct evm_env* env, const struct evm_uint160be* address, const struct evm_uint160be* beneficiary) @@ -118,6 +123,7 @@ static const struct evm_host example_host = { get_storage, set_storage, get_balance, + get_code, selfdestruct, call, get_tx_context, diff --git a/include/evm.h b/include/evm.h index a4ddc68..f17602c 100644 --- a/include/evm.h +++ b/include/evm.h @@ -192,8 +192,6 @@ struct evm_result { /// The query callback key. enum evm_query_key { - EVM_CODE_BY_ADDRESS = 10, ///< Code by an address for EXTCODECOPY. - EVM_CODE_SIZE = 11, ///< Code size by an address for EXTCODESIZE. EVM_ACCOUNT_EXISTS = 14, ///< Check if an account exists. }; @@ -234,12 +232,6 @@ union evm_variant { /// /// ## Types of queries /// -/// - ::EVM_CODE_BY_ADDRESS -/// @result evm_variant::data The appropriate code for the given address or NULL if not found. -/// -/// - ::EVM_CODE_SIZE -/// @result evm_variant::int64 The appropriate code size for the given address or 0 if not found. -/// /// - ::EVM_ACCOUNT_EXISTS /// @result evm_variant::int64 1 if exists, 0 if not. /// @@ -294,6 +286,21 @@ typedef void (*evm_get_balance_fn)(struct evm_uint256be* result, struct evm_env* env, const struct evm_uint160be* address); +/// Get code callback function. +/// +/// This callback function is used by an EVM to get the code of a contract of +/// given address. +/// @param[out] result The pointer to the contract code. This argument is +/// optional. If NULL is provided, the host MUST only +/// return the code size. +/// @param env Pointer to execution environment managed by the host +/// application. +/// @param address The address of the contract. +/// @return The size of the code. +typedef size_t (*evm_get_code_fn)(const uint8_t** result_code, + struct evm_env* env, + const struct evm_uint160be* address); + /// Selfdestruct callback function. /// /// This callback function is used by an EVM to SELFDESTRUCT given contract. @@ -349,6 +356,7 @@ struct evm_host { evm_get_storage_fn get_storage; evm_set_storage_fn set_storage; evm_get_balance_fn get_balance; + evm_get_code_fn get_code; evm_selfdestruct_fn selfdestruct; evm_call_fn call; evm_get_tx_context_fn get_tx_context; From 182d7f3876bf7ec5de6da39fdc4155c9122602bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 8 Aug 2017 10:26:52 +0200 Subject: [PATCH 3/5] EVM-C: Reduce query_fn to account_exists_fn --- examples/capi.c | 21 ++++++----------- include/evm.h | 63 +++++++------------------------------------------ 2 files changed, 16 insertions(+), 68 deletions(-) diff --git a/examples/capi.c b/examples/capi.c index 8250901..682c0b1 100644 --- a/examples/capi.c +++ b/examples/capi.c @@ -24,19 +24,12 @@ static void print_address(const struct evm_uint160be* address) printf("%x", address->bytes[i] & 0xff); } -static void query(union evm_variant* result, - struct evm_env* env, - enum evm_query_key key, - const struct evm_uint160be* address) { - printf("EVM-C: QUERY %d\n", key); - switch (key) { - case EVM_ACCOUNT_EXISTS: - result->int64 = 0; - break; - - default: - result->int64 = 0; - } +static int account_exists(struct evm_env* env, + const struct evm_uint160be* address) { + printf("EVM-C: EXISTS @"); + print_address(address); + printf("\n"); + return 0; } static void get_storage(struct evm_uint256be* result, @@ -119,7 +112,7 @@ static void evm_log(struct evm_env* env, const struct evm_uint160be* address, } static const struct evm_host example_host = { - query, + account_exists, get_storage, set_storage, get_balance, diff --git a/include/evm.h b/include/evm.h index f17602c..7a16f99 100644 --- a/include/evm.h +++ b/include/evm.h @@ -190,61 +190,16 @@ struct evm_result { } reserved; }; -/// The query callback key. -enum evm_query_key { - EVM_ACCOUNT_EXISTS = 14, ///< Check if an account exists. -}; - - -/// Variant type to represent possible types of values used in EVM. +/// Check account existence callback function /// -/// Type-safety is lost around the code that uses this type. We should have -/// complete set of unit tests covering all possible cases. -/// The size of the type is 64 bytes and should fit in single cache line. -union evm_variant { - /// A host-endian 64-bit integer. - int64_t int64; - - /// A big-endian 256-bit integer or hash. - struct evm_uint256be uint256be; - - /// A memory reference. - struct { - /// Pointer to the data. - uint8_t const* data; - - /// Size of the referenced memory/data. - size_t data_size; - }; -}; - -/// Query callback function. -/// -/// This callback function is used by the EVM to query the host application -/// about additional information about accounts in the state required to -/// execute EVM code. -/// @param[out] result The result of the query. -/// @param env Pointer to execution environment managed by the host -/// application. -/// @param key The kind of the query. See evm_query_key -/// and details below. +/// This callback function is used by the EVM to check if +/// there exists an account at given address. +/// @param env Pointer to execution environment managed by the host +/// application. /// @param address The address of the account the query is about. -/// -/// ## Types of queries -/// -/// - ::EVM_ACCOUNT_EXISTS -/// @result evm_variant::int64 1 if exists, 0 if not. -/// -/// -/// @todo -/// - Consider swapping key and address arguments, -/// e.g. `query(result, env, addr, EVM_SLOAD, k)`. -/// - Consider renaming key argument to something else. Key is confusing -/// especially for SSTORE and SLOAD. Maybe "kind"? -typedef void (*evm_query_state_fn)(union evm_variant* result, - struct evm_env* env, - enum evm_query_key key, - const struct evm_uint160be* address); +/// @return 1 if exists, 0 otherwise. +typedef int (*evm_account_exists_fn)(struct evm_env* env, + const struct evm_uint160be* address); /// Get storage callback function. /// @@ -352,7 +307,7 @@ typedef void (*evm_call_fn)( /// /// @todo Merge evm_host with evm_env? struct evm_host { - evm_query_state_fn query; + evm_account_exists_fn account_exists; evm_get_storage_fn get_storage; evm_set_storage_fn set_storage; evm_get_balance_fn get_balance; From 9503ac90c2a36487272f0c806b57ecd2c1b3a31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 18 Aug 2017 13:40:25 +0200 Subject: [PATCH 4/5] EVM-C: Improve example --- examples/capi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/capi.c b/examples/capi.c index 682c0b1..6252a57 100644 --- a/examples/capi.c +++ b/examples/capi.c @@ -59,6 +59,7 @@ static void get_balance(struct evm_uint256be* result, printf("EVM-C: BALANCE @"); print_address(address); printf("\n"); + *result = balance(env, address); } static size_t get_code(const uint8_t** code, From 2004671cb2a0da4a51cf65f8c9123eff750d62c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 18 Aug 2017 14:09:55 +0200 Subject: [PATCH 5/5] EVM-C: Fix docs --- include/evm.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/evm.h b/include/evm.h index 7a16f99..1672a1a 100644 --- a/include/evm.h +++ b/include/evm.h @@ -245,13 +245,12 @@ typedef void (*evm_get_balance_fn)(struct evm_uint256be* result, /// /// This callback function is used by an EVM to get the code of a contract of /// given address. -/// @param[out] result The pointer to the contract code. This argument is -/// optional. If NULL is provided, the host MUST only -/// return the code size. -/// @param env Pointer to execution environment managed by the host -/// application. -/// @param address The address of the contract. -/// @return The size of the code. +/// @param[out] result_code The pointer to the contract code. This argument is +/// optional. If NULL is provided, the host MUST only +/// return the code size. +/// @param env Pointer to execution context managed by the Host. +/// @param address The address of the contract. +/// @return The size of the code. typedef size_t (*evm_get_code_fn)(const uint8_t** result_code, struct evm_env* env, const struct evm_uint160be* address);