Introduce EVMC_STORAGE_NON_EXISTING_ACCOUNT for set_storage() Host method

This commit is contained in:
Paweł Bylica 2018-09-06 18:21:05 +02:00
parent 16049f2a8f
commit d128fe45d7
No known key found for this signature in database
GPG Key ID: 7A0C037434FE77EF
3 changed files with 40 additions and 12 deletions

View File

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

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 = {};
@ -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<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

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