EVM-C: Replace evm_{uint|hash}256 with single evm_uint256be

All values transfered to/from a VM must be passed as big-endian integers.
This commit is contained in:
Paweł Bylica 2016-08-31 11:40:02 +02:00
parent 50c49b0b9d
commit 2a99b13573
3 changed files with 42 additions and 55 deletions

View File

@ -4,15 +4,15 @@
#include "evm.h" #include "evm.h"
struct evm_uint256 balance(struct evm_env* env, struct evm_hash160 address) struct evm_uint256be balance(struct evm_env* env, struct evm_uint160be address)
{ {
struct evm_uint256 ret = { .words = { 1 } }; struct evm_uint256be ret = {.bytes = {1, 2, 3, 4}};
return ret; return ret;
} }
struct evm_hash160 address(struct evm_env* env) struct evm_uint160be address(struct evm_env* env)
{ {
struct evm_hash160 ret = { .bytes = { 1, 2, 3, 4 } }; struct evm_uint160be ret = {.bytes = {1, 2, 3, 4}};
return ret; return ret;
} }
@ -25,7 +25,7 @@ union evm_variant query(struct evm_env* env,
case EVM_GAS_LIMIT: result.int64 = 314; break; case EVM_GAS_LIMIT: result.int64 = 314; break;
case EVM_BALANCE: case EVM_BALANCE:
result.uint256 = balance(env, arg.address); result.uint256be = balance(env, arg.address);
break; break;
case EVM_ADDRESS: case EVM_ADDRESS:
@ -49,8 +49,8 @@ int64_t call(
struct evm_env* _opaqueEnv, struct evm_env* _opaqueEnv,
enum evm_call_kind _kind, enum evm_call_kind _kind,
int64_t _gas, int64_t _gas,
struct evm_hash160 _address, struct evm_uint160be _address,
struct evm_uint256 _value, struct evm_uint256be _value,
uint8_t const* _inputData, uint8_t const* _inputData,
size_t _inputSize, size_t _inputSize,
uint8_t* _outputData, uint8_t* _outputData,
@ -68,9 +68,9 @@ int main(int argc, char *argv[]) {
char const code[] = "exec()"; char const code[] = "exec()";
const size_t code_size = sizeof(code); const size_t code_size = sizeof(code);
struct evm_hash256 code_hash = {.bytes = {1, 2, 3,}}; struct evm_uint256be code_hash = {.bytes = {1, 2, 3,}};
char const input[] = "Hello World!"; char const input[] = "Hello World!";
struct evm_uint256 value = {{1, 0, 0, 0}}; struct evm_uint256be value = {{1, 0, 0, 0}};
int64_t gas = 200000; int64_t gas = 200000;
struct evm_result result = struct evm_result result =

View File

@ -43,13 +43,13 @@ int evm_set_option(struct evm_instance* evm,
static struct evm_result evm_execute(struct evm_instance* instance, static struct evm_result evm_execute(struct evm_instance* instance,
struct evm_env* env, struct evm_env* env,
enum evm_mode mode, enum evm_mode mode,
struct evm_hash256 code_hash, struct evm_uint256be code_hash,
uint8_t const* code, uint8_t const* code,
size_t code_size, size_t code_size,
int64_t gas, int64_t gas,
uint8_t const* input, uint8_t const* input,
size_t input_size, size_t input_size,
struct evm_uint256 value) struct evm_uint256be value)
{ {
struct evm_result ret; struct evm_result ret;

View File

@ -25,36 +25,26 @@ extern "C" {
/// The EVM-C ABI version number matching the interface declared in this file. /// The EVM-C ABI version number matching the interface declared in this file.
static const uint32_t EVM_ABI_VERSION = 0; static const uint32_t EVM_ABI_VERSION = 0;
/// Host-endian 256-bit integer. /// Big-endian 256-bit integer.
/// ///
/// 32 bytes of data representing host-endian (that means little-endian almost /// 32 bytes of data representing big-endian 256-bit integer. I.e. bytes[0] is
/// all the time) 256-bit integer. This applies to the words[] order as well. /// the most significant byte, bytes[31] is the least significant byte.
/// words[0] contains the 64 lowest precision bits, words[3] constains the 64 /// This type is used to transfer to/from the VM values interpreted by the user
/// highest precision bits. /// as both 256-bit integers and 256-bit hashes.
struct evm_uint256 { struct evm_uint256be {
/// The 4 64-bit words of the integer. Memory aligned to 8 bytes. /// The 32 bytes of the big-endian integer or hash.
uint64_t words[4];
};
/// Big-endian 160-bit hash suitable for keeping an Ethereum address.
struct evm_hash160 {
/// The 20 bytes of the hash.
uint8_t bytes[20];
};
/// Big-endian 256-bit integer/hash.
///
/// 32 bytes of data. For EVM that means big-endian 256-bit integer. Values of
/// this type are converted to host-endian values inside EVM.
struct evm_hash256 {
/// The 32 bytes of the integer/hash.
/// ///
/// The memory is expected be aligned to 8 bytes, but there is no portable /// The memory is expected be aligned to 8 bytes, but there is no portable
/// way to express that. /// way to express that.
uint8_t bytes[32]; uint8_t bytes[32];
}; };
/// Big-endian 160-bit hash suitable for keeping an Ethereum address.
struct evm_uint160be {
/// The 20 bytes of the hash.
uint8_t bytes[20];
};
/// The execution result code. /// The execution result code.
enum evm_result_code { enum evm_result_code {
EVM_SUCCESS = 0, ///< Execution finished with success. EVM_SUCCESS = 0, ///< Execution finished with success.
@ -128,11 +118,8 @@ union evm_variant {
/// A host-endian 64-bit integer. /// A host-endian 64-bit integer.
int64_t int64; int64_t int64;
/// A host-endian 256-bit integer. /// A big-endian 256-bit integer or hash.
struct evm_uint256 uint256; struct evm_uint256be uint256be;
/// A big-endian 256-bit integer/hash.
struct evm_hash256 hash256;
struct { struct {
/// Additional padding to align the evm_variant::address with lower /// Additional padding to align the evm_variant::address with lower
@ -140,7 +127,7 @@ union evm_variant {
uint8_t address_padding[12]; uint8_t address_padding[12];
/// An Ethereum address. /// An Ethereum address.
struct evm_hash160 address; struct evm_uint160be address;
}; };
/// A memory reference. /// A memory reference.
@ -166,19 +153,19 @@ union evm_variant {
/// ## Types of queries /// ## Types of queries
/// Key | Arg | Expected result /// Key | Arg | Expected result
/// ----------------------| -------------------- | ---------------------------- /// ----------------------| -------------------- | ----------------------------
/// ::EVM_GAS_PRICE | | evm_variant::uint256 /// ::EVM_GAS_PRICE | | evm_variant::uint256be
/// ::EVM_ADDRESS | | evm_variant::address /// ::EVM_ADDRESS | | evm_variant::address
/// ::EVM_CALLER | | evm_variant::address /// ::EVM_CALLER | | evm_variant::address
/// ::EVM_ORIGIN | | evm_variant::address /// ::EVM_ORIGIN | | evm_variant::address
/// ::EVM_COINBASE | | evm_variant::address /// ::EVM_COINBASE | | evm_variant::address
/// ::EVM_DIFFICULTY | | evm_variant::uint256 /// ::EVM_DIFFICULTY | | evm_variant::uint256be
/// ::EVM_GAS_LIMIT | | evm_variant::uint256 /// ::EVM_GAS_LIMIT | | evm_variant::uint256be
/// ::EVM_NUMBER | | evm_variant::int64? /// ::EVM_NUMBER | | evm_variant::int64?
/// ::EVM_TIMESTAMP | | evm_variant::int64? /// ::EVM_TIMESTAMP | | evm_variant::int64?
/// ::EVM_CODE_BY_ADDRESS | evm_variant::address | evm_variant::data /// ::EVM_CODE_BY_ADDRESS | evm_variant::address | evm_variant::data
/// ::EVM_BALANCE | evm_variant::address | evm_variant::uint256 /// ::EVM_BALANCE | evm_variant::address | evm_variant::uint256be
/// ::EVM_BLOCKHASH | evm_variant::int64 | evm_variant::hash256 /// ::EVM_BLOCKHASH | evm_variant::int64 | evm_variant::uint256be
/// ::EVM_SLOAD | evm_variant::uint256 | evm_variant::uint256? /// ::EVM_SLOAD | evm_variant::uint256be | evm_variant::uint256be
typedef union evm_variant (*evm_query_fn)(struct evm_env* env, typedef union evm_variant (*evm_query_fn)(struct evm_env* env,
enum evm_query_key key, enum evm_query_key key,
union evm_variant arg); union evm_variant arg);
@ -203,13 +190,13 @@ enum evm_update_key {
/// ## Kinds of updates /// ## Kinds of updates
/// ///
/// - ::EVM_SSTORE /// - ::EVM_SSTORE
/// @param arg1 evm_variant::uint256 The index of the storage entry. /// @param arg1 evm_variant::uint256be The index of the storage entry.
/// @param arg2 evm_variant::uint256 The value to be stored. /// @param arg2 evm_variant::uint256be The value to be stored.
/// ///
/// - ::EVM_LOG /// - ::EVM_LOG
/// @param arg1 evm_variant::data The log unindexed data. /// @param arg1 evm_variant::data The log unindexed data.
/// @param arg2 evm_variant::data The log topics. The referenced data is an /// @param arg2 evm_variant::data The log topics. The referenced data is an
/// array of evm_hash256[] of possible length /// array of evm_uint256be[] of possible length
/// from 0 to 4. So the valid /// from 0 to 4. So the valid
/// evm_variant::data_size values are 0, 32, 64 /// evm_variant::data_size values are 0, 32, 64
/// 92 and 128. /// 92 and 128.
@ -257,8 +244,8 @@ typedef int64_t (*evm_call_fn)(
struct evm_env* env, struct evm_env* env,
enum evm_call_kind kind, enum evm_call_kind kind,
int64_t gas, int64_t gas,
struct evm_hash160 address, struct evm_uint160be address,
struct evm_uint256 value, struct evm_uint256be value,
uint8_t const* input, uint8_t const* input,
size_t input_size, size_t input_size,
uint8_t* output, uint8_t* output,
@ -335,13 +322,13 @@ enum evm_mode {
typedef struct evm_result (*evm_execute_fn)(struct evm_instance* instance, typedef struct evm_result (*evm_execute_fn)(struct evm_instance* instance,
struct evm_env* env, struct evm_env* env,
enum evm_mode mode, enum evm_mode mode,
struct evm_hash256 code_hash, struct evm_uint256be code_hash,
uint8_t const* code, uint8_t const* code,
size_t code_size, size_t code_size,
int64_t gas, int64_t gas,
uint8_t const* input, uint8_t const* input,
size_t input_size, size_t input_size,
struct evm_uint256 value); struct evm_uint256be value);
/// Releases resources assigned to an execution result. /// Releases resources assigned to an execution result.
/// ///
@ -370,14 +357,14 @@ enum evm_code_status {
typedef enum evm_code_status typedef enum evm_code_status
(*evm_get_code_status_fn)(struct evm_instance* instance, (*evm_get_code_status_fn)(struct evm_instance* instance,
enum evm_mode mode, enum evm_mode mode,
struct evm_hash256 code_hash); struct evm_uint256be code_hash);
/// Request preparation of the code for faster execution. It is not required /// Request preparation of the code for faster execution. It is not required
/// to execute the code but allows compilation of the code ahead of time in /// to execute the code but allows compilation of the code ahead of time in
/// JIT-like VMs. /// JIT-like VMs.
typedef void (*evm_prepare_code_fn)(struct evm_instance* instance, typedef void (*evm_prepare_code_fn)(struct evm_instance* instance,
enum evm_mode mode, enum evm_mode mode,
struct evm_hash256 code_hash, struct evm_uint256be code_hash,
uint8_t const* code, uint8_t const* code,
size_t code_size); size_t code_size);