mirror of https://github.com/status-im/evmc.git
Merge pull request #151 from ethereum/set-storage
Update storage methods
This commit is contained in:
commit
1322d7559c
|
@ -71,8 +71,8 @@ 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
|
||||
GetStorage(addr common.Address, key common.Hash) (common.Hash, error)
|
||||
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)
|
||||
|
@ -95,18 +95,26 @@ func accountExists(pCtx unsafe.Pointer, pAddr *C.struct_evmc_address) C.bool {
|
|||
}
|
||||
|
||||
//export getStorage
|
||||
func getStorage(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.struct_evmc_uint256be) {
|
||||
func getStorage(pResult *C.struct_evmc_uint256be, pCtx unsafe.Pointer, pAddr *C.struct_evmc_address, pKey *C.struct_evmc_uint256be) C.bool {
|
||||
idx := int((*C.struct_extended_context)(pCtx).index)
|
||||
ctx := getHostContext(idx)
|
||||
value := ctx.GetStorage(goAddress(*pAddr), goHash(*pKey))
|
||||
value, err := ctx.GetStorage(goAddress(*pAddr), goHash(*pKey))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
*pResult = evmcUint256be(value)
|
||||
return true
|
||||
}
|
||||
|
||||
//export setStorage
|
||||
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
|
||||
|
|
|
@ -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 = {};
|
||||
|
@ -47,15 +52,19 @@ static bool account_exists(evmc_context* context, const evmc_address* address)
|
|||
return host->accounts.find(*address) != host->accounts.end();
|
||||
}
|
||||
|
||||
static void get_storage(evmc_uint256be* result,
|
||||
static bool get_storage(evmc_uint256be* result,
|
||||
evmc_context* context,
|
||||
const evmc_address* address,
|
||||
const evmc_uint256be* key)
|
||||
{
|
||||
(void)result;
|
||||
(void)context;
|
||||
(void)address;
|
||||
(void)key;
|
||||
example_host_context* host = static_cast<example_host_context*>(context);
|
||||
auto it = host->accounts.find(*address);
|
||||
if (it != host->accounts.end())
|
||||
{
|
||||
*result = it->second.storage[*key];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum evmc_storage_status set_storage(evmc_context* context,
|
||||
|
@ -63,11 +72,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<example_host_context*>(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)
|
||||
|
|
|
@ -409,15 +409,18 @@ typedef bool (*evmc_account_exists_fn)(struct evmc_context* context,
|
|||
/**
|
||||
* Get storage callback function.
|
||||
*
|
||||
* This callback function is used by an EVM to query the given contract
|
||||
* storage entry.
|
||||
* @param[out] result The returned storage value.
|
||||
* @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.
|
||||
* This callback function is used by a VM to query the given contract storage entry.
|
||||
*
|
||||
* @param[out] result The pointer to the place where to put the result value.
|
||||
* @param context The pointer to the Host execution context.
|
||||
* @param address The address of the account.
|
||||
* @param key The index of the account's storage entry.
|
||||
* @return If the account exists the value is put at the location
|
||||
* pointed by @p result and true is returned.
|
||||
* If the account does not exist false is returned without
|
||||
* modifying the memory pointed by @p result.
|
||||
*/
|
||||
typedef void (*evmc_get_storage_fn)(struct evmc_uint256be* result,
|
||||
typedef bool (*evmc_get_storage_fn)(struct evmc_uint256be* result,
|
||||
struct evmc_context* context,
|
||||
const struct evmc_address* address,
|
||||
const struct evmc_uint256be* key);
|
||||
|
@ -431,6 +434,7 @@ typedef void (*evmc_get_storage_fn)(struct evmc_uint256be* result,
|
|||
* - 0 is zero value,
|
||||
* - X != 0 (X is any value other than 0),
|
||||
* - Y != X, Y != 0 (Y is any value other than X and 0),
|
||||
* - Z != Y (Z is any value other than Y),
|
||||
* - the "->" means the change from one value to another.
|
||||
*/
|
||||
enum evmc_storage_status
|
||||
|
@ -458,21 +462,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,
|
||||
|
|
Loading…
Reference in New Issue