[skip ci] simplify EVM message creation

This commit is contained in:
andri lim 2020-01-07 22:44:38 +07:00 committed by zah
parent 727b477fca
commit 40ddbca1ee
6 changed files with 80 additions and 213 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 gas*: GasInt
destination*: EthAddress gasPrice*: GasInt
sender*: EthAddress origin*: EthAddress
value*: UInt256 sender*: EthAddress
data*: seq[byte] storageAddress*: EthAddress
gas*: GasInt codeAddress*: EthAddress
gasPrice*: GasInt value*: UInt256
depth*: int data*: seq[byte]
#kind*: CallKind code*: seq[byte]
flags*: MsgFlags contractCreation*: bool
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
depth*: int
createAddress*: EthAddress
codeAddress*: EthAddress
flags*: MsgFlags