[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,
gasLimit, gasPrice: GasInt,
contractCreation: bool): BaseComputation =
let
# Handle optional defaults.
message = newMessage(
gas = gasLimit,
gasPrice = gasPrice,
to = destination,
sender = sender,
value = value,
data = data,
code = vmState.readOnlyStateDB.getCode(destination).toSeq,
contractCreation = contractCreation,
options = newMessageOptions(origin = sender,
createAddress = destination))
result = newBaseComputation(vmState, blockNumber, message)
#let
# # Handle optional defaults.
# message = newMessage(
# gas = gasLimit,
# gasPrice = gasPrice,
# to = destination,
# sender = sender,
# value = value,
# data = data,
# code = vmState.readOnlyStateDB.getCode(destination).toSeq,
# contractCreation = contractCreation,
# options = newMessageOptions(origin = sender,
# createAddress = destination))
#
#result = newBaseComputation(vmState, blockNumber, message)
rpcsrv.rpc("eth_call") do(call: EthCall, quantityTag: string) -> HexDataStr:
## 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 =
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) =
comp.dbsnapshot.transaction = comp.vmState.chaindb.db.beginTransaction()
comp.dbsnapshot.intermediateRoot = comp.vmState.accountDb.rootHash

View File

@ -576,18 +576,20 @@ proc setupCreate(computation: BaseComputation, memPos, len: int, value: Uint256,
push: 0
return
let childMsg = prepareChildMessage(
computation,
gas = createMsgGas,
to = CREATE_CONTRACT_ADDRESS,
value = value,
data = @[],
code = callData,
contractCreation = true,
options = MessageOptions(createAddress: contractAddress)
let childMsg = Message(
depth: computation.msg.depth + 1,
gas: createMsgGas,
gasPrice: computation.msg.gasPrice,
origin: computation.msg.origin,
sender: computation.msg.storageAddress,
storageAddress: contractAddress,
codeAddress: CREATE_CONTRACT_ADDRESS,
value: value,
data: @[],
code: callData,
contractCreation: true
)
childMsg.sender = computation.msg.storageAddress
result = newBaseComputation(
computation.vmState,
computation.vmState.blockNumber,
@ -627,13 +629,10 @@ proc callParams(computation: BaseComputation): (UInt256, UInt256, EthAddress, Et
memoryInputStartPosition, memoryInputSize,
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(5)
let to = codeAddress
let sender = computation.msg.storageAddress
result = (gas,
value,
to,
sender,
codeAddress, # contractAddress
computation.msg.storageAddress, # sender
codeAddress,
memoryInputStartPosition,
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) =
let gas = computation.stack.popInt()
let to = computation.stack.popAddress()
let codeAddress = computation.stack.popAddress()
let (value,
memoryInputStartPosition, memoryInputSize,
@ -651,9 +650,9 @@ proc callCodeParams(computation: BaseComputation): (UInt256, UInt256, EthAddress
result = (gas,
value,
to,
computation.msg.storageAddress, # sender
to, # code_address
computation.msg.storageAddress, # contractAddress
computation.msg.storageAddress, # sender
codeAddress,
memoryInputStartPosition,
memoryInputSize,
memoryOutputStartPosition,
@ -667,14 +666,10 @@ proc delegateCallParams(computation: BaseComputation): (UInt256, UInt256, EthAdd
let (memoryInputStartPosition, memoryInputSize,
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(4)
let to = computation.msg.storageAddress
let sender = computation.msg.sender
let value = computation.msg.value
result = (gas,
value,
to,
sender,
computation.msg.value, # value
computation.msg.storageAddress, # contractAddress
computation.msg.sender, # sender
codeAddress,
memoryInputStartPosition,
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) =
let gas = computation.stack.popInt()
let to = computation.stack.popAddress()
let codeAddress = computation.stack.popAddress()
let (memoryInputStartPosition, memoryInputSize,
memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(4)
result = (gas,
0.u256, # value
to,
codeAddress, # contractAddress
computation.msg.storageAddress, # sender
to, # codeAddress
codeAddress,
memoryInputStartPosition,
memoryInputSize,
memoryOutputStartPosition,
@ -702,7 +697,7 @@ proc staticCallParams(computation: BaseComputation): (UInt256, UInt256, EthAddre
template genCall(callName: untyped, opCode: Op): untyped =
proc `callName Setup`(computation: BaseComputation, callNameStr: string): BaseComputation =
let (gas, value, to, sender,
let (gas, value, contractAddress, sender,
codeAddress,
memoryInputStartPosition, memoryInputSize,
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 isNewAccount = if getFork(computation) >= FkSpurious:
computation.vmState.readOnlyStateDb.isDeadAccount(to)
computation.vmState.readOnlyStateDb.isDeadAccount(contractAddress)
else:
not computation.vmState.readOnlyStateDb.accountExists(to)
not computation.vmState.readOnlyStateDb.accountExists(contractAddress)
let (memOffset, memLength) = if calcMemSize(memInPos, memInLen) > calcMemSize(memOutPos, memOutLen):
(memInPos, memInLen)
@ -744,24 +739,19 @@ template genCall(callName: untyped, opCode: Op): untyped =
callData = computation.memory.read(memInPos, memInLen)
code = computation.vmState.readOnlyStateDb.getCode(codeAddress)
var childMsg = prepareChildMessage(
computation,
childGasLimit,
to,
value,
callData,
code.toSeq,
false,
MessageOptions(flags: flags)
)
childMsg.sender = sender
when opCode == CallCode:
childMsg.storageAddress = computation.msg.storageAddress
when opCode == DelegateCall:
childMsg.codeAddress = codeAddress
var childMsg = Message(
depth: computation.msg.depth + 1,
gas: childGasLimit,
gasPrice: computation.msg.gasPrice,
origin: computation.msg.origin,
sender: sender,
storageAddress: contractAddress,
codeAddress: codeAddress,
value: value,
data: callData,
code: code.toSeq,
contractCreation: false,
flags: flags)
var childComp = newBaseComputation(
computation.vmState,

View File

@ -9,95 +9,8 @@ import
eth/common,
../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 =
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 =
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
return
let msg = newMessage(
gas = gas,
gasPrice = tx.gasPrice,
to = tx.to,
sender = sender,
value = tx.value,
data = data,
code = code,
tx.isContractCreation,
options = newMessageOptions(origin = sender,
createAddress = recipient))
let msg = Message(
depth: 0,
gas: gas,
gasPrice: tx.gasPrice,
origin: sender,
sender: sender,
storageAddress: recipient,
codeAddress: tx.to,
value: tx.value,
data: data,
code: code,
contractCreation: tx.isContractCreation
)
result = newBaseComputation(vmState, vmState.blockNumber, msg, some(fork))
doAssert result.isOriginComputation

View File

@ -98,30 +98,15 @@ type
emvcStatic = 1
Message* = ref object
# A message for VM computation
# https://github.com/ethereum/evmc/blob/master/include/evmc/evmc.h
destination*: EthAddress
sender*: EthAddress
value*: UInt256
data*: seq[byte]
gas*: 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
depth*: int
createAddress*: EthAddress
codeAddress*: EthAddress
flags*: MsgFlags
depth*: int
gas*: GasInt
gasPrice*: GasInt
origin*: EthAddress
sender*: EthAddress
storageAddress*: EthAddress
codeAddress*: EthAddress
value*: UInt256
data*: seq[byte]
code*: seq[byte]
contractCreation*: bool
flags*: MsgFlags