Skip to content

Commit

Permalink
Fully switch to DEFAULT_HEADER in VM.runTx() to avoid drawing in bloc…
Browse files Browse the repository at this point in the history
…k code
  • Loading branch information
holgerd77 committed Aug 17, 2024
1 parent 6a803a1 commit 599bcca
Showing 1 changed file with 23 additions and 30 deletions.
53 changes: 23 additions & 30 deletions packages/vm/src/runTx.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cliqueSigner, createEmptyBlock } from '@ethereumjs/block'
import { cliqueSigner, createBlockHeader } from '@ethereumjs/block'
import { ConsensusType, Hardfork } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { Blob4844Tx, Capability, isBlob4844Tx } from '@ethereumjs/tx'
Expand Down Expand Up @@ -51,6 +51,8 @@ import type {
const debug = debugDefault('vm:tx')
const debugGas = debugDefault('vm:tx:gas')

const DEFAULT_HEADER = createBlockHeader()

let enableProfiler = false
const initLabel = 'EVM journal init, address/slot warming, fee validation'
const balanceNonceLabel = 'Balance/Nonce checks and update'
Expand Down Expand Up @@ -80,10 +82,7 @@ export async function runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
console.time(entireTxLabel)
}

// create a reasonable default if no block is given
opts.block = opts.block ?? createEmptyBlock({}, { common: vm.common })

