diff --git a/bindings/rust/evmc-sys/src/lib.rs b/bindings/rust/evmc-sys/src/lib.rs index 6a545ff80..edaa9568d 100644 --- a/bindings/rust/evmc-sys/src/lib.rs +++ b/bindings/rust/evmc-sys/src/lib.rs @@ -47,7 +47,7 @@ mod tests { // TODO: add other checks from test/unittests/test_helpers.cpp assert_eq!(size_of::(), 32); assert_eq!(size_of::(), 20); - assert!(size_of::() <= 64); + assert!(size_of::() <= 128); assert!(size_of::() <= 64); } } diff --git a/bindings/rust/evmc-vm/src/lib.rs b/bindings/rust/evmc-vm/src/lib.rs index 6f604e000..f660b16be 100644 --- a/bindings/rust/evmc-vm/src/lib.rs +++ b/bindings/rust/evmc-vm/src/lib.rs @@ -447,7 +447,7 @@ impl Into for ExecutionResult { } else { Address { bytes: [0u8; 20] } }, - padding: [0u8; 4], + scratchpad: ffi::evmc_result_scratchpad { bytes: [0u8; 32] }, } } } @@ -532,7 +532,7 @@ mod tests { output_size: 4, release: Some(test_result_dispose), create_address: Address { bytes: [0u8; 20] }, - padding: [0u8; 4], + scratchpad: ffi::evmc_result_scratchpad { bytes: [0u8; 32] }, }; let r: ExecutionResult = f.into(); @@ -778,7 +778,7 @@ mod tests { output_size: msg.input_size, release: None, create_address: ffi::evmc_address::default(), - padding: [0u8; 4], + scratchpad: ffi::evmc_result_scratchpad { bytes: [0u8; 32] }, } } diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index fe950d379..9583c8e62 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -336,6 +336,7 @@ struct evmc_result; */ typedef void (*evmc_release_result_fn)(const struct evmc_result* result); + /** The EVM code execution result. */ struct evmc_result { @@ -402,18 +403,23 @@ struct evmc_result */ evmc_address create_address; - /** - * Reserved data that MAY be used by a evmc_result object creator. - * - * This reserved 4 bytes together with 20 bytes from create_address form - * 24 bytes of memory called "optional data" within evmc_result struct - * to be optionally used by the evmc_result object creator. - * - * @see evmc_result_optional_data, evmc_get_optional_data(). - * - * Also extends the size of the evmc_result to 64 bytes (full cache line). - */ - uint8_t padding[4]; + union scratchpad + { + /** + * Reserved data that MAY be used by a evmc_result object creator. + * + * This reserved 4 bytes together with 20 bytes from create_address form + * 24 bytes of memory called "optional data" within evmc_result struct + * to be optionally used by the evmc_result object creator. + * + * @see evmc_result_optional_data, evmc_get_optional_data(). + * + * Also extends the size of the evmc_result to 64 bytes (full cache line). + */ + uint8_t bytes[32]; + + void* pointer; + } scratchpad; }; diff --git a/include/evmc/evmc.hpp b/include/evmc/evmc.hpp index e161c0324..6759b379a 100644 --- a/include/evmc/evmc.hpp +++ b/include/evmc/evmc.hpp @@ -266,11 +266,11 @@ constexpr auto make_result = evmc_make_result; class result : private evmc_result { public: - using evmc_result::create_address; using evmc_result::gas_left; using evmc_result::output_data; using evmc_result::output_size; using evmc_result::status_code; + using evmc_result::create_address; /// Creates the result from the provided arguments. /// diff --git a/include/evmc/helpers.h b/include/evmc/helpers.h index 36febfd72..d4c50b02e 100644 --- a/include/evmc/helpers.h +++ b/include/evmc/helpers.h @@ -160,53 +160,4 @@ static inline void evmc_release_result(struct evmc_result* result) result->release(result); } - -/** - * Helpers for optional storage of evmc_result. - * - * In some contexts (i.e. evmc_result::create_address is unused) objects of - * type evmc_result contains a memory storage that MAY be used by the object - * owner. This group defines helper types and functions for accessing - * the optional storage. - * - * @defgroup result_optional_storage Result Optional Storage - * @{ - */ - -/** - * The union representing evmc_result "optional storage". - * - * The evmc_result struct contains 24 bytes of optional storage that can be - * reused by the object creator if the object does not contain - * evmc_result::create_address. - * - * A VM implementation MAY use this memory to keep additional data - * when returning result from evmc_execute_fn(). - * The host application MAY use this memory to keep additional data - * when returning result of performed calls from evmc_call_fn(). - * - * @see evmc_get_optional_storage(), evmc_get_const_optional_storage(). - */ -union evmc_result_optional_storage -{ - uint8_t bytes[24]; /**< 24 bytes of optional storage. */ - void* pointer; /**< Optional pointer. */ -}; - -/** Provides read-write access to evmc_result "optional storage". */ -static inline union evmc_result_optional_storage* evmc_get_optional_storage( - struct evmc_result* result) -{ - return (union evmc_result_optional_storage*)&result->create_address; -} - -/** Provides read-only access to evmc_result "optional storage". */ -static inline const union evmc_result_optional_storage* evmc_get_const_optional_storage( - const struct evmc_result* result) -{ - return (const union evmc_result_optional_storage*)&result->create_address; -} - -/** @} */ - /** @} */ diff --git a/test/unittests/test_cpp.cpp b/test/unittests/test_cpp.cpp index 7ac6a2dbc..f390fffcb 100644 --- a/test/unittests/test_cpp.cpp +++ b/test/unittests/test_cpp.cpp @@ -236,13 +236,13 @@ TEST(cpp, result) int release_called = 0; { auto raw_result = evmc_result{}; - evmc_get_optional_storage(&raw_result)->pointer = &release_called; + raw_result.scratchpad.pointer = &release_called; EXPECT_EQ(release_called, 0); raw_result.output_data = &output; raw_result.release = [](const evmc_result* r) { EXPECT_EQ(r->output_data, &output); - ++*static_cast(evmc_get_const_optional_storage(r)->pointer); + ++*static_cast(r->scratchpad.pointer); }; EXPECT_EQ(release_called, 0); diff --git a/test/unittests/test_helpers.cpp b/test/unittests/test_helpers.cpp index cc9f21ac5..e9a71086e 100644 --- a/test/unittests/test_helpers.cpp +++ b/test/unittests/test_helpers.cpp @@ -10,7 +10,7 @@ static_assert(sizeof(evmc_bytes32) == 32, "evmc_bytes32 is too big"); static_assert(sizeof(evmc_address) == 20, "evmc_address is too big"); -static_assert(sizeof(evmc_result) <= 64, "evmc_result does not fit cache line"); +static_assert(sizeof(evmc_result) <= 128, "evmc_result does not fit 2 cache lines"); static_assert(sizeof(evmc_vm) <= 64, "evmc_vm does not fit cache line"); static_assert(offsetof(evmc_message, value) % sizeof(size_t) == 0, "evmc_message.value not aligned"); @@ -21,10 +21,9 @@ static_assert(sizeof(evmc_call_kind) == sizeof(int), "Enum `evmc_call_kind` is not the size of int"); static_assert(sizeof(evmc_revision) == sizeof(int), "Enum `evmc_revision` is not the size of int"); -static constexpr size_t optionalDataSize = - sizeof(evmc_result) - offsetof(evmc_result, create_address); -static_assert(optionalDataSize >= sizeof(evmc_result_optional_storage), - "evmc_result's optional data space is too small"); + +static_assert(offsetof(evmc_result, scratchpad) % 8 == 0, + "evmc_result's scratchpad not properly aligned"); TEST(helpers, release_result) {