Merge pull request #151 from ethereum/set-storage

Update storage methods
This commit is contained in:
Paweł Bylica 2018-09-06 23:41:39 +02:00 committed by GitHub
commit 1322d7559c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 28 deletions

View File

@ -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

View File

@ -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)

View File

@ -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,