From d128fe45d7bccfdb675e50afe2e0bfaac7310f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Sep 2018 18:21:05 +0200 Subject: [PATCH] Introduce EVMC_STORAGE_NON_EXISTING_ACCOUNT for set_storage() Host method --- bindings/go/evmc/host.go | 8 ++++++-- examples/example_host.cpp | 30 +++++++++++++++++++++++++----- include/evmc/evmc.h | 14 +++++++++----- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/bindings/go/evmc/host.go b/bindings/go/evmc/host.go index 0a97aa8..7a3dea0 100644 --- a/bindings/go/evmc/host.go +++ b/bindings/go/evmc/host.go @@ -72,7 +72,7 @@ func goByteSlice(data *C.uint8_t, size C.size_t) []byte { 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 + SetStorage(addr common.Address, key common.Hash, value common.Hash) (StorageStatus, error) GetBalance(addr common.Address) (common.Hash, error) GetCodeSize(addr common.Address) (int, error) GetCodeHash(addr common.Address) (common.Hash, error) @@ -106,7 +106,11 @@ func getStorage(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C. func setStorage(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.struct_evmc_uint256be, pVal *C.struct_evmc_uint256be) C.enum_evmc_storage_status { idx := int((*C.struct_extended_context)(pCtx).index) ctx := getHostContext(idx) - return C.enum_evmc_storage_status(ctx.SetStorage(goAddress(*pAddr), goHash(*pKey), goHash(*pVal))) + status, err := ctx.SetStorage(goAddress(*pAddr), goHash(*pKey), goHash(*pVal)) + if err != nil { + return C.EVMC_STORAGE_NON_EXISTING_ACCOUNT + } + return C.enum_evmc_storage_status(status) } //export getBalance diff --git a/examples/example_host.cpp b/examples/example_host.cpp index e675f86..af285c0 100644 --- a/examples/example_host.cpp +++ b/examples/example_host.cpp @@ -24,6 +24,11 @@ bool operator<(const evmc_uint256be& a, const evmc_uint256be& b) return std::memcmp(a.bytes, b.bytes, sizeof(a)) < 0; } +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 = {}; @@ -63,11 +68,26 @@ static enum evmc_storage_status set_storage(evmc_context* context, const evmc_uint256be* key, const evmc_uint256be* value) { - (void)context; - (void)address; - (void)key; - (void)value; - return EVMC_STORAGE_UNCHANGED; + example_host_context* host = static_cast(context); + auto accountIt = host->accounts.find(*address); + if (accountIt == host->accounts.end()) + return EVMC_STORAGE_NON_EXISTING_ACCOUNT; + + auto storageIt = accountIt->second.storage.find(*key); + if (storageIt == accountIt->second.storage.end()) + { + accountIt->second.storage.emplace(std::make_pair(*key, *value)); + return EVMC_STORAGE_ADDED; + } + else if (storageIt->second == *value) + { + return EVMC_STORAGE_UNCHANGED; + } + else + { + storageIt->second = *value; + return EVMC_STORAGE_MODIFIED; + } } static bool get_balance(evmc_uint256be* result, evmc_context* context, const evmc_address* address) diff --git a/include/evmc/evmc.h b/include/evmc/evmc.h index ca18da5..e71585a 100644 --- a/include/evmc/evmc.h +++ b/include/evmc/evmc.h @@ -459,21 +459,25 @@ enum evmc_storage_status /** * A storage item has been deleted: X -> 0. */ - EVMC_STORAGE_DELETED = 4 + EVMC_STORAGE_DELETED = 4, + + /** + * An attempt to modify storage of an non-existing account. + */ + EVMC_STORAGE_NON_EXISTING_ACCOUNT = 5 }; /** * Set storage callback function. * - * This callback function is used by an EVM to update the given contract - * storage entry. + * This callback function is used by an EVM to update the given contract storage entry. + * * @param context The pointer to the Host execution context. - * @see ::evmc_context. * @param address The address of the contract. * @param key The index of the storage entry. * @param value The value to be stored. - * @return The effect on the storage item, @see ::evmc_storage_status. + * @return The effect on the storage item. @see ::evmc_storage_status. */ typedef enum evmc_storage_status (*evmc_set_storage_fn)(struct evmc_context* context, const struct evmc_address* address,