if (opts.skipHardForkValidation !== true) {
if (opts.skipHardForkValidation !== true && opts.block !== undefined) {
// If block and tx don't have a same hardfork, set tx hardfork to block
if (opts.tx.common.hardfork() !== opts.block.common.hardfork()) {
opts.tx.common.setHardfork(opts.block.common.hardfork())
Expand All @@ -95,7 +94,8 @@ export async function runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
}
}

if (opts.skipBlockGasLimitValidation !== true && opts.block.header.gasLimit < opts.tx.gasLimit) {
const gasLimit = opts.block?.header.gasLimit ?? DEFAULT_HEADER.gasLimit
if (opts.skipBlockGasLimitValidation !== true && gasLimit < opts.tx.gasLimit) {
const msg = _errorMsg('tx has a higher gas limit than the block', vm, opts.block, opts.tx)
throw new Error(msg)
}
Expand Down Expand Up @@ -198,10 +198,6 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {

const { tx, block } = opts

if (!block) {
throw new Error('block required')
}

/**
* The `beforeTx` event
*
Expand Down Expand Up @@ -232,7 +228,8 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
vm.evm.journal.addAlwaysWarmAddress(bytesToUnprefixedHex(tx.to.bytes))
}
if (vm.common.isActivatedEIP(3651)) {
vm.evm.journal.addAlwaysWarmAddress(bytesToUnprefixedHex(block.header.coinbase.bytes))
const coinbase = block?.header.coinbase.bytes ?? DEFAULT_HEADER.coinbase.bytes
vm.evm.journal.addAlwaysWarmAddress(bytesToUnprefixedHex(coinbase))
}
}

Expand Down Expand Up @@ -260,7 +257,7 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
// Ensure that the user was willing to at least pay the base fee
// assert transaction.max_fee_per_gas >= block.base_fee_per_gas
const maxFeePerGas = 'maxFeePerGas' in tx ? tx.maxFeePerGas : tx.gasPrice
const baseFeePerGas = block.header.baseFeePerGas!
const baseFeePerGas = block?.header.baseFeePerGas ?? DEFAULT_HEADER.baseFeePerGas!
if (maxFeePerGas < baseFeePerGas) {
const msg = _errorMsg(
`Transaction's ${
Expand Down Expand Up @@ -296,7 +293,8 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
}

// Check balance against upfront tx cost
const upFrontCost = tx.getUpfrontCost(block.header.baseFeePerGas)
const baseFeePerGas = block?.header.baseFeePerGas ?? DEFAULT_HEADER.baseFeePerGas
const upFrontCost = tx.getUpfrontCost(baseFeePerGas)
if (balance < upFrontCost) {
if (opts.skipBalance === true && fromAccount.balance < upFrontCost) {
if (tx.supports(Capability.EIP1559FeeMarket) === false) {
Expand Down Expand Up @@ -339,16 +337,7 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
maxCost += totalblobGas * castTx.maxFeePerBlobGas

// 4844 minimum blobGas price check
if (opts.block === undefined) {
const msg = _errorMsg(
`Block option must be supplied to compute blob gas price`,
vm,
block,
tx,
)
throw new Error(msg)
}
blobGasPrice = opts.block.header.getBlobGasPrice()
blobGasPrice = opts.block?.header.getBlobGasPrice() ?? DEFAULT_HEADER.getBlobGasPrice()
if (castTx.maxFeePerBlobGas < blobGasPrice) {
const msg = _errorMsg(
`Transaction's maxFeePerBlobGas ${castTx.maxFeePerBlobGas}) is less than block blobGasPrice (${blobGasPrice}).`,
Expand Down Expand Up @@ -393,15 +382,15 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
// EIP-1559 tx
if (tx.supports(Capability.EIP1559FeeMarket)) {
// TODO make txs use the new getEffectivePriorityFee
const baseFee = block.header.baseFeePerGas!
const baseFee = block?.header.baseFeePerGas ?? DEFAULT_HEADER.baseFeePerGas!
inclusionFeePerGas = tx.getEffectivePriorityFee(baseFee)

gasPrice = inclusionFeePerGas + baseFee
} else {
// Have to cast as legacy tx since EIP1559 tx does not have gas price
gasPrice = (<LegacyTx>tx).gasPrice
if (vm.common.isActivatedEIP(1559)) {
const baseFee = block.header.baseFeePerGas!
const baseFee = block?.header.baseFeePerGas ?? DEFAULT_HEADER.baseFeePerGas!
inclusionFeePerGas = (<LegacyTx>tx).gasPrice - baseFee
}
}
Expand Down Expand Up @@ -588,9 +577,9 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
// Update miner's balance
let miner
if (vm.common.consensusType() === ConsensusType.ProofOfAuthority) {
miner = cliqueSigner(block.header)
miner = cliqueSigner(block?.header ?? DEFAULT_HEADER)
} else {
miner = block.header.coinbase
miner = block?.header.coinbase ?? DEFAULT_HEADER.coinbase
}

let minerAccount = await state.getAccount(miner)
Expand Down Expand Up @@ -702,7 +691,10 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise<RunTxResult> {
}

// Generate the tx receipt
const gasUsed = opts.blockGasUsed !== undefined ? opts.blockGasUsed : block.header.gasUsed
const gasUsed =
opts.blockGasUsed !== undefined
? opts.blockGasUsed
: (block?.header.gasUsed ?? DEFAULT_HEADER.gasUsed)
const cumulativeGasUsed = gasUsed + results.totalGasSpent
results.receipt = await generateTxReceipt(
vm,
Expand Down Expand Up @@ -834,8 +826,9 @@ export async function generateTxReceipt(
* @param msg Base error message
* @hidden
*/
function _errorMsg(msg: string, vm: VM, block: Block, tx: TypedTransaction) {
const blockErrorStr = 'errorStr' in block ? block.errorStr() : 'block'
function _errorMsg(msg: string, vm: VM, block: Block | undefined, tx: TypedTransaction) {
const blockOrHeader = block ?? DEFAULT_HEADER
const blockErrorStr = 'errorStr' in blockOrHeader ? blockOrHeader.errorStr() : 'block'
const txErrorStr = 'errorStr' in tx ? tx.errorStr() : 'tx'

const errorMsg = `${msg} (${vm.errorStr()} -> ${blockErrorStr} -> ${txErrorStr})`
Expand Down

0 comments on commit 599bcca

Please sign in to comment.