2018-12-04 11:42:55 +00:00
|
|
|
import ../db/[db_chain, state_db], ../transaction, eth_common,
|
|
|
|
../vm_state, ../vm_types, ../vm_state_transactions, ranges,
|
|
|
|
chronicles, ../vm/[computation, interpreter_dispatch, message]
|
|
|
|
|
|
|
|
proc processTransaction*(db: var AccountStateDB, t: Transaction, sender: EthAddress, vmState: BaseVMState): UInt256 =
|
|
|
|
## Process the transaction, write the results to db.
|
|
|
|
## Returns amount of ETH to be rewarded to miner
|
2018-12-06 23:16:34 +00:00
|
|
|
trace "Sender", sender
|
|
|
|
trace "txHash", rlpHash = t.rlpHash
|
2018-12-04 11:42:55 +00:00
|
|
|
# Inct nonce:
|
|
|
|
db.setNonce(sender, db.getNonce(sender) + 1)
|
|
|
|
var transactionFailed = false
|
|
|
|
|
|
|
|
#t.dump
|
|
|
|
|
|
|
|
# TODO: combine/refactor re validate
|
|
|
|
let upfrontGasCost = t.gasLimit.u256 * t.gasPrice.u256
|
|
|
|
let upfrontCost = upfrontGasCost + t.value
|
|
|
|
var balance = db.getBalance(sender)
|
|
|
|
if balance < upfrontCost:
|
|
|
|
if balance <= upfrontGasCost:
|
|
|
|
result = balance
|
|
|
|
balance = 0.u256
|
|
|
|
else:
|
|
|
|
result = upfrontGasCost
|
|
|
|
balance -= upfrontGasCost
|
|
|
|
transactionFailed = true
|
|
|
|
else:
|
|
|
|
balance -= upfrontCost
|
|
|
|
|
|
|
|
db.setBalance(sender, balance)
|
|
|
|
if transactionFailed:
|
|
|
|
return
|
|
|
|
|
|
|
|
var gasUsed = t.payload.intrinsicGas.GasInt # += 32000 appears in Homestead when contract create
|
|
|
|
|
|
|
|
if gasUsed > t.gasLimit:
|
2018-12-06 23:16:34 +00:00
|
|
|
debug "Transaction failed. Out of gas."
|
2018-12-04 11:42:55 +00:00
|
|
|
transactionFailed = true
|
|
|
|
else:
|
|
|
|
if t.isContractCreation:
|
|
|
|
# TODO: re-derive sender in callee for cleaner interface, perhaps
|
|
|
|
return applyCreateTransaction(db, t, vmState, sender)
|
|
|
|
|
|
|
|
else:
|
|
|
|
let code = db.getCode(t.to)
|
|
|
|
if code.len == 0:
|
|
|
|
# Value transfer
|
2018-12-06 23:16:34 +00:00
|
|
|
trace "Transfer", value = t.value, sender, to = t.to
|
2018-12-04 11:42:55 +00:00
|
|
|
|
|
|
|
db.addBalance(t.to, t.value)
|
|
|
|
else:
|
|
|
|
# Contract call
|
2018-12-06 23:16:34 +00:00
|
|
|
trace "Contract call"
|
|
|
|
trace "Transaction", sender, to = t.to, value = t.value, hasCode = code.len != 0
|
2018-12-04 11:42:55 +00:00
|
|
|
let msg = newMessage(t.gasLimit, t.gasPrice, t.to, sender, t.value, t.payload, code.toSeq)
|
|
|
|
# TODO: Run the vm
|
|
|
|
|
|
|
|
if gasUsed > t.gasLimit:
|
|
|
|
gasUsed = t.gasLimit
|
|
|
|
|
|
|
|
var refund = (t.gasLimit - gasUsed).u256 * t.gasPrice.u256
|
|
|
|
if transactionFailed:
|
|
|
|
refund += t.value
|
|
|
|
|
|
|
|
db.addBalance(sender, refund)
|
|
|
|
|
|
|
|
return gasUsed.u256 * t.gasPrice.u256
|