EIP-4788: Make it clear what is an EVM system call
This commit is contained in:
parent
2d2def9a8d
commit
cc7a7db74b
|
@ -140,32 +140,26 @@ proc processBeaconBlockRoot*(vmState: BaseVMState, beaconRoot: Hash256):
|
|||
let
|
||||
statedb = vmState.stateDB
|
||||
call = CallParams(
|
||||
vmState: vmState,
|
||||
sender: SystemAddress,
|
||||
gasLimit: 30_000_000.GasInt,
|
||||
gasPrice: 0.GasInt,
|
||||
to: BeaconRootsStorageAddress,
|
||||
input: @(beaconRoot.data),
|
||||
vmState : vmState,
|
||||
sender : SystemAddress,
|
||||
gasLimit : 30_000_000.GasInt,
|
||||
gasPrice : 0.GasInt,
|
||||
to : BeaconRootsStorageAddress,
|
||||
input : @(beaconRoot.data),
|
||||
|
||||
# It's a systemCall, no need for other knicks knacks
|
||||
sysCall : true,
|
||||
noAccessList: true,
|
||||
noIntrinsic : true,
|
||||
noGasCharge : true,
|
||||
noRefund : true,
|
||||
)
|
||||
|
||||
# runComputation a.k.a syscall/evm.call
|
||||
if call.runComputation().isError:
|
||||
return err("processBeaconBlockRoot: syscall error")
|
||||
|
||||
# We can choose to set SystemAddress nonce to 0
|
||||
# like erigon or geth(their EVM have explicit nonce set)
|
||||
# or we delete the account manually instead of let it deleted
|
||||
# by AccountsCache.persist.
|
||||
statedb.deleteAccount(SystemAddress)
|
||||
|
||||
when false:
|
||||
# nimbus EVM automatically increase sender nonce by one
|
||||
# for each call/create.
|
||||
statedb.setNonce(SystemAddress, 0)
|
||||
# statedb.persist probably not needed as each processTransaction
|
||||
# will call it.
|
||||
statedb.persist(clearEmptyAccount = true, clearCache = false)
|
||||
|
||||
statedb.persist(clearEmptyAccount = true, clearCache = false)
|
||||
ok()
|
||||
|
||||
proc asyncProcessTransaction*(
|
||||
|
|
|
@ -448,7 +448,7 @@ proc setBalance*(ac: AccountsCache, address: EthAddress, balance: UInt256) =
|
|||
proc addBalance*(ac: AccountsCache, address: EthAddress, delta: UInt256) {.inline.} =
|
||||
# EIP161: We must check emptiness for the objects such that the account
|
||||
# clearing (0,0,0 objects) can take effect.
|
||||
if delta == 0.u256:
|
||||
if delta.isZero:
|
||||
let acc = ac.getAccount(address)
|
||||
if acc.isEmpty:
|
||||
ac.makeDirty(address).flags.incl Touched
|
||||
|
@ -456,6 +456,12 @@ proc addBalance*(ac: AccountsCache, address: EthAddress, delta: UInt256) {.inlin
|
|||
ac.setBalance(address, ac.getBalance(address) + delta)
|
||||
|
||||
proc subBalance*(ac: AccountsCache, address: EthAddress, delta: UInt256) {.inline.} =
|
||||
if delta.isZero:
|
||||
# This zero delta early exit is important as shown in EIP-4788.
|
||||
# If the account is created, it will change the state.
|
||||
# But early exit will prevent the account creation.
|
||||
# In this case, the SystemAddress
|
||||
return
|
||||
ac.setBalance(address, ac.getBalance(address) - delta)
|
||||
|
||||
proc setNonce*(ac: AccountsCache, address: EthAddress, nonce: AccountNonce) =
|
||||
|
|
|
@ -212,7 +212,7 @@ template getTransientStorage*(c: Computation, slot: UInt256): UInt256 =
|
|||
c.vmState.readOnlyStateDB.
|
||||
getTransientStorage(c.msg.contractAddress, slot)
|
||||
|
||||
proc newComputation*(vmState: BaseVMState, message: Message,
|
||||
proc newComputation*(vmState: BaseVMState, sysCall: bool, message: Message,
|
||||
salt: ContractSalt = ZERO_CONTRACTSALT): Computation =
|
||||
new result
|
||||
result.vmState = vmState
|
||||
|
@ -221,6 +221,7 @@ proc newComputation*(vmState: BaseVMState, message: Message,
|
|||
result.stack = newStack()
|
||||
result.returnStack = @[]
|
||||
result.gasMeter.init(message.gas)
|
||||
result.sysCall = sysCall
|
||||
|
||||
if result.msg.isCreate():
|
||||
result.msg.contractAddress = result.generateContractAddress(salt)
|
||||
|
@ -230,7 +231,8 @@ proc newComputation*(vmState: BaseVMState, message: Message,
|
|||
result.code = newCodeStream(
|
||||
vmState.readOnlyStateDB.getCode(message.codeAddress))
|
||||
|
||||
proc newComputation*(vmState: BaseVMState, message: Message, code: seq[byte]): Computation =
|
||||
proc newComputation*(vmState: BaseVMState, sysCall: bool,
|
||||
message: Message, code: seq[byte]): Computation =
|
||||
new result
|
||||
result.vmState = vmState
|
||||
result.msg = message
|
||||
|
@ -239,6 +241,7 @@ proc newComputation*(vmState: BaseVMState, message: Message, code: seq[byte]): C
|
|||
result.returnStack = @[]
|
||||
result.gasMeter.init(message.gas)
|
||||
result.code = newCodeStream(code)
|
||||
result.sysCall = sysCall
|
||||
|
||||
template gasCosts*(c: Computation): untyped =
|
||||
c.vmState.gasCosts
|
||||
|
|
|
@ -172,7 +172,7 @@ 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
|
||||
child = newComputation(c.vmState, childMsg)
|
||||
child = newComputation(c.vmState, false, childMsg)
|
||||
|
||||
c.chainTo(child):
|
||||
if not child.shouldBurnGas:
|
||||
|
|
|
@ -63,7 +63,7 @@ else:
|
|||
|
||||
# need to provide explicit <c> and <child> for capturing in chainTo proc()
|
||||
var
|
||||
child = newComputation(c.vmState, childMsg, salt)
|
||||
child = newComputation(c.vmState, false, childMsg, salt)
|
||||
|
||||
c.chainTo(child):
|
||||
if not child.shouldBurnGas:
|
||||
|
|
|
@ -63,6 +63,9 @@ proc execComputation*(c: Computation)
|
|||
c.execCallOrCreate()
|
||||
c.postExecComputation()
|
||||
|
||||
template execSysCall*(c: Computation) =
|
||||
c.execCallOrCreate()
|
||||
|
||||
# FIXME-duplicatedForAsync
|
||||
proc asyncExecComputation*(c: Computation): Future[void] {.async.} =
|
||||
c.preExecComputation()
|
||||
|
|
|
@ -87,6 +87,7 @@ type
|
|||
parent*, child*: Computation
|
||||
pendingAsyncOperation*: Future[void]
|
||||
continuation*: proc() {.gcsafe, raises: [CatchableError].}
|
||||
sysCall*: bool
|
||||
|
||||
Error* = ref object
|
||||
statusCode*: evmc_status_code
|
||||
|
|
|
@ -42,6 +42,7 @@ type
|
|||
noAccessList*: bool # Don't initialise EIP-2929 access list.
|
||||
noGasCharge*: bool # Don't charge sender account for gas.
|
||||
noRefund*: bool # Don't apply gas refund/burn rule.
|
||||
sysCall*: bool # System call or ordinary call
|
||||
|
||||
# Standard call result. (Some fields are beyond what EVMC can return,
|
||||
# and must only be used from tests because they will not always be set).
|
||||
|
@ -176,7 +177,7 @@ proc setupHost(call: CallParams): TransactionHost =
|
|||
host.msg.input_data = host.input[0].addr
|
||||
|
||||
let cMsg = hostToComputationMessage(host.msg)
|
||||
host.computation = newComputation(vmState, cMsg, code)
|
||||
host.computation = newComputation(vmState, call.sysCall, cMsg, code)
|
||||
|
||||
shallowCopy(host.code, code)
|
||||
|
||||
|
@ -189,7 +190,7 @@ proc setupHost(call: CallParams): TransactionHost =
|
|||
host.msg.input_data = host.input[0].addr
|
||||
|
||||
let cMsg = hostToComputationMessage(host.msg)
|
||||
host.computation = newComputation(vmState, cMsg)
|
||||
host.computation = newComputation(vmState, call.sysCall, cMsg)
|
||||
|
||||
vmState.captureStart(host.computation, call.sender, call.to,
|
||||
call.isCreate, call.input,
|
||||
|
@ -297,7 +298,10 @@ proc runComputation*(call: CallParams): CallResult
|
|||
when defined(evmc_enabled):
|
||||
doExecEvmc(host, call)
|
||||
else:
|
||||
execComputation(host.computation)
|
||||
if host.computation.sysCall:
|
||||
execSysCall(host.computation)
|
||||
else:
|
||||
execComputation(host.computation)
|
||||
|
||||
finishRunningComputation(host, call)
|
||||
|
||||
|
|
|
@ -38,7 +38,10 @@ proc evmcExecute(vm: ptr evmc_vm, hostInterface: ptr evmc_host_interface,
|
|||
# host.computation = c
|
||||
|
||||
c.host.init(cast[ptr nimbus_host_interface](hostInterface), hostContext)
|
||||
execComputation(c)
|
||||
if c.sysCall:
|
||||
execSysCall(c)
|
||||
else:
|
||||
execComputation(c)
|
||||
|
||||
# When output size is zero, output data pointer may be null.
|
||||
var output_data: ptr byte
|
||||
|
|
|
@ -30,7 +30,7 @@ proc beforeExecCreateEvmcNested(host: TransactionHost,
|
|||
value: m.value.fromEvmc,
|
||||
data: @(makeOpenArray(m.inputData, m.inputSize.int))
|
||||
)
|
||||
return newComputation(host.vmState, childMsg,
|
||||
return newComputation(host.vmState, false, childMsg,
|
||||
cast[ContractSalt](m.create2_salt))
|
||||
|
||||
proc afterExecCreateEvmcNested(host: TransactionHost, child: Computation,
|
||||
|
@ -67,7 +67,7 @@ proc beforeExecCallEvmcNested(host: TransactionHost,
|
|||
data: @(makeOpenArray(m.inputData, m.inputSize.int)),
|
||||
flags: m.flags,
|
||||
)
|
||||
return newComputation(host.vmState, childMsg)
|
||||
return newComputation(host.vmState, false, childMsg)
|
||||
|
||||
proc afterExecCallEvmcNested(host: TransactionHost, child: Computation,
|
||||
res: var EvmcResult) {.inline.} =
|
||||
|
|
|
@ -13,6 +13,7 @@ import
|
|||
|
||||
export
|
||||
vmx.asyncExecComputation,
|
||||
vmx.execComputation
|
||||
vmx.execComputation,
|
||||
vmx.execSysCall
|
||||
|
||||
# End
|
||||
|
|
Loading…
Reference in New Issue