Skip to content

Commit

Permalink
Move EVM code initialization outside of newComputation (#2926)
Browse files Browse the repository at this point in the history
* Move EVM code initialization outside of newComputation

* Tidying up call_common.setupHost
  • Loading branch information
jangko authored Dec 11, 2024
1 parent 7b88bb3 commit 674e65f
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 214 deletions.
48 changes: 6 additions & 42 deletions nimbus/evm/computation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import
std/sequtils,
".."/[db/ledger, constants],
"."/[code_stream, memory, message, stack, state],
"."/[code_stream, memory, stack, state],
"."/[types],
./interpreter/[gas_meter, gas_costs, op_codes],
./evm_errors,
Expand Down Expand Up @@ -46,17 +46,6 @@ when defined(evmc_enabled):
const
evmc_enabled* = defined(evmc_enabled)

# ------------------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------------------

proc generateContractAddress(c: Computation, salt: ContractSalt): Address =
if c.msg.kind == EVMC_CREATE:
let creationNonce = c.vmState.readOnlyStateDB().getNonce(c.msg.sender)
result = generateAddress(c.msg.sender, creationNonce)
else:
result = generateSafeAddress(c.msg.sender, salt, c.msg.data)

# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -259,42 +248,17 @@ template resolveCode*(c: Computation, address: Address): CodeBytesRef =
else:
c.vmState.readOnlyStateDB.resolveCode(address)

proc newComputation*(vmState: BaseVMState, sysCall: bool, message: Message,
isPrecompile, keepStack: bool, salt: ContractSalt = ZERO_CONTRACTSALT): Computation =
new result
result.vmState = vmState
result.msg = message
result.gasMeter.init(message.gas)
result.sysCall = sysCall
result.keepStack = keepStack

if not isPrecompile:
result.memory = EvmMemory.init()
result.stack = EvmStack.init()

if result.msg.isCreate():
result.msg.contractAddress = result.generateContractAddress(salt)
result.code = CodeStream.init(message.data)
message.data = @[]
else:
if vmState.fork >= FkPrague:
result.code = CodeStream.init(
vmState.readOnlyStateDB.resolveCode(message.codeAddress))
else:
result.code = CodeStream.init(
vmState.readOnlyStateDB.getCode(message.codeAddress))


func newComputation*(vmState: BaseVMState, sysCall: bool,
message: Message, code: CodeBytesRef, isPrecompile, keepStack: bool, ): Computation =
func newComputation*(vmState: BaseVMState,
keepStack: bool,
message: Message,
code = CodeBytesRef(nil)): Computation =
new result
result.vmState = vmState
result.msg = message
result.gasMeter.init(message.gas)
result.sysCall = sysCall
result.keepStack = keepStack

if not isPrecompile:
if not code.isNil:
result.code = CodeStream.init(code)
result.memory = EvmMemory.init()
result.stack = EvmStack.init()
Expand Down
12 changes: 6 additions & 6 deletions nimbus/evm/evmc_helpers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ func toEvmc*(h: Hash32): evmc_bytes32 {.inline.} =
doAssert sizeof(h) == sizeof(evmc_bytes32)
evmc_bytes32(bytes: h.data)

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

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

func fromEvmc*(T: type, n: evmc_bytes32): T {.inline.} =
when T is ContractSalt:
when T is Bytes32:
doAssert sizeof(n) == sizeof(T)
cast[T](n)
T(n.bytes)
elif T is Hash32:
Hash32(n.bytes)
elif T is UInt256:
Expand All @@ -63,6 +63,6 @@ when isMainModule:
var h = EMPTY_SHA3
var eh = toEvmc(h)
assert(h == fromEvmc(Hash32, eh))
var s = cast[ContractSalt](EMPTY_ROOT_HASH)
var s = Bytes32(EMPTY_ROOT_HASH.data)
var es = toEvmc(s)
assert(s == fromEvmc(ContractSalt, es))
assert(s == fromEvmc(Bytes32, es))
6 changes: 3 additions & 3 deletions nimbus/evm/interpreter/op_handlers/oph_call.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import
../../../core/eip7702,
../../computation,
../../memory,
../../precompiles,
../../stack,
../../types,
../gas_costs,
Expand All @@ -39,6 +38,7 @@ import
when not defined(evmc_enabled):
import
../../state,
../../message,
../../../db/ledger
else:
import
Expand Down Expand Up @@ -203,9 +203,9 @@ else:
# need to provide explicit <c> and <child> for capturing in chainTo proc()
# <memPos> and <memLen> are provided by value and need not be captured
var
precompile = getPrecompile(c.fork, childMsg.codeAddress)
code = getCallCode(c.vmState, childMsg.codeAddress)
child = newComputation(
c.vmState, false, childMsg, isPrecompile = precompile.isSome(), keepStack = false)
c.vmState, keepStack = false, childMsg, code)

c.chainTo(child):
if not child.shouldBurnGas:
Expand Down
53 changes: 33 additions & 20 deletions nimbus/evm/interpreter/op_handlers/oph_create.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ import
chronicles,
eth/common,
eth/common/eth_types,
stew/assign2,
stint

when not defined(evmc_enabled):
import
../../state,
../../message,
../../../db/ledger
else:
import
stew/assign2,
stew/saturation_arith

