nimbus-eth1/nimbus/p2p/executor/process_transaction.nim
Jordan Hrycaj fbff3aea68
Feature/goerli replay clique poa (#743)
* extract unused clique/mining support into separate file

why:
  mining is currently unsupported by nimbus

* Replay first 51840 transactions from Goerli block chain

why:
  Currently Goerli is loaded but the block headers are not verified.
  Replaying allows real data PoA development.

details:
  Simple stupid gzipped dump/undump layer for debugging based on
  the zlib module (no nim-faststream support.)

  This is a replay running against p2p/chain.persistBlocks() where
  the data were captured from.

* prepare stubs for PoA engine

* split executor source into sup-modules

why:
  make room for updates, clique integration should go into
  executor/update_poastate.nim

* Simplify p2p/executor.processBlock() function prototype

why:
  vmState argument always wraps basicChainDB

* split processBlock() into sub-functions

why:
  isolate the part where it will support clique/poa

* provided additional processTransaction() function prototype without _fork_ argument

why:
  with the exception of some tests, the _fork_ argument is always derived
  from the other prototype argument _vmState_

details:
  similar situation with makeReceipt()

* provide new processBlock() version explicitly supporting PoA

details:
  The new processBlock() version supporting PoA is the general one also
  supporting non-PoA networks, it needs an additional _Clique_ descriptor
  function argument for PoA state (if any.)
  The old processBlock() function without the _Clique_ descriptor argument
  retorns an error on PoA networgs (e.g. Goerli.)

* re-implemented Clique descriptor as _ref object_

why:
  gives more flexibility when moving around the descriptor object

details:
  also cleaned up a bit the clique sources

* comments for clarifying handling of Clique/PoA state descriptor
2021-07-06 14:14:45 +01:00

85 lines
2.7 KiB
Nim

# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
import
std/[sets],
../../db/accounts_cache,
../../forks,
../../transaction/call_evm,
../../vm_state,
../../vm_types,
../validate,
./executor_helpers,
chronicles,
eth/common
proc eip1559TxNormalization(tx: Transaction): Transaction =
result = tx
if tx.txType < TxEip1559:
result.maxPriorityFee = tx.gasPrice
result.maxFee = tx.gasPrice
proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: Fork): GasInt =
## Process the transaction, write the results to db.
## Returns amount of ETH to be rewarded to miner
trace "Sender", sender
trace "txHash", rlpHash = tx.rlpHash
var tx = eip1559TxNormalization(tx)
var priorityFee: GasInt
if fork >= FkLondon:
# priority fee is capped because the base fee is filled first
let baseFee = vmState.blockHeader.baseFee.truncate(GasInt)
priorityFee = min(tx.maxPriorityFee, tx.maxFee - baseFee)
# signer pays both the priority fee and the base fee
# tx.gasPrice now is the effective gasPrice
tx.gasPrice = priorityFee + baseFee
let miner = vmState.coinbase()
if validateTransaction(vmState, tx, sender, fork):
result = txCallEvm(tx, sender, vmState, fork)
# miner fee
if fork >= FkLondon:
# miner only receives the priority fee;
# note that the base fee is not given to anyone (it is burned)
let txFee = result.u256 * priorityFee.u256
vmState.accountDb.addBalance(miner, txFee)
else:
let txFee = result.u256 * tx.gasPrice.u256
vmState.accountDb.addBalance(miner, txFee)
vmState.cumulativeGasUsed += result
vmState.mutateStateDB:
for deletedAccount in vmState.selfDestructs:
db.deleteAccount deletedAccount
if fork >= FkSpurious:
vmState.touchedAccounts.incl(miner)
# EIP158/161 state clearing
for account in vmState.touchedAccounts:
if db.accountExists(account) and db.isEmptyAccount(account):
debug "state clearing", account
db.deleteAccount(account)
if vmState.generateWitness:
vmState.accountDb.collectWitnessData()
vmState.accountDb.persist(clearCache = false)
proc processTransaction*(tx: Transaction,
sender: EthAddress, vmState: BaseVMState): GasInt =
tx.processTransaction(sender, vmState, vmState.getFork)
# End