Integrate PoS payload attributes into txPool (#2998)

* Integrate PoS payload attributes into txPool

* Fix test_txpool
This commit is contained in:
andri lim 2025-01-14 20:30:56 +07:00 committed by GitHub
parent 6e83a48969
commit 288ee28077
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 162 additions and 154 deletions

View File

@ -1,5 +1,5 @@
# Nimbus # Nimbus
# Copyright (c) 2023-2024 Status Research & Development GmbH # Copyright (c) 2023-2025 Status Research & Development GmbH
# Licensed under either of # Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT)) # * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -16,7 +16,7 @@ import
./payload_conv, ./payload_conv,
./payload_queue, ./payload_queue,
./api_handler/api_utils, ./api_handler/api_utils,
../core/[tx_pool, casper, chain] ../core/[tx_pool, chain]
export export
chain, chain,
@ -68,12 +68,12 @@ const
# Private helpers # Private helpers
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
func setWithdrawals(ctx: CasperRef, attrs: PayloadAttributes) = func setWithdrawals(xp: TxPoolRef, attrs: PayloadAttributes) =
case attrs.version case attrs.version
of Version.V2, Version.V3: of Version.V2, Version.V3:
ctx.withdrawals = ethWithdrawals attrs.withdrawals.get xp.withdrawals = ethWithdrawals attrs.withdrawals.get
else: else:
ctx.withdrawals = @[] xp.withdrawals = @[]
template wrapException(body: untyped): auto = template wrapException(body: untyped): auto =
try: try:
@ -146,19 +146,18 @@ proc generateExecutionBundle*(ben: BeaconEngineRef,
wrapException: wrapException:
let let
xp = ben.txPool xp = ben.txPool
pos = xp.com.pos
headBlock = ben.chain.latestHeader headBlock = ben.chain.latestHeader
pos.prevRandao = attrs.prevRandao xp.prevRandao = attrs.prevRandao
pos.timestamp = ethTime attrs.timestamp xp.timestamp = ethTime attrs.timestamp
pos.feeRecipient = attrs.suggestedFeeRecipient xp.feeRecipient = attrs.suggestedFeeRecipient
if attrs.parentBeaconBlockRoot.isSome: if attrs.parentBeaconBlockRoot.isSome:
pos.parentBeaconBlockRoot = attrs.parentBeaconBlockRoot.get xp.parentBeaconBlockRoot = attrs.parentBeaconBlockRoot.get
pos.setWithdrawals(attrs) xp.setWithdrawals(attrs)
if pos.timestamp <= headBlock.timestamp: if xp.timestamp <= headBlock.timestamp:
return err "timestamp must be strictly later than parent" return err "timestamp must be strictly later than parent"
# someBaseFee = true: make sure bundle.blk.header # someBaseFee = true: make sure bundle.blk.header

View File

@ -1,5 +1,5 @@
# Nimbus # Nimbus
# Copyright (c) 2022-2024 Status Research & Development GmbH # Copyright (c) 2022-2025 Status Research & Development GmbH
# Licensed under either of # Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT)) # * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -11,7 +11,6 @@
import import
chronicles, chronicles,
../core/casper,
../db/[core_db, ledger, storage_types], ../db/[core_db, ledger, storage_types],
../utils/[utils], ../utils/[utils],
".."/[constants, errors, version], ".."/[constants, errors, version],
@ -90,9 +89,6 @@ type
## installing a snapshot pivot. The default value for this field is ## installing a snapshot pivot. The default value for this field is
## `GENESIS_PARENT_HASH` to start at the very beginning. ## `GENESIS_PARENT_HASH` to start at the very beginning.
pos: CasperRef
## Proof Of Stake descriptor
pruneHistory: bool pruneHistory: bool
## Must not not set for a full node, might go away some time ## Must not not set for a full node, might go away some time
@ -181,7 +177,6 @@ proc init(com : CommonRef,
com.syncProgress= SyncProgress() com.syncProgress= SyncProgress()
com.syncState = Waiting com.syncState = Waiting
com.pruneHistory= pruneHistory com.pruneHistory= pruneHistory
com.pos = CasperRef.new
com.extraData = ShortClientId com.extraData = ShortClientId
com.taskpool = taskpool com.taskpool = taskpool
com.gasLimit = DEFAULT_GAS_LIMIT com.gasLimit = DEFAULT_GAS_LIMIT
@ -202,7 +197,6 @@ proc init(com : CommonRef,
toGenesisHeader(genesis, fork, com.db) toGenesisHeader(genesis, fork, com.db)
com.setForkId(com.genesisHeader) com.setForkId(com.genesisHeader)
com.pos.timestamp = genesis.timestamp
# By default, history begins at genesis. # By default, history begins at genesis.
com.startOfHistory = GENESIS_PARENT_HASH com.startOfHistory = GENESIS_PARENT_HASH
@ -276,7 +270,6 @@ func clone*(com: CommonRef, db: CoreDbRef): CommonRef =
genesisHeader: com.genesisHeader, genesisHeader: com.genesisHeader,
syncProgress : com.syncProgress, syncProgress : com.syncProgress,
networkId : com.networkId, networkId : com.networkId,
pos : com.pos,
pruneHistory : com.pruneHistory) pruneHistory : com.pruneHistory)
func clone*(com: CommonRef): CommonRef = func clone*(com: CommonRef): CommonRef =
@ -363,10 +356,6 @@ func startOfHistory*(com: CommonRef): Hash32 =
## Getter ## Getter
com.startOfHistory com.startOfHistory
func pos*(com: CommonRef): CasperRef =
## Getter
com.pos
func db*(com: CommonRef): CoreDbRef = func db*(com: CommonRef): CoreDbRef =
com.db com.db

View File

@ -1,56 +0,0 @@
# Nimbus
# Copyright (c) 2022-2024 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.
import
eth/common/blocks
type
CasperRef* = ref object
feeRecipient: Address
timestamp : EthTime
prevRandao : Bytes32
withdrawals : seq[Withdrawal] ## EIP-4895
beaconRoot : Hash32 ## EIP-4788
# ------------------------------------------------------------------------------
# Getters
# ------------------------------------------------------------------------------
func feeRecipient*(ctx: CasperRef): Address =
ctx.feeRecipient
func timestamp*(ctx: CasperRef): EthTime =
ctx.timestamp
func prevRandao*(ctx: CasperRef): Bytes32 =
ctx.prevRandao
proc withdrawals*(ctx: CasperRef): seq[Withdrawal] =
ctx.withdrawals
func parentBeaconBlockRoot*(ctx: CasperRef): Hash32 =
ctx.beaconRoot
# ------------------------------------------------------------------------------
# Setters
# ------------------------------------------------------------------------------
proc `feeRecipient=`*(ctx: CasperRef, val: Address) =
ctx.feeRecipient = val
proc `timestamp=`*(ctx: CasperRef, val: EthTime) =
ctx.timestamp = val
proc `prevRandao=`*(ctx: CasperRef, val: Bytes32) =
ctx.prevRandao = val
proc `withdrawals=`*(ctx: CasperRef, val: sink seq[Withdrawal]) =
ctx.withdrawals = system.move(val)
proc `parentBeaconBlockRoot=`*(ctx: CasperRef, val: Hash32) =
ctx.beaconRoot = val

View File

@ -1,5 +1,5 @@
# Nimbus # Nimbus
# Copyright (c) 2018-2024 Status Research & Development GmbH # Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed under either of # Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0) # http://www.apache.org/licenses/LICENSE-2.0)
@ -42,8 +42,7 @@ import
./tx_pool/tx_item, ./tx_pool/tx_item,
./tx_pool/tx_desc, ./tx_pool/tx_desc,
./tx_pool/tx_packer, ./tx_pool/tx_packer,
./chain/forked_chain, ./chain/forked_chain
./casper
from eth/common/eth_types_rlp import rlpHash from eth/common/eth_types_rlp import rlpHash
@ -143,7 +142,7 @@ proc assembleBlock*(
return err(error) return err(error)
var blk = EthBlock( var blk = EthBlock(
header: pst.assembleHeader header: pst.assembleHeader(xp)
) )
var blobsBundle: BlobsBundle var blobsBundle: BlobsBundle
for item in pst.packedTxs: for item in pst.packedTxs:
@ -160,7 +159,7 @@ proc assembleBlock*(
let com = xp.vmState.com let com = xp.vmState.com
if com.isShanghaiOrLater(blk.header.timestamp): if com.isShanghaiOrLater(blk.header.timestamp):
blk.withdrawals = Opt.some(com.pos.withdrawals) blk.withdrawals = Opt.some(xp.withdrawals)
if not com.isCancunOrLater(blk.header.timestamp) and blobsBundle.commitments.len > 0: if not com.isCancunOrLater(blk.header.timestamp) and blobsBundle.commitments.len > 0:
return err("PooledTransaction contains blobs prior to Cancun") return err("PooledTransaction contains blobs prior to Cancun")
@ -187,3 +186,37 @@ proc assembleBlock*(
blobsBundle: blobsBundleOpt, blobsBundle: blobsBundleOpt,
blockValue: pst.blockValue, blockValue: pst.blockValue,
executionRequests: executionRequestsOpt) executionRequests: executionRequestsOpt)
# ------------------------------------------------------------------------------
# PoS payload attributes getters
# ------------------------------------------------------------------------------
export
feeRecipient,
timestamp,
prevRandao,
withdrawals,
parentBeaconBlockRoot
# feeRecipient(xp: TxPoolRef): Address
# timestamp(xp: TxPoolRef): EthTime
# prevRandao(xp: TxPoolRef): Bytes32
# withdrawals(xp: TxPoolRef): seq[Withdrawal]
# parentBeaconBlockRoot(xp: TxPoolRef): Hash32
# ------------------------------------------------------------------------------
# PoS payload attributes setters
# ------------------------------------------------------------------------------
export
`feeRecipient=`,
`timestamp=`,
`prevRandao=`,
`withdrawals=`,
`parentBeaconBlockRoot=`
# `feeRecipient=`(xp: TxPoolRef, val: Address)
# `timestamp=`(xp: TxPoolRef, val: EthTime)
# `prevRandao=`(xp: TxPoolRef, val: Bytes32)
# `withdrawals=`(xp: TxPoolRef, val: sink seq[Withdrawal])
# `parentBeaconBlockRoot=`(xp: TxPoolRef, val: Hash32)

View File

@ -25,7 +25,6 @@ import
../chain/forked_chain, ../chain/forked_chain,
../pow/header, ../pow/header,
../eip4844, ../eip4844,
../casper,
../validate, ../validate,
./tx_tabs, ./tx_tabs,
./tx_item ./tx_item
@ -36,12 +35,20 @@ logScope:
topics = "txpool" topics = "txpool"
type type
PosPayloadAttr = object
feeRecipient: Address
timestamp : EthTime
prevRandao : Bytes32
withdrawals : seq[Withdrawal] ## EIP-4895
beaconRoot : Hash32 ## EIP-4788
TxPoolRef* = ref object TxPoolRef* = ref object
vmState : BaseVMState vmState : BaseVMState
chain : ForkedChainRef chain : ForkedChainRef
senderTab: TxSenderTab senderTab: TxSenderTab
idTab : TxIdTab idTab : TxIdTab
rmHash : Hash32 rmHash : Hash32
pos : PosPayloadAttr
const const
MAX_POOL_SIZE = 5000 MAX_POOL_SIZE = 5000
@ -65,9 +72,11 @@ func getGasLimit(com: CommonRef; parent: Header): GasInt =
## Post Merge rule ## Post Merge rule
calcGasLimit1559(parent.gasLimit, desiredLimit = com.gasLimit) calcGasLimit1559(parent.gasLimit, desiredLimit = com.gasLimit)
proc setupVMState(com: CommonRef; parent: Header, parentHash: Hash32): BaseVMState = proc setupVMState(com: CommonRef;
parent: Header,
parentHash: Hash32,
pos: PosPayloadAttr): BaseVMState =
let let
pos = com.pos
electra = com.isPragueOrLater(pos.timestamp) electra = com.isPragueOrLater(pos.timestamp)
BaseVMState.new( BaseVMState.new(
@ -158,8 +167,8 @@ proc classifyValid(xp: TxPoolRef; tx: Transaction, sender: Address): bool =
return false return false
if tx.gasLimit > xp.gasLimit: if tx.gasLimit > xp.gasLimit:
debug "Invalid transaction: Gas limit too high", debug "Invalid transaction: Gas limit too high",
txGasLimit = tx.gasLimit, txGasLimit = tx.gasLimit,
gasLimit = xp.gasLimit gasLimit = xp.gasLimit
return false return false
@ -167,8 +176,8 @@ proc classifyValid(xp: TxPoolRef; tx: Transaction, sender: Address): bool =
# And to at least pay the current data gasprice # And to at least pay the current data gasprice
if tx.txType >= TxEip1559: if tx.txType >= TxEip1559:
if tx.maxFeePerGas < xp.baseFee: if tx.maxFeePerGas < xp.baseFee:
debug "Invalid transaction: maxFeePerGas lower than baseFee", debug "Invalid transaction: maxFeePerGas lower than baseFee",
maxFeePerGas = tx.maxFeePerGas, maxFeePerGas = tx.maxFeePerGas,
baseFee = xp.baseFee baseFee = xp.baseFee
return false return false
@ -178,8 +187,8 @@ proc classifyValid(xp: TxPoolRef; tx: Transaction, sender: Address): bool =
electra = xp.vmState.fork >= FkPrague electra = xp.vmState.fork >= FkPrague
blobGasPrice = getBlobBaseFee(excessBlobGas, electra) blobGasPrice = getBlobBaseFee(excessBlobGas, electra)
if tx.maxFeePerBlobGas < blobGasPrice: if tx.maxFeePerBlobGas < blobGasPrice:
debug "Invalid transaction: maxFeePerBlobGas lower than blobGasPrice", debug "Invalid transaction: maxFeePerBlobGas lower than blobGasPrice",
maxFeePerBlobGas = tx.maxFeePerBlobGas, maxFeePerBlobGas = tx.maxFeePerBlobGas,
blobGasPrice = blobGasPrice blobGasPrice = blobGasPrice
return false return false
@ -188,14 +197,14 @@ proc classifyValid(xp: TxPoolRef; tx: Transaction, sender: Address): bool =
balance = xp.getBalance(sender) balance = xp.getBalance(sender)
gasCost = tx.gasCost gasCost = tx.gasCost
if balance < gasCost: if balance < gasCost:
debug "Invalid transaction: Insufficient balance for gas cost", debug "Invalid transaction: Insufficient balance for gas cost",
balance = balance, balance = balance,
gasCost = gasCost gasCost = gasCost
return false return false
let balanceOffGasCost = balance - gasCost let balanceOffGasCost = balance - gasCost
if balanceOffGasCost < tx.value: if balanceOffGasCost < tx.value:
debug "Invalid transaction: Insufficient balance for tx value", debug "Invalid transaction: Insufficient balance for tx value",
balanceOffGasCost = balanceOffGasCost, balanceOffGasCost = balanceOffGasCost,
txValue = tx.value txValue = tx.value
return false return false
@ -203,7 +212,7 @@ proc classifyValid(xp: TxPoolRef; tx: Transaction, sender: Address): bool =
# high enough. These checks are optional. # high enough. These checks are optional.
if tx.txType < TxEip1559: if tx.txType < TxEip1559:
if tx.gasPrice < 0: if tx.gasPrice < 0:
debug "Invalid transaction: Legacy transaction with invalid gas price", debug "Invalid transaction: Legacy transaction with invalid gas price",
gasPrice = tx.gasPrice gasPrice = tx.gasPrice
return false return false
@ -220,12 +229,12 @@ proc classifyValid(xp: TxPoolRef; tx: Transaction, sender: Address): bool =
if tx.maxFeePerGas < 1.GasInt: if tx.maxFeePerGas < 1.GasInt:
debug "Invalid transaction: EIP-1559 transaction with maxFeePerGas lower than 1" debug "Invalid transaction: EIP-1559 transaction with maxFeePerGas lower than 1"
return false return false
debug "Valid transaction", debug "Valid transaction",
txType = tx.txType, txType = tx.txType,
sender = sender, sender = sender,
gasLimit = tx.gasLimit, gasLimit = tx.gasLimit,
gasPrice = tx.gasPrice, gasPrice = tx.gasPrice,
value = tx.value value = tx.value
true true
@ -235,8 +244,9 @@ proc classifyValid(xp: TxPoolRef; tx: Transaction, sender: Address): bool =
proc init*(xp: TxPoolRef; chain: ForkedChainRef) = proc init*(xp: TxPoolRef; chain: ForkedChainRef) =
## Constructor, returns new tx-pool descriptor. ## Constructor, returns new tx-pool descriptor.
xp.pos.timestamp = chain.latestHeader.timestamp
xp.vmState = setupVMState(chain.com, xp.vmState = setupVMState(chain.com,
chain.latestHeader, chain.latestHash) chain.latestHeader, chain.latestHash, xp.pos)
xp.chain = chain xp.chain = chain
xp.rmHash = chain.latestHash xp.rmHash = chain.latestHash
@ -272,7 +282,7 @@ func `rmHash=`*(xp: TxPoolRef, val: Hash32) =
proc updateVmState*(xp: TxPoolRef) = proc updateVmState*(xp: TxPoolRef) =
## Reset transaction environment, e.g. before packing a new block ## Reset transaction environment, e.g. before packing a new block
xp.vmState = setupVMState(xp.chain.com, xp.vmState = setupVMState(xp.chain.com,
xp.chain.latestHeader, xp.chain.latestHash) xp.chain.latestHeader, xp.chain.latestHash, xp.pos)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public functions # Public functions
@ -303,16 +313,16 @@ proc removeExpiredTxs*(xp: TxPoolRef, lifeTime: Duration = TX_ITEM_LIFETIME) =
proc addTx*(xp: TxPoolRef, ptx: PooledTransaction): Result[void, TxError] = proc addTx*(xp: TxPoolRef, ptx: PooledTransaction): Result[void, TxError] =
if not ptx.tx.validateChainId(xp.chain.com.chainId): if not ptx.tx.validateChainId(xp.chain.com.chainId):
debug "Transaction chain id mismatch", debug "Transaction chain id mismatch",
txChainId = ptx.tx.chainId, txChainId = ptx.tx.chainId,
chainId = xp.chain.com.chainId chainId = xp.chain.com.chainId
return err(txErrorChainIdMismatch) return err(txErrorChainIdMismatch)
let id = ptx.rlpHash let id = ptx.rlpHash
if ptx.tx.txType == TxEip4844: if ptx.tx.txType == TxEip4844:
ptx.validateBlobTransactionWrapper().isOkOr: ptx.validateBlobTransactionWrapper().isOkOr:
debug "Invalid transaction: Blob transaction wrapper validation failed", debug "Invalid transaction: Blob transaction wrapper validation failed",
tx = ptx.tx, tx = ptx.tx,
error = error error = error
return err(txErrorInvalidBlob) return err(txErrorInvalidBlob)
@ -325,7 +335,7 @@ proc addTx*(xp: TxPoolRef, ptx: PooledTransaction): Result[void, TxError] =
ptx.tx, ptx.tx,
xp.nextFork, xp.nextFork,
validateFork = true).isOkOr: validateFork = true).isOkOr:
debug "Invalid transaction: Basic validation failed", debug "Invalid transaction: Basic validation failed",
txHash = id, txHash = id,
error = error error = error
return err(txErrorBasicValidation) return err(txErrorBasicValidation)
@ -349,8 +359,8 @@ proc addTx*(xp: TxPoolRef, ptx: PooledTransaction): Result[void, TxError] =
# xp.updateVmState() # xp.updateVmState()
# maybe can solve the accuracy but it is quite expensive. # maybe can solve the accuracy but it is quite expensive.
if ptx.tx.nonce < nonce: if ptx.tx.nonce < nonce:
debug "Transaction rejected: Nonce too small", debug "Transaction rejected: Nonce too small",
txNonce = ptx.tx.nonce, txNonce = ptx.tx.nonce,
nonce = nonce, nonce = nonce,
sender = sender sender = sender
return err(txErrorNonceTooSmall) return err(txErrorNonceTooSmall)
@ -369,7 +379,7 @@ proc addTx*(xp: TxPoolRef, ptx: PooledTransaction): Result[void, TxError] =
?xp.insertToSenderTab(item) ?xp.insertToSenderTab(item)
xp.idTab[item.id] = item xp.idTab[item.id] = item
debug "Transaction added to txpool", debug "Transaction added to txpool",
txHash = id, txHash = id,
sender = sender, sender = sender,
recipient = ptx.tx.getRecipient(sender), recipient = ptx.tx.getRecipient(sender),
@ -386,3 +396,41 @@ iterator byPriceAndNonce*(xp: TxPoolRef): TxItemRef =
for item in byPriceAndNonce(xp.senderTab, xp.idTab, for item in byPriceAndNonce(xp.senderTab, xp.idTab,
xp.vmState.ledger, xp.baseFee): xp.vmState.ledger, xp.baseFee):
yield item yield item
# ------------------------------------------------------------------------------
# PoS payload attributes getters
# ------------------------------------------------------------------------------
func feeRecipient*(xp: TxPoolRef): Address =
xp.pos.feeRecipient
func timestamp*(xp: TxPoolRef): EthTime =
xp.pos.timestamp
func prevRandao*(xp: TxPoolRef): Bytes32 =
xp.pos.prevRandao
proc withdrawals*(xp: TxPoolRef): seq[Withdrawal] =
xp.pos.withdrawals
func parentBeaconBlockRoot*(xp: TxPoolRef): Hash32 =
xp.pos.beaconRoot
# ------------------------------------------------------------------------------
# PoS payload attributes setters
# ------------------------------------------------------------------------------
proc `feeRecipient=`*(xp: TxPoolRef, val: Address) =
xp.pos.feeRecipient = val
proc `timestamp=`*(xp: TxPoolRef, val: EthTime) =
xp.pos.timestamp = val
proc `prevRandao=`*(xp: TxPoolRef, val: Bytes32) =
xp.pos.prevRandao = val
proc `withdrawals=`*(xp: TxPoolRef, val: sink seq[Withdrawal]) =
xp.pos.withdrawals = system.move(val)
proc `parentBeaconBlockRoot=`*(xp: TxPoolRef, val: Hash32) =
xp.pos.beaconRoot = val

View File

@ -1,5 +1,5 @@
# Nimbus # Nimbus
# Copyright (c) 2018-2024 Status Research & Development GmbH # Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed under either of # Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0) # http://www.apache.org/licenses/LICENSE-2.0)
@ -27,7 +27,6 @@ import
../../evm/types, ../../evm/types,
../executor, ../executor,
../validate, ../validate,
../casper,
../eip4844, ../eip4844,
../eip6110, ../eip6110,
../eip7691, ../eip7691,
@ -101,9 +100,6 @@ func baseFee(pst: TxPacker): GasInt =
else: else:
0.GasInt 0.GasInt
func feeRecipient(pst: TxPacker): Address =
pst.vmState.com.pos.feeRecipient
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Private functions # Private functions
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -115,7 +111,7 @@ proc runTx(pst: var TxPacker; item: TxItemRef): GasInt =
doAssert 0 <= gasUsed doAssert 0 <= gasUsed
gasUsed gasUsed
proc runTxCommit(pst: var TxPacker; item: TxItemRef; gasBurned: GasInt) = proc runTxCommit(pst: var TxPacker; item: TxItemRef; gasBurned: GasInt, xp: TxPoolRef) =
## Book keeping after executing argument `item` transaction in the VM. The ## Book keeping after executing argument `item` transaction in the VM. The
## function returns the next number of items `nItems+1`. ## function returns the next number of items `nItems+1`.
let let
@ -124,7 +120,7 @@ proc runTxCommit(pst: var TxPacker; item: TxItemRef; gasBurned: GasInt) =
gasTip = item.tx.tip(pst.baseFee) gasTip = item.tx.tip(pst.baseFee)
let reward = gasBurned.u256 * gasTip.u256 let reward = gasBurned.u256 * gasTip.u256
vmState.ledger.addBalance(pst.feeRecipient, reward) vmState.ledger.addBalance(xp.feeRecipient, reward)
pst.blockValue += reward pst.blockValue += reward
# Update receipts sequence # Update receipts sequence
@ -154,7 +150,7 @@ proc vmExecInit(xp: TxPoolRef): Result[TxPacker, string] =
# EIP-4788 # EIP-4788
if xp.nextFork >= FkCancun: if xp.nextFork >= FkCancun:
let beaconRoot = xp.vmState.com.pos.parentBeaconBlockRoot let beaconRoot = xp.parentBeaconBlockRoot
xp.vmState.processBeaconBlockRoot(beaconRoot).isOkOr: xp.vmState.processBeaconBlockRoot(beaconRoot).isOkOr:
return err(error) return err(error)
@ -165,7 +161,7 @@ proc vmExecInit(xp: TxPoolRef): Result[TxPacker, string] =
ok(packer) ok(packer)
proc vmExecGrabItem(pst: var TxPacker; item: TxItemRef): bool = proc vmExecGrabItem(pst: var TxPacker; item: TxItemRef, xp: TxPoolRef): bool =
## Greedily collect & compact items as long as the accumulated `gasLimit` ## Greedily collect & compact items as long as the accumulated `gasLimit`
## values are below the maximum block size. ## values are below the maximum block size.
let let
@ -215,7 +211,7 @@ proc vmExecGrabItem(pst: var TxPacker; item: TxItemRef): bool =
vmState.ledger.persist(clearEmptyAccount = vmState.fork >= FkSpurious) vmState.ledger.persist(clearEmptyAccount = vmState.fork >= FkSpurious)
# Finish book-keeping # Finish book-keeping
pst.runTxCommit(item, gasUsed) pst.runTxCommit(item, gasUsed, xp)
pst.numBlobPerBlock += item.tx.versionedHashes.len pst.numBlobPerBlock += item.tx.versionedHashes.len
vmState.blobGasUsed += blobGasUsed vmState.blobGasUsed += blobGasUsed
@ -223,14 +219,14 @@ proc vmExecGrabItem(pst: var TxPacker; item: TxItemRef): bool =
ContinueWithNextAccount ContinueWithNextAccount
proc vmExecCommit(pst: var TxPacker): Result[void, string] = proc vmExecCommit(pst: var TxPacker, xp: TxPoolRef): Result[void, string] =
let let
vmState = pst.vmState vmState = pst.vmState
ledger = vmState.ledger ledger = vmState.ledger
# EIP-4895 # EIP-4895
if vmState.fork >= FkShanghai: if vmState.fork >= FkShanghai:
for withdrawal in vmState.com.pos.withdrawals: for withdrawal in xp.withdrawals:
ledger.addBalance(withdrawal.address, withdrawal.weiAmount) ledger.addBalance(withdrawal.address, withdrawal.weiAmount)
# EIP-6110, EIP-7002, EIP-7251 # EIP-6110, EIP-7002, EIP-7251
@ -264,11 +260,11 @@ proc packerVmExec*(xp: TxPoolRef): Result[TxPacker, string] =
return err(error) return err(error)
for item in xp.byPriceAndNonce: for item in xp.byPriceAndNonce:
let rc = pst.vmExecGrabItem(item) let rc = pst.vmExecGrabItem(item, xp)
if rc == StopCollecting: if rc == StopCollecting:
break break
?pst.vmExecCommit() ?pst.vmExecCommit(xp)
ok(pst) ok(pst)
func getExtraData(com: CommonRef): seq[byte] = func getExtraData(com: CommonRef): seq[byte] =
@ -277,17 +273,16 @@ func getExtraData(com: CommonRef): seq[byte] =
else: else:
com.extraData.toBytes com.extraData.toBytes
proc assembleHeader*(pst: TxPacker): Header = proc assembleHeader*(pst: TxPacker, xp: TxPoolRef): Header =
## Generate a new header, a child of the cached `head` ## Generate a new header, a child of the cached `head`
let let
vmState = pst.vmState vmState = pst.vmState
com = vmState.com com = vmState.com
pos = com.pos
result = Header( result = Header(
parentHash: vmState.blockCtx.parentHash, parentHash: vmState.blockCtx.parentHash,
ommersHash: EMPTY_UNCLE_HASH, ommersHash: EMPTY_UNCLE_HASH,
coinbase: pos.feeRecipient, coinbase: xp.feeRecipient,
stateRoot: pst.stateRoot, stateRoot: pst.stateRoot,
receiptsRoot: pst.receiptsRoot, receiptsRoot: pst.receiptsRoot,
logsBloom: pst.logsBloom, logsBloom: pst.logsBloom,
@ -295,22 +290,22 @@ proc assembleHeader*(pst: TxPacker): Header =
number: vmState.blockNumber, number: vmState.blockNumber,
gasLimit: vmState.blockCtx.gasLimit, gasLimit: vmState.blockCtx.gasLimit,
gasUsed: vmState.cumulativeGasUsed, gasUsed: vmState.cumulativeGasUsed,
timestamp: pos.timestamp, timestamp: xp.timestamp,
extraData: getExtraData(com), extraData: getExtraData(com),
mixHash: pos.prevRandao, mixHash: xp.prevRandao,
nonce: default(Bytes8), nonce: default(Bytes8),
baseFeePerGas: vmState.blockCtx.baseFeePerGas, baseFeePerGas: vmState.blockCtx.baseFeePerGas,
) )
if com.isShanghaiOrLater(pos.timestamp): if com.isShanghaiOrLater(xp.timestamp):
result.withdrawalsRoot = Opt.some(calcWithdrawalsRoot(pos.withdrawals)) result.withdrawalsRoot = Opt.some(calcWithdrawalsRoot(xp.withdrawals))
if com.isCancunOrLater(pos.timestamp): if com.isCancunOrLater(xp.timestamp):
result.parentBeaconBlockRoot = Opt.some(pos.parentBeaconBlockRoot) result.parentBeaconBlockRoot = Opt.some(xp.parentBeaconBlockRoot)
result.blobGasUsed = Opt.some vmState.blobGasUsed result.blobGasUsed = Opt.some vmState.blobGasUsed
result.excessBlobGas = Opt.some vmState.blockCtx.excessBlobGas result.excessBlobGas = Opt.some vmState.blockCtx.excessBlobGas
if com.isPragueOrLater(pos.timestamp): if com.isPragueOrLater(xp.timestamp):
let requestsHash = calcRequestsHash([ let requestsHash = calcRequestsHash([
(DEPOSIT_REQUEST_TYPE, pst.depositReqs), (DEPOSIT_REQUEST_TYPE, pst.depositReqs),
(WITHDRAWAL_REQUEST_TYPE, pst.withdrawalReqs), (WITHDRAWAL_REQUEST_TYPE, pst.withdrawalReqs),

View File

@ -1,5 +1,5 @@
# Nimbus # Nimbus
# Copyright (c) 2018-2024 Status Research & Development GmbH # Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed under either of # Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0) # http://www.apache.org/licenses/LICENSE-2.0)
@ -18,7 +18,6 @@ import
../nimbus/common/common, ../nimbus/common/common,
../nimbus/core/chain, ../nimbus/core/chain,
../nimbus/core/tx_pool, ../nimbus/core/tx_pool,
../nimbus/core/casper,
../nimbus/transaction, ../nimbus/transaction,
../nimbus/constants, ../nimbus/constants,
../nimbus/db/ledger {.all.}, # import all private symbols ../nimbus/db/ledger {.all.}, # import all private symbols
@ -312,13 +311,13 @@ proc runLedgerTransactionTests(noisy = true) =
for _ in 0..<NumTransactions: for _ in 0..<NumTransactions:
let recipient = initAddr(recipientSeed) let recipient = initAddr(recipientSeed)
let tx = env.makeTx(recipient, 1.u256) let tx = env.makeTx(recipient, 1.u256)
check env.xp.addTx(tx).isOk check env.xp.addTx(tx).isOk
inc recipientSeed inc recipientSeed
check env.xp.len == NumTransactions check env.xp.len == NumTransactions
env.com.pos.prevRandao = prevRandao env.xp.prevRandao = prevRandao
env.com.pos.feeRecipient = feeRecipient env.xp.feeRecipient = feeRecipient
env.com.pos.timestamp = blockTime env.xp.timestamp = blockTime
blockTime = EthTime(blockTime.uint64 + 1'u64) blockTime = EthTime(blockTime.uint64 + 1'u64)

View File

@ -1,5 +1,5 @@
# Nimbus # Nimbus
# Copyright (c) 2018-2024 Status Research & Development GmbH # Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed under either of # Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) # * 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) # * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
@ -18,7 +18,7 @@ import
../nimbus/[constants, transaction, config, version], ../nimbus/[constants, transaction, config, version],
../nimbus/db/[ledger, storage_types], ../nimbus/db/[ledger, storage_types],
../nimbus/sync/protocol, ../nimbus/sync/protocol,
../nimbus/core/[tx_pool, chain, pow/difficulty, casper], ../nimbus/core/[tx_pool, chain, pow/difficulty],
../nimbus/utils/utils, ../nimbus/utils/utils,
../nimbus/[common, rpc], ../nimbus/[common, rpc],
../nimbus/rpc/rpc_types, ../nimbus/rpc/rpc_types,
@ -236,9 +236,9 @@ proc generateBlock(env: var TestEnv) =
doAssert(xp.len == 2) doAssert(xp.len == 2)
# generate block # generate block
com.pos.prevRandao = prevRandao xp.prevRandao = prevRandao
com.pos.feeRecipient = feeRecipient xp.feeRecipient = feeRecipient
com.pos.timestamp = EthTime.now() xp.timestamp = EthTime.now()
let bundle = xp.assembleBlock().valueOr: let bundle = xp.assembleBlock().valueOr:
debugEcho error debugEcho error

View File

@ -21,7 +21,6 @@ import
../nimbus/[config, transaction, constants], ../nimbus/[config, transaction, constants],
../nimbus/core/tx_pool, ../nimbus/core/tx_pool,
../nimbus/core/tx_pool/tx_desc, ../nimbus/core/tx_pool/tx_desc,
../nimbus/core/casper,
../nimbus/common/common, ../nimbus/common/common,
../nimbus/utils/utils, ../nimbus/utils/utils,
./macro_assembler ./macro_assembler
@ -111,7 +110,7 @@ template checkAddTxSupersede(xp, tx) =
check xp.len == prevCount check xp.len == prevCount
template checkAssembleBlock(xp, expCount): auto = template checkAssembleBlock(xp, expCount): auto =
xp.com.pos.timestamp = xp.com.pos.timestamp + 1 xp.timestamp = xp.timestamp + 1
let rc = xp.assembleBlock() let rc = xp.assembleBlock()
check rc.isOk == true check rc.isOk == true
if rc.isErr: if rc.isErr:
@ -186,9 +185,9 @@ proc txPoolMain*() =
chain = env.chain chain = env.chain
com = env.com com = env.com
com.pos.prevRandao = prevRandao xp.prevRandao = prevRandao
com.pos.feeRecipient = feeRecipient xp.feeRecipient = feeRecipient
com.pos.timestamp = EthTime.now() xp.timestamp = EthTime.now()
test "Bad blob tx": test "Bad blob tx":
let acc = mx.getAccount(7) let acc = mx.getAccount(7)
@ -334,7 +333,7 @@ proc txPoolMain*() =
var numTxsPacked = 0 var numTxsPacked = 0
while numTxsPacked < MAX_TXS_GENERATED: while numTxsPacked < MAX_TXS_GENERATED:
com.pos.timestamp = com.pos.timestamp + 1 xp.timestamp = xp.timestamp + 1
let bundle = xp.assembleBlock().valueOr: let bundle = xp.assembleBlock().valueOr:
debugEcho error debugEcho error
check false check false
@ -370,6 +369,8 @@ proc txPoolMain*() =
xp.checkAddTx(ptx2) xp.checkAddTx(ptx2)
xp2.checkImportBlock(2, 0) xp2.checkImportBlock(2, 0)
xp.timestamp = xp2.timestamp + 1
xp.checkImportBlock(1, 0) xp.checkImportBlock(1, 0)
test "mixed type of transactions": test "mixed type of transactions":