# ------------------------------------------------------------------------------
Expand All @@ -62,12 +63,12 @@ when evmc_enabled:

else:
proc execSubCreate(c: Computation; childMsg: Message;
salt: ContractSalt = ZERO_CONTRACTSALT) {.raises: [].} =
code: CodeBytesRef) {.raises: [].} =
## Create new VM -- helper for `Create`-like operations

# need to provide explicit <c> and <child> for capturing in chainTo proc()
var
child = newComputation(c.vmState, false, childMsg, false, false, salt)
child = newComputation(c.vmState, keepStack = false, childMsg, code)

c.chainTo(child):
if not child.shouldBurnGas:
Expand Down Expand Up @@ -154,14 +155,19 @@ proc createOp(cpt: VmCpt): EvmResultVoid =
)
c.execSubCreate(msg)
else:
var childMsg = Message(
kind: EVMC_CREATE,
depth: cpt.msg.depth + 1,
gas: createMsgGas,
sender: cpt.msg.contractAddress,
value: endowment)
assign(childMsg.data, cpt.memory.read(memPos, memLen))
cpt.execSubCreate(childMsg)
var
childMsg = Message(
kind: EVMC_CREATE,
depth: cpt.msg.depth + 1,
gas: createMsgGas,
sender: cpt.msg.contractAddress,
contractAddress: generateContractAddress(
cpt.vmState,
EVMC_CREATE,
cpt.msg.contractAddress),
value: endowment)
code = CodeBytesRef.init(cpt.memory.read(memPos, memLen))
cpt.execSubCreate(childMsg, code)
ok()

# ---------------------
Expand All @@ -176,7 +182,7 @@ proc create2Op(cpt: VmCpt): EvmResultVoid =
memPos = cpt.stack.lsPeekSafeInt(^2)
memLen = cpt.stack.lsPeekSafeInt(^3)
salt256 = cpt.stack.lsPeekInt(^4)
salt = ContractSalt(bytes: salt256.toBytesBE)
salt = Bytes32(salt256.toBytesBE)

cpt.stack.lsShrink(3)
cpt.stack.lsTop(0)
Expand Down Expand Up @@ -237,14 +243,21 @@ proc create2Op(cpt: VmCpt): EvmResultVoid =
)
c.execSubCreate(msg)
else:
var childMsg = Message(
kind: EVMC_CREATE2,
depth: cpt.msg.depth + 1,
gas: createMsgGas,
sender: cpt.msg.contractAddress,
value: endowment)
assign(childMsg.data, cpt.memory.read(memPos, memLen))
cpt.execSubCreate(salt = salt, childMsg = childMsg)
var
code = CodeBytesRef.init(cpt.memory.read(memPos, memLen))
childMsg = Message(
kind: EVMC_CREATE2,
depth: cpt.msg.depth + 1,
gas: createMsgGas,
sender: cpt.msg.contractAddress,
contractAddress: generateContractAddress(
cpt.vmState,
EVMC_CREATE2,
cpt.msg.contractAddress,
salt,
code),
value: endowment)
cpt.execSubCreate(childMsg, code)
ok()

# ------------------------------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions nimbus/evm/interpreter_dispatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,13 @@ else:
c.dispose()
c = c.parent

proc postExecComputation*(c: Computation) =
if c.isSuccess:
if c.fork < FkLondon:
# EIP-3529: Reduction in refunds
c.refundSelfDestruct()
c.vmState.status = c.isSuccess

# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------
32 changes: 30 additions & 2 deletions nimbus/evm/message.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Copyright (c) 2018-2024 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
Expand All @@ -8,7 +8,35 @@
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.

import ./types
import
./types,
./state,
./code_bytes,
./precompiles,
../common/evmforks,
../utils/utils,
../db/ledger

proc isCreate*(message: Message): bool =
message.kind in {EVMC_CREATE, EVMC_CREATE2}

proc generateContractAddress*(vmState: BaseVMState,
kind: CallKind,
sender: Address,
salt = ZERO_CONTRACTSALT,
code = CodeBytesRef(nil)): Address =
if kind == EVMC_CREATE:
let creationNonce = vmState.readOnlyStateDB().getNonce(sender)
generateAddress(sender, creationNonce)
else:
generateSafeAddress(sender, salt, code.bytes)

proc getCallCode*(vmState: BaseVMState, codeAddress: Address): CodeBytesRef =
let isPrecompile = getPrecompile(vmState.fork, codeAddress).isSome()
if isPrecompile:
return CodeBytesRef(nil)

if vmState.fork >= FkPrague:
vmState.readOnlyStateDB.resolveCode(codeAddress)
else:
vmState.readOnlyStateDB.getCode(codeAddress)
34 changes: 0 additions & 34 deletions nimbus/evm/state_transactions.nim

This file was deleted.

1 change: 0 additions & 1 deletion nimbus/evm/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ type
else:
parent*, child*: Computation
continuation*: proc(): EvmResultVoid {.gcsafe, raises: [].}
sysCall*: bool
keepStack*: bool
finalStack*: seq[UInt256]

Expand Down
Loading

0 comments on commit 674e65f

Please sign in to comment.