mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 21:34:33 +00:00
initial contract call/create unification
This commit is contained in:
parent
a53a543569
commit
fdf9e04108
@ -53,9 +53,9 @@ OK: 0/46 Fail: 0/46 Skip: 46/46
|
|||||||
## stAttackTest
|
## stAttackTest
|
||||||
```diff
|
```diff
|
||||||
ContractCreationSpam.json Skip
|
ContractCreationSpam.json Skip
|
||||||
CrashingTransaction.json Skip
|
+ CrashingTransaction.json OK
|
||||||
```
|
```
|
||||||
OK: 0/2 Fail: 0/2 Skip: 2/2
|
OK: 1/2 Fail: 0/2 Skip: 1/2
|
||||||
## stBadOpcode
|
## stBadOpcode
|
||||||
```diff
|
```diff
|
||||||
+ badOpcodes.json OK
|
+ badOpcodes.json OK
|
||||||
@ -2520,4 +2520,4 @@ OK: 0/133 Fail: 0/133 Skip: 133/133
|
|||||||
OK: 0/130 Fail: 0/130 Skip: 130/130
|
OK: 0/130 Fail: 0/130 Skip: 130/130
|
||||||
|
|
||||||
---TOTAL---
|
---TOTAL---
|
||||||
OK: 1179/2334 Fail: 0/2334 Skip: 1155/2334
|
OK: 1180/2334 Fail: 0/2334 Skip: 1154/2334
|
||||||
|
@ -6,55 +6,28 @@ import options,
|
|||||||
../vm/[computation, interpreter_dispatch, message],
|
../vm/[computation, interpreter_dispatch, message],
|
||||||
../vm/interpreter/vm_forks
|
../vm/interpreter/vm_forks
|
||||||
|
|
||||||
proc contractCall*(tx: Transaction, vmState: BaseVMState, sender: EthAddress, forkOverride=none(Fork)): GasInt =
|
proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, forkOverride=none(Fork)): GasInt =
|
||||||
var db = vmState.accountDb
|
|
||||||
var computation = setupComputation(vmState, tx, sender, forkOverride)
|
|
||||||
result = tx.gasLimit
|
|
||||||
|
|
||||||
if execComputation(computation):
|
|
||||||
let
|
|
||||||
gasRemaining = computation.gasMeter.gasRemaining
|
|
||||||
gasRefunded = computation.getGasRefund()
|
|
||||||
gasUsed = tx.gasLimit - gasRemaining
|
|
||||||
gasRefund = min(gasRefunded, gasUsed div 2)
|
|
||||||
gasRefundAmount = (gasRemaining + gasRefund).u256 * tx.gasPrice.u256
|
|
||||||
|
|
||||||
db.addBalance(sender, gasRefundAmount)
|
|
||||||
return (gasUsed - gasRefund)
|
|
||||||
|
|
||||||
proc processTransaction*(tx: 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
|
||||||
trace "txHash", rlpHash = tx.rlpHash
|
trace "txHash", rlpHash = tx.rlpHash
|
||||||
|
|
||||||
var db = vmState.accountDb
|
|
||||||
var transactionFailed = false
|
|
||||||
|
|
||||||
# TODO: combine/refactor re validate
|
|
||||||
let upfrontGasCost = tx.gasLimit.u256 * tx.gasPrice.u256
|
let upfrontGasCost = tx.gasLimit.u256 * tx.gasPrice.u256
|
||||||
let upfrontCost = upfrontGasCost + tx.value
|
var balance = vmState.readOnlyStateDb().getBalance(sender)
|
||||||
var balance = db.getBalance(sender)
|
if balance < upfrontGasCost:
|
||||||
if balance < upfrontCost:
|
return tx.gasLimit
|
||||||
if balance <= upfrontGasCost:
|
|
||||||
result = (balance div tx.gasPrice.u256).truncate(GasInt)
|
|
||||||
balance = 0.u256
|
|
||||||
else:
|
|
||||||
result = tx.gasLimit
|
|
||||||
balance -= upfrontGasCost
|
|
||||||
transactionFailed = true
|
|
||||||
else:
|
|
||||||
balance -= upfrontGasCost
|
|
||||||
|
|
||||||
db.incNonce(sender)
|
vmState.mutateStateDB:
|
||||||
db.setBalance(sender, balance)
|
db.incNonce(sender)
|
||||||
if transactionFailed: return
|
db.subBalance(sender, upfrontGasCost)
|
||||||
|
|
||||||
# TODO: Run the vm with proper fork
|
var computation = setupComputation(vmState, tx, sender, forkOverride)
|
||||||
if tx.isContractCreation:
|
result = tx.gasLimit
|
||||||
result = tx.contractCreate(vmState, sender)
|
|
||||||
else:
|
if execComputation(computation):
|
||||||
result = tx.contractCall(vmState, sender)
|
if tx.isContractCreation:
|
||||||
|
computation.writeContract()
|
||||||
|
result = computation.refundGas(tx, sender)
|
||||||
|
|
||||||
type
|
type
|
||||||
# TODO: these types need to be removed
|
# TODO: these types need to be removed
|
||||||
|
@ -87,39 +87,33 @@ proc execComputation*(computation: var BaseComputation): bool =
|
|||||||
snapshot.revert()
|
snapshot.revert()
|
||||||
if computation.tracingEnabled: computation.traceError()
|
if computation.tracingEnabled: computation.traceError()
|
||||||
|
|
||||||
proc contractCreate*(tx: Transaction, vmState: BaseVMState, sender: EthAddress, forkOverride=none(Fork)): GasInt =
|
proc refundGas*(computation: BaseComputation, tx: Transaction, sender: EthAddress): GasInt =
|
||||||
doAssert tx.isContractCreation
|
let
|
||||||
var c = setupComputation(vmState, tx, sender, forkOverride)
|
gasRemaining = computation.gasMeter.gasRemaining
|
||||||
result = tx.gasLimit
|
gasRefunded = computation.getGasRefund()
|
||||||
|
gasUsed = tx.gasLimit - gasRemaining
|
||||||
|
gasRefund = min(gasRefunded, gasUsed div 2)
|
||||||
|
|
||||||
if execComputation(c):
|
computation.vmState.mutateStateDB:
|
||||||
var db = vmState.accountDb
|
db.addBalance(sender, (gasRemaining + gasRefund).u256 * tx.gasPrice.u256)
|
||||||
let
|
|
||||||
gasRemaining = c.gasMeter.gasRemaining
|
|
||||||
gasRefunded = c.getGasRefund()
|
|
||||||
gasUsed = tx.gasLimit - gasRemaining
|
|
||||||
gasRefund = min(gasRefunded, gasUsed div 2)
|
|
||||||
|
|
||||||
var codeCost = c.gasCosts[Create].m_handler(0, 0, c.output.len)
|
result = gasUsed - gasRefund
|
||||||
|
|
||||||
# This apparently is not supposed to actually consume the gas, just be able to,
|
proc writeContract*(computation: var BaseComputation) =
|
||||||
# for purposes of accounting. Py-EVM apparently does consume the gas, but it is
|
let codeCost = computation.gasCosts[Create].m_handler(0, 0, computation.output.len)
|
||||||
# not matching observed blockchain balances if consumeGas is called.
|
let contractAddress = computation.msg.storageAddress
|
||||||
|
if not computation.isSuicided(contractAddress):
|
||||||
let contractAddress = c.msg.storageAddress
|
# make changes only if it not selfdestructed
|
||||||
if not c.isSuicided(contractAddress):
|
if computation.gasMeter.gasRemaining >= codeCost:
|
||||||
# make changes only if it not selfdestructed
|
computation.gasMeter.consumeGas(codeCost, reason = "Write contract code for CREATE")
|
||||||
if gasRemaining >= codeCost:
|
computation.vmState.mutateStateDB:
|
||||||
db.setCode(contractAddress, c.output.toRange)
|
db.setCode(contractAddress, computation.output.toRange)
|
||||||
else:
|
else:
|
||||||
# XXX: Homestead behaves differently; reverts state on gas failure
|
# XXX: Homestead behaves differently; reverts state on gas failure
|
||||||
# https://github.com/ethereum/py-evm/blob/master/eth/vm/forks/homestead/computation.py
|
# https://github.com/ethereum/py-evm/blob/master/eth/vm/forks/homestead/computation.py
|
||||||
codeCost = 0
|
computation.vmState.mutateStateDB:
|
||||||
db.setCode(contractAddress, ByteRange())
|
db.setCode(contractAddress, ByteRange())
|
||||||
|
|
||||||
db.addBalance(sender, (gasRemaining + gasRefund - codeCost).u256 * tx.gasPrice.u256)
|
|
||||||
return (gasUsed - gasRefund + codeCost)
|
|
||||||
|
|
||||||
#[
|
#[
|
||||||
method executeTransaction(vmState: BaseVMState, transaction: Transaction): (BaseComputation, BlockHeader) {.base.}=
|
method executeTransaction(vmState: BaseVMState, transaction: Transaction): (BaseComputation, BlockHeader) {.base.}=
|
||||||
# Execute the transaction in the vm
|
# Execute the transaction in the vm
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
# being mostly used for short-term regression prevention.
|
# being mostly used for short-term regression prevention.
|
||||||
func allowedFailingGeneralStateTest*(folder, name: string): bool =
|
func allowedFailingGeneralStateTest*(folder, name: string): bool =
|
||||||
let allowedFailingGeneralStateTests = @[
|
let allowedFailingGeneralStateTests = @[
|
||||||
"CrashingTransaction.json",
|
|
||||||
"callcallcallcode_001.json",
|
"callcallcallcode_001.json",
|
||||||
"callcallcallcode_001.json",
|
"callcallcallcode_001.json",
|
||||||
"callcallcode_01.json",
|
"callcallcode_01.json",
|
||||||
|
@ -50,14 +50,8 @@ proc testFixtureIndexes(prevStateRoot: Hash256, header: BlockHeader, pre: JsonNo
|
|||||||
db.addBalance(header.coinbase, 0.u256)
|
db.addBalance(header.coinbase, 0.u256)
|
||||||
return
|
return
|
||||||
|
|
||||||
let gasCost = tx.gasLimit.u256 * tx.gasPrice.u256
|
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
db.incNonce(sender)
|
let gasUsed = tx.processTransaction(sender, vmState, some(fork))
|
||||||
db.subBalance(sender, gasCost)
|
|
||||||
let gasUsed = if tx.isContractCreation and tx.payload.len > 0:
|
|
||||||
tx.contractCreate(vmState, sender, some(fork))
|
|
||||||
else:
|
|
||||||
tx.contractCall(vmState, sender, some(fork))
|
|
||||||
db.addBalance(header.coinbase, gasUsed.u256 * tx.gasPrice.u256)
|
db.addBalance(header.coinbase, gasUsed.u256 * tx.gasPrice.u256)
|
||||||
|
|
||||||
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user