Skip to content

Commit

Permalink
evmc fixes
Browse files Browse the repository at this point in the history
These fixes probably introduce a bit of overhead, which at this point
doesn't really matter since we don't use evmc for anything but testing
  • Loading branch information
arnetheduck committed Sep 28, 2024
1 parent b57571d commit c500ae7
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 39 deletions.
82 changes: 50 additions & 32 deletions nimbus/evm/evmc_api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -61,30 +61,30 @@ type
padding* : array[4, byte]

nimbus_host_interface* = object
account_exists*: proc(context: evmc_host_context, address: EthAddress): bool {.cdecl, gcsafe, raises: [].}
get_storage*: proc(context: evmc_host_context, address: EthAddress, key: ptr evmc_uint256be): evmc_uint256be {.cdecl, gcsafe, raises: [].}
set_storage*: proc(context: evmc_host_context, address: EthAddress,
account_exists*: proc(context: evmc_host_context, address: ptr evmc_address): bool {.cdecl, gcsafe, raises: [].}
get_storage*: proc(context: evmc_host_context, address: ptr evmc_address, key: ptr evmc_uint256be): evmc_uint256be {.cdecl, gcsafe, raises: [].}
set_storage*: proc(context: evmc_host_context, address: ptr evmc_address,
key, value: ptr evmc_uint256be): evmc_storage_status {.cdecl, gcsafe, raises: [].}
get_balance*: proc(context: evmc_host_context, address: EthAddress): evmc_uint256be {.cdecl, gcsafe, raises: [].}
get_code_size*: proc(context: evmc_host_context, address: EthAddress): uint {.cdecl, gcsafe, raises: [].}
get_code_hash*: proc(context: evmc_host_context, address: EthAddress): Hash256 {.cdecl, gcsafe, raises: [].}
copy_code*: proc(context: evmc_host_context, address: EthAddress,
get_balance*: proc(context: evmc_host_context, address: ptr evmc_address): evmc_uint256be {.cdecl, gcsafe, raises: [].}
get_code_size*: proc(context: evmc_host_context, address: ptr evmc_address): uint {.cdecl, gcsafe, raises: [].}
get_code_hash*: proc(context: evmc_host_context, address: ptr evmc_address): evmc_bytes32 {.cdecl, gcsafe, raises: [].}
copy_code*: proc(context: evmc_host_context, address: ptr evmc_address,
code_offset: int, buffer_data: ptr byte,
buffer_size: int): int {.cdecl, gcsafe, raises: [].}
selfdestruct*: proc(context: evmc_host_context, address, beneficiary: EthAddress) {.cdecl, gcsafe, raises: [].}
selfdestruct*: proc(context: evmc_host_context, address, beneficiary: ptr evmc_address) {.cdecl, gcsafe, raises: [].}
call*: proc(context: evmc_host_context, msg: ptr nimbus_message): nimbus_result {.cdecl, gcsafe, raises: [].}
get_tx_context*: proc(context: evmc_host_context): nimbus_tx_context {.cdecl, gcsafe, raises: [].}
get_block_hash*: proc(context: evmc_host_context, number: int64): Hash256 {.cdecl, gcsafe, raises: [].}
emit_log*: proc(context: evmc_host_context, address: EthAddress,
get_block_hash*: proc(context: evmc_host_context, number: int64): evmc_bytes32 {.cdecl, gcsafe, raises: [].}
emit_log*: proc(context: evmc_host_context, address: ptr evmc_address,
data: ptr byte, data_size: uint,
topics: ptr evmc_bytes32, topics_count: uint) {.cdecl, gcsafe, raises: [].}
access_account*: proc(context: evmc_host_context,
address: EthAddress): evmc_access_status {.cdecl, gcsafe, raises: [].}
access_storage*: proc(context: evmc_host_context, address: EthAddress,
key: var evmc_bytes32): evmc_access_status {.cdecl, gcsafe, raises: [].}
get_transient_storage*: proc(context: evmc_host_context, address: EthAddress,
address: ptr evmc_address): evmc_access_status {.cdecl, gcsafe, raises: [].}
access_storage*: proc(context: evmc_host_context, address: ptr evmc_address,
key: ptr evmc_bytes32): evmc_access_status {.cdecl, gcsafe, raises: [].}
get_transient_storage*: proc(context: evmc_host_context, address: ptr evmc_address,
key: ptr evmc_uint256be): evmc_uint256be {.cdecl, gcsafe, raises: [].}
set_transient_storage*: proc(context: evmc_host_context, address: EthAddress,
set_transient_storage*: proc(context: evmc_host_context, address: ptr evmc_address,
key, value: ptr evmc_uint256be) {.cdecl, gcsafe, raises: [].}

proc nim_host_get_interface*(): ptr nimbus_host_interface {.importc, cdecl.}
Expand All @@ -108,69 +108,87 @@ proc getTxContext*(ctx: HostContext): nimbus_tx_context =
ctx.host.get_tx_context(ctx.context)

proc getBlockHash*(ctx: HostContext, number: BlockNumber): Hash256 =
ctx.host.get_block_hash(ctx.context, number.int64)
Hash256.fromEvmc ctx.host.get_block_hash(ctx.context, number.int64)

proc accountExists*(ctx: HostContext, address: EthAddress): bool =
ctx.host.account_exists(ctx.context, address)
var address = toEvmc(address)
ctx.host.account_exists(ctx.context, address.addr)

proc getStorage*(ctx: HostContext, address: EthAddress, key: UInt256): UInt256 =
var key = toEvmc(key)
UInt256.fromEvmc ctx.host.get_storage(ctx.context, address, key.addr)
var
address = toEvmc(address)
key = toEvmc(key)
UInt256.fromEvmc ctx.host.get_storage(ctx.context, address.addr, key.addr)

proc setStorage*(ctx: HostContext, address: EthAddress,
key, value: UInt256): evmc_storage_status =
var
address = toEvmc(address)
key = toEvmc(key)
value = toEvmc(value)
ctx.host.set_storage(ctx.context, address, key.addr, value.addr)
ctx.host.set_storage(ctx.context, address.addr, key.addr, value.addr)

proc getBalance*(ctx: HostContext, address: EthAddress): UInt256 =
UInt256.fromEvmc ctx.host.get_balance(ctx.context, address)
var address = toEvmc(address)
UInt256.fromEvmc ctx.host.get_balance(ctx.context, address.addr)

proc getCodeSize*(ctx: HostContext, address: EthAddress): uint =
ctx.host.get_code_size(ctx.context, address)
var address = toEvmc(address)
ctx.host.get_code_size(ctx.context, address.addr)

proc getCodeHash*(ctx: HostContext, address: EthAddress): Hash256 =
ctx.host.get_code_hash(ctx.context, address)
var address = toEvmc(address)
Hash256.fromEvmc ctx.host.get_code_hash(ctx.context, address.addr)

proc copyCode*(ctx: HostContext, address: EthAddress, codeOffset: int = 0): seq[byte] =
let size = ctx.getCodeSize(address).int
if size - codeOffset > 0:
result = newSeq[byte](size - codeOffset)
let read = ctx.host.copy_code(ctx.context, address,
var address = toEvmc(address)
let read = ctx.host.copy_code(ctx.context, address.addr,
codeOffset, result[0].addr, result.len)
doAssert(read == result.len)

proc selfDestruct*(ctx: HostContext, address, beneficiary: EthAddress) =
ctx.host.selfdestruct(ctx.context, address, beneficiary)
var
address = toEvmc(address)
beneficiary = toEvmc(beneficiary)
ctx.host.selfdestruct(ctx.context, address.addr, beneficiary.addr)

proc emitLog*(ctx: HostContext, address: EthAddress, data: openArray[byte],
topics: ptr evmc_bytes32, topicsCount: int) =
ctx.host.emit_log(ctx.context, address, if data.len > 0: data[0].unsafeAddr else: nil,
var address = toEvmc(address)
ctx.host.emit_log(ctx.context, address.addr, if data.len > 0: data[0].unsafeAddr else: nil,
data.len.uint, topics, topicsCount.uint)

proc call*(ctx: HostContext, msg: nimbus_message): nimbus_result =
ctx.host.call(ctx.context, msg.unsafeAddr)

proc accessAccount*(ctx: HostContext,
address: EthAddress): evmc_access_status =
ctx.host.access_account(ctx.context, address)
var address = toEvmc(address)
ctx.host.access_account(ctx.context, address.addr)

proc accessStorage*(ctx: HostContext, address: EthAddress,
key: UInt256): evmc_access_status =
var key = toEvmc(key)
ctx.host.access_storage(ctx.context, address, key)
var
address = toEvmc(address)
key = toEvmc(key)
ctx.host.access_storage(ctx.context, address.addr, key.addr)

proc getTransientStorage*(ctx: HostContext, address: EthAddress, key: UInt256): UInt256 =
var key = toEvmc(key)
UInt256.fromEvmc ctx.host.get_transient_storage(ctx.context, address, key.addr)
var
address = toEvmc(address)
key = toEvmc(key)
UInt256.fromEvmc ctx.host.get_transient_storage(ctx.context, address.addr, key.addr)

proc setTransientStorage*(ctx: HostContext, address: EthAddress,
key, value: UInt256) =
var
address = toEvmc(address)
key = toEvmc(key)
value = toEvmc(value)
ctx.host.set_transient_storage(ctx.context, address, key.addr, value.addr)
ctx.host.set_transient_storage(ctx.context, address.addr, key.addr, value.addr)

# The following two templates put here because the stupid style checker
# complaints about block_number vs blockNumber and chain_id vs chainId
Expand Down
14 changes: 10 additions & 4 deletions nimbus/evm/evmc_helpers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ const
evmc_native* {.booldefine.} = false

func toEvmc*(a: EthAddress): evmc_address {.inline.} =
cast[evmc_address](a)
evmc_address(bytes: a.data)

func toEvmc*(h: Hash256 | ContractSalt): evmc_bytes32 {.inline.} =
func toEvmc*(h: Hash256): evmc_bytes32 {.inline.} =
doAssert sizeof(h) == sizeof(evmc_bytes32)
evmc_bytes32(bytes: h.data)

func toEvmc*(h: ContractSalt): evmc_bytes32 {.inline.} =
doAssert sizeof(h) == sizeof(evmc_bytes32)
cast[evmc_bytes32](h)

Expand All @@ -31,9 +35,11 @@ func toEvmc*(n: UInt256): evmc_uint256be {.inline.} =
cast[evmc_uint256be](n.toBytesBE)

func fromEvmc*(T: type, n: evmc_bytes32): T {.inline.} =
when T is Hash256 | ContractSalt:
when T is ContractSalt:
doAssert sizeof(n) == sizeof(T)
cast[T](n)
elif T is Hash32:
Hash32(n.bytes)
elif T is UInt256:
when evmc_native:
cast[UInt256](n)
Expand All @@ -43,7 +49,7 @@ func fromEvmc*(T: type, n: evmc_bytes32): T {.inline.} =
{.error: "cannot convert unsupported evmc type".}

func fromEvmc*(a: evmc_address): EthAddress {.inline.} =
cast[EthAddress](a)
EthAddress(a.bytes)

when isMainModule:
import ../constants
Expand Down
6 changes: 3 additions & 3 deletions nimbus/transaction/host_types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,16 @@ template toEvmc*(n: UInt256): evmc_uint256be =
cast[evmc_uint256be](n)

template toEvmc*(n: Hash256): evmc_bytes32 =
cast[evmc_bytes32](n)
evmc_bytes32(bytes: n.data)

template toEvmc*(address: EthAddress): evmc_address =
cast[evmc_address](address)
evmc_address(bytes: address.data)

template fromEvmc*(n: evmc_uint256be): UInt256 =
cast[UInt256](n)

template fromEvmc*(address: evmc_address): EthAddress =
cast[EthAddress](address)
EthAddress(address.bytes)

template flip256*(word256: evmc_uint256be): evmc_uint256be =
cast[evmc_uint256be](UInt256.fromBytesBE(word256.bytes).toBytes(cpuEndian))
Expand Down

0 comments on commit c500ae7

Please sign in to comment.