[skip ci] simplify EVM message creation
This commit is contained in:
parent
727b477fca
commit
40ddbca1ee
|
@ -277,21 +277,21 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) =
|
||||||
sender, destination: EthAddress,
|
sender, destination: EthAddress,
|
||||||
gasLimit, gasPrice: GasInt,
|
gasLimit, gasPrice: GasInt,
|
||||||
contractCreation: bool): BaseComputation =
|
contractCreation: bool): BaseComputation =
|
||||||
let
|
#let
|
||||||
# Handle optional defaults.
|
# # Handle optional defaults.
|
||||||
message = newMessage(
|
# message = newMessage(
|
||||||
gas = gasLimit,
|
# gas = gasLimit,
|
||||||
gasPrice = gasPrice,
|
# gasPrice = gasPrice,
|
||||||
to = destination,
|
# to = destination,
|
||||||
sender = sender,
|
# sender = sender,
|
||||||
value = value,
|
# value = value,
|
||||||
data = data,
|
# data = data,
|
||||||
code = vmState.readOnlyStateDB.getCode(destination).toSeq,
|
# code = vmState.readOnlyStateDB.getCode(destination).toSeq,
|
||||||
contractCreation = contractCreation,
|
# contractCreation = contractCreation,
|
||||||
options = newMessageOptions(origin = sender,
|
# options = newMessageOptions(origin = sender,
|
||||||
createAddress = destination))
|
# createAddress = destination))
|
||||||
|
#
|
||||||
result = newBaseComputation(vmState, blockNumber, message)
|
#result = newBaseComputation(vmState, blockNumber, message)
|
||||||
|
|
||||||
rpcsrv.rpc("eth_call") do(call: EthCall, quantityTag: string) -> HexDataStr:
|
rpcsrv.rpc("eth_call") do(call: EthCall, quantityTag: string) -> HexDataStr:
|
||||||
## Executes a new message call immediately without creating a transaction on the block chain.
|
## Executes a new message call immediately without creating a transaction on the block chain.
|
||||||
|
|
|
@ -76,29 +76,6 @@ proc outputHex*(c: BaseComputation): string =
|
||||||
proc isSuicided*(c: BaseComputation, address: EthAddress): bool =
|
proc isSuicided*(c: BaseComputation, address: EthAddress): bool =
|
||||||
result = address in c.accountsToDelete
|
result = address in c.accountsToDelete
|
||||||
|
|
||||||
proc prepareChildMessage*(
|
|
||||||
c: BaseComputation,
|
|
||||||
gas: GasInt,
|
|
||||||
to: EthAddress,
|
|
||||||
value: UInt256,
|
|
||||||
data: seq[byte],
|
|
||||||
code: seq[byte],
|
|
||||||
contractCreation: bool,
|
|
||||||
options: MessageOptions = newMessageOptions()): Message =
|
|
||||||
|
|
||||||
var childOptions = options
|
|
||||||
childOptions.depth = c.msg.depth + 1
|
|
||||||
result = newMessage(
|
|
||||||
gas,
|
|
||||||
c.msg.gasPrice,
|
|
||||||
to,
|
|
||||||
c.msg.origin,
|
|
||||||
value,
|
|
||||||
data,
|
|
||||||
code,
|
|
||||||
contractCreation,
|
|
||||||
childOptions)
|
|
||||||
|
|
||||||
proc snapshot*(comp: BaseComputation) =
|
proc snapshot*(comp: BaseComputation) =
|
||||||
comp.dbsnapshot.transaction = comp.vmState.chaindb.db.beginTransaction()
|
comp.dbsnapshot.transaction = comp.vmState.chaindb.db.beginTransaction()
|
||||||
comp.dbsnapshot.intermediateRoot = comp.vmState.accountDb.rootHash
|
comp.dbsnapshot.intermediateRoot = comp.vmState.accountDb.rootHash
|
||||||
|
|
|
@ -576,18 +576,20 @@ proc setupCreate(computation: BaseComputation, memPos, len: int, value: Uint256,
|
||||||
push: 0
|
push: 0
|
||||||
return
|
return
|
||||||
|
|
||||||
let childMsg = prepareChildMessage(
|
let childMsg = Message(
|
||||||
computation,
|
depth: computation.msg.depth + 1,
|
||||||
gas = createMsgGas,
|
gas: createMsgGas,
|
||||||
to = CREATE_CONTRACT_ADDRESS,
|
gasPrice: computation.msg.gasPrice,
|
||||||
value = value,
|
origin: computation.msg.origin,
|
||||||
data = @[],
|
sender: computation.msg.storageAddress,
|
||||||
code = callData,
|
storageAddress: contractAddress,
|
||||||
contractCreation = true,
|
codeAddress: CREATE_CONTRACT_ADDRESS,
|
||||||
options = MessageOptions(createAddress: contractAddress)
|
value: value,
|
||||||
|
data: @[],
|
||||||
|
code: callData,
|
||||||
|
contractCreation: true
|
||||||
)
|
)
|
||||||
|
|
||||||
childMsg.sender = computation.msg.storageAddress
|
|
||||||
result = newBaseComputation(
|
result = newBaseComputation(
|
||||||
computation.vmState,
|
computation.vmState,
|
||||||
computation.vmState.blockNumber,
|
computation.vmState.blockNumber,
|
||||||
|
@ -627,13 +629,10 @@ proc callParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, Et
|
||||||
memoryInputStartPosition, memoryInputSize,
|
memoryInputStartPosition, memoryInputSize,
|
||||||
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(5)
|
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(5)
|
||||||
|
|
||||||
let to = codeAddress
|
|
||||||
let sender = computation.msg.storageAddress
|
|
||||||
|
|
||||||
result = (gas,
|
result = (gas,
|
||||||
value,
|
value,
|
||||||
to,
|
codeAddress, # contractAddress
|
||||||
sender,
|
computation.msg.storageAddress, # sender
|
||||||
codeAddress,
|
codeAddress,
|
||||||
memoryInputStartPosition,
|
memoryInputStartPosition,
|
||||||
memoryInputSize,
|
memoryInputSize,
|
||||||
|
@ -643,7 +642,7 @@ proc callParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, Et
|
||||||
|
|
||||||
proc callCodeParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, EthAddress, EthAddress, UInt256, UInt256, UInt256, UInt256, MsgFlags) =
|
proc callCodeParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, EthAddress, EthAddress, UInt256, UInt256, UInt256, UInt256, MsgFlags) =
|
||||||
let gas = computation.stack.popInt()
|
let gas = computation.stack.popInt()
|
||||||
let to = computation.stack.popAddress()
|
let codeAddress = computation.stack.popAddress()
|
||||||
|
|
||||||
let (value,
|
let (value,
|
||||||
memoryInputStartPosition, memoryInputSize,
|
memoryInputStartPosition, memoryInputSize,
|
||||||
|
@ -651,9 +650,9 @@ proc callCodeParams(computation: BaseComputation): (UInt256, UInt256, EthAddress
|
||||||
|
|
||||||
result = (gas,
|
result = (gas,
|
||||||
value,
|
value,
|
||||||
to,
|
computation.msg.storageAddress, # contractAddress
|
||||||
computation.msg.storageAddress, # sender
|
computation.msg.storageAddress, # sender
|
||||||
to, # code_address
|
codeAddress,
|
||||||
memoryInputStartPosition,
|
memoryInputStartPosition,
|
||||||
memoryInputSize,
|
memoryInputSize,
|
||||||
memoryOutputStartPosition,
|
memoryOutputStartPosition,
|
||||||
|
@ -667,14 +666,10 @@ proc delegateCallParams(computation: BaseComputation): (UInt256, UInt256, EthAdd
|
||||||
let (memoryInputStartPosition, memoryInputSize,
|
let (memoryInputStartPosition, memoryInputSize,
|
||||||
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(4)
|
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(4)
|
||||||
|
|
||||||
let to = computation.msg.storageAddress
|
|
||||||
let sender = computation.msg.sender
|
|
||||||
let value = computation.msg.value
|
|
||||||
|
|
||||||
result = (gas,
|
result = (gas,
|
||||||
value,
|
computation.msg.value, # value
|
||||||
to,
|
computation.msg.storageAddress, # contractAddress
|
||||||
sender,
|
computation.msg.sender, # sender
|
||||||
codeAddress,
|
codeAddress,
|
||||||
memoryInputStartPosition,
|
memoryInputStartPosition,
|
||||||
memoryInputSize,
|
memoryInputSize,
|
||||||
|
@ -684,16 +679,16 @@ proc delegateCallParams(computation: BaseComputation): (UInt256, UInt256, EthAdd
|
||||||
|
|
||||||
proc staticCallParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, EthAddress, EthAddress, UInt256, UInt256, UInt256, UInt256, MsgFlags) =
|
proc staticCallParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, EthAddress, EthAddress, UInt256, UInt256, UInt256, UInt256, MsgFlags) =
|
||||||
let gas = computation.stack.popInt()
|
let gas = computation.stack.popInt()
|
||||||
let to = computation.stack.popAddress()
|
let codeAddress = computation.stack.popAddress()
|
||||||
|
|
||||||
let (memoryInputStartPosition, memoryInputSize,
|
let (memoryInputStartPosition, memoryInputSize,
|
||||||
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(4)
|
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(4)
|
||||||
|
|
||||||
result = (gas,
|
result = (gas,
|
||||||
0.u256, # value
|
0.u256, # value
|
||||||
to,
|
codeAddress, # contractAddress
|
||||||
computation.msg.storageAddress, # sender
|
computation.msg.storageAddress, # sender
|
||||||
to, # codeAddress
|
codeAddress,
|
||||||
memoryInputStartPosition,
|
memoryInputStartPosition,
|
||||||
memoryInputSize,
|
memoryInputSize,
|
||||||
memoryOutputStartPosition,
|
memoryOutputStartPosition,
|
||||||
|
@ -702,7 +697,7 @@ proc staticCallParams(computation: BaseComputation): (UInt256, UInt256, EthAddre
|
||||||
|
|
||||||
template genCall(callName: untyped, opCode: Op): untyped =
|
template genCall(callName: untyped, opCode: Op): untyped =
|
||||||
proc `callName Setup`(computation: BaseComputation, callNameStr: string): BaseComputation =
|
proc `callName Setup`(computation: BaseComputation, callNameStr: string): BaseComputation =
|
||||||
let (gas, value, to, sender,
|
let (gas, value, contractAddress, sender,
|
||||||
codeAddress,
|
codeAddress,
|
||||||
memoryInputStartPosition, memoryInputSize,
|
memoryInputStartPosition, memoryInputSize,
|
||||||
memoryOutputStartPosition, memoryOutputSize,
|
memoryOutputStartPosition, memoryOutputSize,
|
||||||
|
@ -711,9 +706,9 @@ template genCall(callName: untyped, opCode: Op): untyped =
|
||||||
let (memInPos, memInLen, memOutPos, memOutLen) = (memoryInputStartPosition.cleanMemRef, memoryInputSize.cleanMemRef, memoryOutputStartPosition.cleanMemRef, memoryOutputSize.cleanMemRef)
|
let (memInPos, memInLen, memOutPos, memOutLen) = (memoryInputStartPosition.cleanMemRef, memoryInputSize.cleanMemRef, memoryOutputStartPosition.cleanMemRef, memoryOutputSize.cleanMemRef)
|
||||||
|
|
||||||
let isNewAccount = if getFork(computation) >= FkSpurious:
|
let isNewAccount = if getFork(computation) >= FkSpurious:
|
||||||
computation.vmState.readOnlyStateDb.isDeadAccount(to)
|
computation.vmState.readOnlyStateDb.isDeadAccount(contractAddress)
|
||||||
else:
|
else:
|
||||||
not computation.vmState.readOnlyStateDb.accountExists(to)
|
not computation.vmState.readOnlyStateDb.accountExists(contractAddress)
|
||||||
|
|
||||||
let (memOffset, memLength) = if calcMemSize(memInPos, memInLen) > calcMemSize(memOutPos, memOutLen):
|
let (memOffset, memLength) = if calcMemSize(memInPos, memInLen) > calcMemSize(memOutPos, memOutLen):
|
||||||
(memInPos, memInLen)
|
(memInPos, memInLen)
|
||||||
|
@ -744,24 +739,19 @@ template genCall(callName: untyped, opCode: Op): untyped =
|
||||||
callData = computation.memory.read(memInPos, memInLen)
|
callData = computation.memory.read(memInPos, memInLen)
|
||||||
code = computation.vmState.readOnlyStateDb.getCode(codeAddress)
|
code = computation.vmState.readOnlyStateDb.getCode(codeAddress)
|
||||||
|
|
||||||
var childMsg = prepareChildMessage(
|
var childMsg = Message(
|
||||||
computation,
|
depth: computation.msg.depth + 1,
|
||||||
childGasLimit,
|
gas: childGasLimit,
|
||||||
to,
|
gasPrice: computation.msg.gasPrice,
|
||||||
value,
|
origin: computation.msg.origin,
|
||||||
callData,
|
sender: sender,
|
||||||
code.toSeq,
|
storageAddress: contractAddress,
|
||||||
false,
|
codeAddress: codeAddress,
|
||||||
MessageOptions(flags: flags)
|
value: value,
|
||||||
)
|
data: callData,
|
||||||
|
code: code.toSeq,
|
||||||
childMsg.sender = sender
|
contractCreation: false,
|
||||||
|
flags: flags)
|
||||||
when opCode == CallCode:
|
|
||||||
childMsg.storageAddress = computation.msg.storageAddress
|
|
||||||
|
|
||||||
when opCode == DelegateCall:
|
|
||||||
childMsg.codeAddress = codeAddress
|
|
||||||
|
|
||||||
var childComp = newBaseComputation(
|
var childComp = newBaseComputation(
|
||||||
computation.vmState,
|
computation.vmState,
|
||||||
|
|
|
@ -9,95 +9,8 @@ import
|
||||||
eth/common,
|
eth/common,
|
||||||
../constants, ../validation, ../vm_types, chronicles
|
../constants, ../validation, ../vm_types, chronicles
|
||||||
|
|
||||||
logScope:
|
|
||||||
topics = "message"
|
|
||||||
|
|
||||||
proc `origin=`*(message: var Message, value: EthAddress) =
|
|
||||||
message.internalOrigin = value
|
|
||||||
|
|
||||||
proc `codeAddress=`*(message: var Message, value: EthAddress) =
|
|
||||||
message.internalCodeAddress = value
|
|
||||||
|
|
||||||
proc `storageAddress=`*(message: var Message, value: EthAddress) =
|
|
||||||
message.internalStorageAddress = value
|
|
||||||
|
|
||||||
proc newMessageOptions*(
|
|
||||||
origin = ZERO_ADDRESS,
|
|
||||||
depth: int = 0,
|
|
||||||
createAddress = ZERO_ADDRESS,
|
|
||||||
codeAddress = ZERO_ADDRESS,
|
|
||||||
flags: MsgFlags = static(emvcNoFlags)): MessageOptions =
|
|
||||||
|
|
||||||
result = MessageOptions(
|
|
||||||
origin: origin,
|
|
||||||
depth: depth,
|
|
||||||
createAddress: createAddress,
|
|
||||||
codeAddress: codeAddress,
|
|
||||||
flags: flags)
|
|
||||||
|
|
||||||
proc newMessage*(
|
|
||||||
gas: GasInt,
|
|
||||||
gasPrice: GasInt,
|
|
||||||
to: EthAddress,
|
|
||||||
sender: EthAddress,
|
|
||||||
value: UInt256,
|
|
||||||
data: seq[byte],
|
|
||||||
code: seq[byte],
|
|
||||||
contractCreation: bool,
|
|
||||||
options: MessageOptions = newMessageOptions()): Message =
|
|
||||||
|
|
||||||
validateGte(options.depth, minimum=0, title="Message.depth")
|
|
||||||
|
|
||||||
trace "New message",
|
|
||||||
gas = gas,
|
|
||||||
gasPrice = gasPrice,
|
|
||||||
destination = to,
|
|
||||||
sender = sender,
|
|
||||||
value = value,
|
|
||||||
depth = options.depth,
|
|
||||||
storageAddress = options.createAddress,
|
|
||||||
codeAddress = options.codeAddress,
|
|
||||||
contractCreation = contractCreation
|
|
||||||
|
|
||||||
new(result)
|
|
||||||
result.gas = gas
|
|
||||||
result.gasPrice = gasPrice
|
|
||||||
result.destination = to
|
|
||||||
result.sender = sender
|
|
||||||
result.value = value
|
|
||||||
result.data = data
|
|
||||||
result.depth = options.depth
|
|
||||||
result.storageAddress = options.createAddress
|
|
||||||
result.codeAddress = options.codeAddress
|
|
||||||
result.flags = options.flags
|
|
||||||
result.code = code
|
|
||||||
result.contractCreation = contractCreation
|
|
||||||
|
|
||||||
if options.origin != ZERO_ADDRESS:
|
|
||||||
result.internalOrigin = options.origin
|
|
||||||
else:
|
|
||||||
result.internalOrigin = sender
|
|
||||||
|
|
||||||
proc origin*(message: Message): EthAddress =
|
|
||||||
if message.internalOrigin != ZERO_ADDRESS:
|
|
||||||
message.internalOrigin
|
|
||||||
else:
|
|
||||||
message.sender
|
|
||||||
|
|
||||||
proc isOrigin*(message: Message): bool =
|
proc isOrigin*(message: Message): bool =
|
||||||
message.sender == message.origin
|
message.sender == message.origin
|
||||||
|
|
||||||
proc codeAddress*(message: Message): EthAddress =
|
|
||||||
if message.internalCodeAddress != ZERO_ADDRESS:
|
|
||||||
message.internalCodeAddress
|
|
||||||
else:
|
|
||||||
message.destination
|
|
||||||
|
|
||||||
proc `storageAddress`*(message: Message): EthAddress =
|
|
||||||
if message.internalStorageAddress != ZERO_ADDRESS:
|
|
||||||
message.internalStorageAddress
|
|
||||||
else:
|
|
||||||
message.destination
|
|
||||||
|
|
||||||
proc isCreate*(message: Message): bool =
|
proc isCreate*(message: Message): bool =
|
||||||
message.contractCreation
|
message.contractCreation
|
||||||
|
|
|
@ -44,17 +44,19 @@ proc setupComputation*(vmState: BaseVMState, tx: Transaction, sender, recipient:
|
||||||
debug "not enough gas to perform calculation", gas=gas
|
debug "not enough gas to perform calculation", gas=gas
|
||||||
return
|
return
|
||||||
|
|
||||||
let msg = newMessage(
|
let msg = Message(
|
||||||
gas = gas,
|
depth: 0,
|
||||||
gasPrice = tx.gasPrice,
|
gas: gas,
|
||||||
to = tx.to,
|
gasPrice: tx.gasPrice,
|
||||||
sender = sender,
|
origin: sender,
|
||||||
value = tx.value,
|
sender: sender,
|
||||||
data = data,
|
storageAddress: recipient,
|
||||||
code = code,
|
codeAddress: tx.to,
|
||||||
tx.isContractCreation,
|
value: tx.value,
|
||||||
options = newMessageOptions(origin = sender,
|
data: data,
|
||||||
createAddress = recipient))
|
code: code,
|
||||||
|
contractCreation: tx.isContractCreation
|
||||||
|
)
|
||||||
|
|
||||||
result = newBaseComputation(vmState, vmState.blockNumber, msg, some(fork))
|
result = newBaseComputation(vmState, vmState.blockNumber, msg, some(fork))
|
||||||
doAssert result.isOriginComputation
|
doAssert result.isOriginComputation
|
||||||
|
|
|
@ -98,30 +98,15 @@ type
|
||||||
emvcStatic = 1
|
emvcStatic = 1
|
||||||
|
|
||||||
Message* = ref object
|
Message* = ref object
|
||||||
# A message for VM computation
|
depth*: int
|
||||||
# https://github.com/ethereum/evmc/blob/master/include/evmc/evmc.h
|
|
||||||
destination*: EthAddress
|
|
||||||
sender*: EthAddress
|
|
||||||
value*: UInt256
|
|
||||||
data*: seq[byte]
|
|
||||||
gas*: GasInt
|
gas*: GasInt
|
||||||
gasPrice*: GasInt
|
gasPrice*: GasInt
|
||||||
depth*: int
|
|
||||||
#kind*: CallKind
|
|
||||||
flags*: MsgFlags
|
|
||||||
|
|
||||||
# Not in EVMC API
|
|
||||||
# TODO: Done via callback function (v)table in EVMC
|
|
||||||
code*: seq[byte]
|
|
||||||
|
|
||||||
internalOrigin*: EthAddress
|
|
||||||
internalCodeAddress*: EthAddress
|
|
||||||
internalStorageAddress*: EthAddress
|
|
||||||
contractCreation*: bool
|
|
||||||
|
|
||||||
MessageOptions* = ref object
|
|
||||||
origin*: EthAddress
|
origin*: EthAddress
|
||||||
depth*: int
|
sender*: EthAddress
|
||||||
createAddress*: EthAddress
|
storageAddress*: EthAddress
|
||||||
codeAddress*: EthAddress
|
codeAddress*: EthAddress
|
||||||
|
value*: UInt256
|
||||||
|
data*: seq[byte]
|
||||||
|
code*: seq[byte]
|
||||||
|
contractCreation*: bool
|
||||||
flags*: MsgFlags
|
flags*: MsgFlags
|
||||||
|
|
Loading…
Reference in New Issue