mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-13 22:04:52 +00:00
refactor gas used in transaction
This commit is contained in:
parent
f21f73e5c5
commit
8193a4ae6a
@ -6,7 +6,7 @@ import options,
|
|||||||
../vm/[computation, interpreter_dispatch, message],
|
../vm/[computation, interpreter_dispatch, message],
|
||||||
../vm/interpreter/vm_forks
|
../vm/interpreter/vm_forks
|
||||||
|
|
||||||
proc contractCall(t: Transaction, vmState: BaseVMState, sender: EthAddress, forkOverride=none(Fork)): UInt256 =
|
proc contractCall(tx: Transaction, vmState: BaseVMState, sender: EthAddress, forkOverride=none(Fork)): GasInt =
|
||||||
# TODO: this function body was copied from GST with it's comments and TODOs.
|
# TODO: this function body was copied from GST with it's comments and TODOs.
|
||||||
# Right now it's main purpose is to produce VM tracing when syncing block with
|
# Right now it's main purpose is to produce VM tracing when syncing block with
|
||||||
# contract call. At later stage, this proc together with applyCreateTransaction
|
# contract call. At later stage, this proc together with applyCreateTransaction
|
||||||
@ -15,33 +15,30 @@ proc contractCall(t: Transaction, vmState: BaseVMState, sender: EthAddress, fork
|
|||||||
# TODO: replace with cachingDb or similar approach; necessary
|
# TODO: replace with cachingDb or similar approach; necessary
|
||||||
# when calls/subcalls/etc come in, too.
|
# when calls/subcalls/etc come in, too.
|
||||||
var db = vmState.accountDb
|
var db = vmState.accountDb
|
||||||
let storageRoot = db.getStorageRoot(t.to)
|
let storageRoot = db.getStorageRoot(tx.to)
|
||||||
|
|
||||||
var computation = setupComputation(vmState, t, sender, forkOverride)
|
var computation = setupComputation(vmState, tx, sender, forkOverride)
|
||||||
# contract creation transaction.to == 0, so ensure happens after
|
# contract creation transaction.to == 0, so ensure happens after
|
||||||
db.addBalance(t.to, t.value)
|
db.addBalance(tx.to, tx.value)
|
||||||
|
|
||||||
let header = vmState.blockHeader
|
|
||||||
let gasCost = t.gasLimit.u256 * t.gasPrice.u256
|
|
||||||
|
|
||||||
if execComputation(computation):
|
if execComputation(computation):
|
||||||
let
|
let
|
||||||
gasRemaining = computation.gasMeter.gasRemaining.u256
|
gasRemaining = computation.gasMeter.gasRemaining
|
||||||
gasRefunded = computation.getGasRefund().u256
|
gasRefunded = computation.getGasRefund()
|
||||||
gasUsed = t.gasLimit.u256 - gasRemaining
|
gasUsed = tx.gasLimit - gasRemaining
|
||||||
gasRefund = min(gasRefunded, gasUsed div 2)
|
gasRefund = min(gasRefunded, gasUsed div 2)
|
||||||
gasRefundAmount = (gasRefund + gasRemaining) * t.gasPrice.u256
|
gasRefundAmount = (gasRefund + gasRemaining).u256 * tx.gasPrice.u256
|
||||||
|
|
||||||
db.addBalance(sender, gasRefundAmount)
|
db.addBalance(sender, gasRefundAmount)
|
||||||
|
|
||||||
return (t.gasLimit.u256 - gasRemaining - gasRefund) * t.gasPrice.u256
|
return (tx.gasLimit - gasRemaining - gasRefund)
|
||||||
else:
|
else:
|
||||||
db.subBalance(t.to, t.value)
|
db.subBalance(tx.to, tx.value)
|
||||||
db.addBalance(sender, t.value)
|
db.addBalance(sender, tx.value)
|
||||||
db.setStorageRoot(t.to, storageRoot)
|
db.setStorageRoot(tx.to, storageRoot)
|
||||||
if computation.tracingEnabled: computation.traceError()
|
if computation.tracingEnabled: computation.traceError()
|
||||||
vmState.clearLogs()
|
vmState.clearLogs()
|
||||||
return t.gasLimit.u256 * t.gasPrice.u256
|
return tx.gasLimit
|
||||||
|
|
||||||
# this proc should not be here, we need to refactor
|
# this proc should not be here, we need to refactor
|
||||||
# processTransaction
|
# processTransaction
|
||||||
@ -50,7 +47,7 @@ proc isPrecompiles*(address: EthAddress): bool {.inline.} =
|
|||||||
if address[i] != 0: return
|
if address[i] != 0: return
|
||||||
result = address[19] >= 1.byte and address[19] <= 8.byte
|
result = address[19] >= 1.byte and address[19] <= 8.byte
|
||||||
|
|
||||||
proc processTransaction*(t: Transaction, sender: EthAddress, vmState: BaseVMState): UInt256 =
|
proc processTransaction*(t: Transaction, sender: EthAddress, vmState: BaseVMState): GasInt =
|
||||||
## Process the transaction, write the results to db.
|
## Process the transaction, write the results to db.
|
||||||
## Returns amount of ETH to be rewarded to miner
|
## Returns amount of ETH to be rewarded to miner
|
||||||
trace "Sender", sender
|
trace "Sender", sender
|
||||||
@ -68,10 +65,10 @@ proc processTransaction*(t: Transaction, sender: EthAddress, vmState: BaseVMStat
|
|||||||
var balance = db.getBalance(sender)
|
var balance = db.getBalance(sender)
|
||||||
if balance < upfrontCost:
|
if balance < upfrontCost:
|
||||||
if balance <= upfrontGasCost:
|
if balance <= upfrontGasCost:
|
||||||
result = balance
|
result = (balance div t.gasPrice.u256).truncate(GasInt)
|
||||||
balance = 0.u256
|
balance = 0.u256
|
||||||
else:
|
else:
|
||||||
result = upfrontGasCost
|
result = t.gasLimit
|
||||||
balance -= upfrontGasCost
|
balance -= upfrontGasCost
|
||||||
transactionFailed = true
|
transactionFailed = true
|
||||||
else:
|
else:
|
||||||
@ -81,7 +78,7 @@ proc processTransaction*(t: Transaction, sender: EthAddress, vmState: BaseVMStat
|
|||||||
if transactionFailed:
|
if transactionFailed:
|
||||||
return
|
return
|
||||||
|
|
||||||
var gasUsed = t.payload.intrinsicGas.GasInt # += 32000 appears in Homestead when contract create
|
var gasUsed = t.intrinsicGas # += 32000 appears in Homestead when contract create
|
||||||
|
|
||||||
if gasUsed > t.gasLimit:
|
if gasUsed > t.gasLimit:
|
||||||
debug "Transaction failed. Out of gas."
|
debug "Transaction failed. Out of gas."
|
||||||
@ -114,7 +111,7 @@ proc processTransaction*(t: Transaction, sender: EthAddress, vmState: BaseVMStat
|
|||||||
refund += t.value
|
refund += t.value
|
||||||
|
|
||||||
db.addBalance(sender, refund)
|
db.addBalance(sender, refund)
|
||||||
return gasUsed.u256 * t.gasPrice.u256
|
return gasUsed
|
||||||
|
|
||||||
type
|
type
|
||||||
# TODO: these types need to be removed
|
# TODO: these types need to be removed
|
||||||
@ -167,15 +164,11 @@ proc processBlock*(chainDB: BaseChainDB, head, header: BlockHeader, body: BlockB
|
|||||||
for txIndex, tx in body.transactions:
|
for txIndex, tx in body.transactions:
|
||||||
var sender: EthAddress
|
var sender: EthAddress
|
||||||
if tx.getSender(sender):
|
if tx.getSender(sender):
|
||||||
let txFee = processTransaction(tx, sender, vmState)
|
let gasUsed = processTransaction(tx, sender, vmState)
|
||||||
|
|
||||||
# perhaps this can be altered somehow
|
|
||||||
# or processTransaction return only gasUsed
|
|
||||||
# a `div` here is ugly and possibly div by zero
|
|
||||||
let gasUsed = (txFee div tx.gasPrice.u256).truncate(GasInt)
|
|
||||||
cumulativeGasUsed += gasUsed
|
cumulativeGasUsed += gasUsed
|
||||||
|
|
||||||
# miner fee
|
# miner fee
|
||||||
|
let txFee = gasUsed.u256 * tx.gasPrice.u256
|
||||||
stateDb.addBalance(header.coinbase, txFee)
|
stateDb.addBalance(header.coinbase, txFee)
|
||||||
else:
|
else:
|
||||||
debug "Could not get sender", txIndex, tx
|
debug "Could not get sender", txIndex, tx
|
||||||
|
@ -102,11 +102,11 @@ proc traceTransaction*(db: BaseChainDB, header: BlockHeader,
|
|||||||
stateDiff["beforeRoot"] = %($stateDb.rootHash)
|
stateDiff["beforeRoot"] = %($stateDb.rootHash)
|
||||||
beforeRoot = stateDb.rootHash
|
beforeRoot = stateDb.rootHash
|
||||||
|
|
||||||
let txFee = processTransaction(tx, sender, vmState)
|
let gasUsed = processTransaction(tx, sender, vmState)
|
||||||
|
let txFee = gasUsed.u256 * tx.gasPrice.u256
|
||||||
stateDb.addBalance(header.coinbase, txFee)
|
stateDb.addBalance(header.coinbase, txFee)
|
||||||
|
|
||||||
if idx == txIndex:
|
if idx == txIndex:
|
||||||
gasUsed = (txFee div tx.gasPrice.u256).truncate(GasInt)
|
|
||||||
after.captureAccount(stateDb, sender, senderName)
|
after.captureAccount(stateDb, sender, senderName)
|
||||||
after.captureAccount(stateDb, recipient, recipientName)
|
after.captureAccount(stateDb, recipient, recipientName)
|
||||||
after.captureAccount(stateDb, header.coinbase, minerName)
|
after.captureAccount(stateDb, header.coinbase, minerName)
|
||||||
@ -204,10 +204,8 @@ proc traceBlock*(db: BaseChainDB, header: BlockHeader, body: BlockBody, tracerFl
|
|||||||
var gasUsed = GasInt(0)
|
var gasUsed = GasInt(0)
|
||||||
|
|
||||||
for tx in body.transactions:
|
for tx in body.transactions:
|
||||||
let
|
let sender = tx.getSender
|
||||||
sender = tx.getSender
|
gasUsed = gasUsed + processTransaction(tx, sender, vmState)
|
||||||
txFee = processTransaction(tx, sender, vmState)
|
|
||||||
gasUsed = gasUsed + (txFee div tx.gasPrice.u256).truncate(GasInt)
|
|
||||||
|
|
||||||
result = vmState.getTracingResult()
|
result = vmState.getTracingResult()
|
||||||
result["gas"] = %gasUsed
|
result["gas"] = %gasUsed
|
||||||
|
@ -80,7 +80,7 @@ proc execComputation*(computation: var BaseComputation): bool =
|
|||||||
else:
|
else:
|
||||||
snapshot.revert()
|
snapshot.revert()
|
||||||
|
|
||||||
proc applyCreateTransaction*(tx: Transaction, vmState: BaseVMState, sender: EthAddress, forkOverride=none(Fork)): UInt256 =
|
proc applyCreateTransaction*(tx: Transaction, vmState: BaseVMState, sender: EthAddress, forkOverride=none(Fork)): GasInt =
|
||||||
doAssert tx.isContractCreation
|
doAssert tx.isContractCreation
|
||||||
# TODO: clean up params
|
# TODO: clean up params
|
||||||
trace "Contract creation"
|
trace "Contract creation"
|
||||||
@ -96,12 +96,10 @@ proc applyCreateTransaction*(tx: Transaction, vmState: BaseVMState, sender: EthA
|
|||||||
# also a couple lines can collapse because variable used once
|
# also a couple lines can collapse because variable used once
|
||||||
# once verified in GST fixture
|
# once verified in GST fixture
|
||||||
let
|
let
|
||||||
gasRemaining = c.gasMeter.gasRemaining.u256
|
gasRemaining = c.gasMeter.gasRemaining
|
||||||
gasRefunded = c.getGasRefund().u256
|
gasRefunded = c.getGasRefund()
|
||||||
gasUsed = tx.gasLimit.u256 - gasRemaining
|
gasUsed = tx.gasLimit - gasRemaining
|
||||||
gasRefund = min(gasRefunded, gasUsed div 2)
|
gasRefund = min(gasRefunded, gasUsed div 2)
|
||||||
gasRefundAmount = (gasRefund + gasRemaining) * tx.gasPrice.u256
|
|
||||||
#echo "gasRemaining is ", gasRemaining, " and gasRefunded = ", gasRefunded, " and gasUsed = ", gasUsed, " and gasRefund = ", gasRefund, " and gasRefundAmount = ", gasRefundAmount
|
|
||||||
|
|
||||||
var codeCost = 200 * c.output.len
|
var codeCost = 200 * c.output.len
|
||||||
|
|
||||||
@ -112,7 +110,7 @@ proc applyCreateTransaction*(tx: Transaction, vmState: BaseVMState, sender: EthA
|
|||||||
if not c.isSuicided(contractAddress):
|
if not c.isSuicided(contractAddress):
|
||||||
# make changes only if it not selfdestructed
|
# make changes only if it not selfdestructed
|
||||||
db.addBalance(contractAddress, tx.value)
|
db.addBalance(contractAddress, tx.value)
|
||||||
if gasRemaining >= codeCost.u256:
|
if gasRemaining >= codeCost:
|
||||||
db.setCode(contractAddress, c.output.toRange)
|
db.setCode(contractAddress, c.output.toRange)
|
||||||
else:
|
else:
|
||||||
# XXX: Homestead behaves differently; reverts state on gas failure
|
# XXX: Homestead behaves differently; reverts state on gas failure
|
||||||
@ -120,8 +118,8 @@ proc applyCreateTransaction*(tx: Transaction, vmState: BaseVMState, sender: EthA
|
|||||||
codeCost = 0
|
codeCost = 0
|
||||||
db.setCode(contractAddress, ByteRange())
|
db.setCode(contractAddress, ByteRange())
|
||||||
|
|
||||||
db.addBalance(sender, (tx.gasLimit.u256 - gasUsed - codeCost.u256 + gasRefund) * tx.gasPrice.u256)
|
db.addBalance(sender, (tx.gasLimit - gasUsed - codeCost + gasRefund).u256 * tx.gasPrice.u256)
|
||||||
return (gasUsed + codeCost.u256 - gasRefund) * tx.gasPrice.u256
|
return (gasUsed + codeCost - gasRefund)
|
||||||
else:
|
else:
|
||||||
# FIXME: don't do this revert, but rather only subBalance correctly
|
# FIXME: don't do this revert, but rather only subBalance correctly
|
||||||
# the if transactionfailed at end is what is supposed to pick it up
|
# the if transactionfailed at end is what is supposed to pick it up
|
||||||
@ -132,7 +130,7 @@ proc applyCreateTransaction*(tx: Transaction, vmState: BaseVMState, sender: EthA
|
|||||||
if c.tracingEnabled:
|
if c.tracingEnabled:
|
||||||
c.traceError()
|
c.traceError()
|
||||||
vmState.clearLogs()
|
vmState.clearLogs()
|
||||||
return tx.gasLimit.u256 * tx.gasPrice.u256
|
return tx.gasLimit
|
||||||
|
|
||||||
#[
|
#[
|
||||||
method executeTransaction(vmState: BaseVMState, transaction: Transaction): (BaseComputation, BlockHeader) {.base.}=
|
method executeTransaction(vmState: BaseVMState, transaction: Transaction): (BaseComputation, BlockHeader) {.base.}=
|
||||||
|
@ -60,7 +60,7 @@ proc testFixtureIndexes(prevStateRoot: Hash256, header: BlockHeader, pre: JsonNo
|
|||||||
#db.addBalance(generateAddress(sender, transaction.accountNonce), transaction.value)
|
#db.addBalance(generateAddress(sender, transaction.accountNonce), transaction.value)
|
||||||
|
|
||||||
let createGasUsed = applyCreateTransaction(transaction, vmState, sender, some(fork))
|
let createGasUsed = applyCreateTransaction(transaction, vmState, sender, some(fork))
|
||||||
db.addBalance(header.coinbase, createGasUsed)
|
db.addBalance(header.coinbase, createGasUsed.u256 * transaction.gasPrice.u256)
|
||||||
return
|
return
|
||||||
var computation = setupComputation(vmState, transaction, sender, some(fork))
|
var computation = setupComputation(vmState, transaction, sender, some(fork))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user