TxPool refactoring: Simplify TxChainRef and remove gauges (#2506)

This is one of the txPool refactoring series to make it ready
for integration with the new ForkedChainRef
This commit is contained in:
andri lim 2024-07-19 16:24:36 +07:00 committed by GitHub
parent 57b36dc4ee
commit 6d03acec30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 116 additions and 465 deletions

View File

@ -598,7 +598,7 @@ func com*(xp: TxPoolRef): CommonRef =
## Getter
xp.chain.com
func baseFee*(xp: TxPoolRef): GasPrice =
func baseFee*(xp: TxPoolRef): GasInt =
## Getter, this parameter modifies/determines the expected gain when packing
xp.chain.baseFee
@ -669,11 +669,6 @@ proc assembleBlock*(
blk: blk,
blobsBundle: blobsBundleOpt)
func gasCumulative*(xp: TxPoolRef): GasInt =
## Getter, retrieves the gas that will be burned in the block after
## retrieving it via `ethBlock`.
xp.chain.gasUsed
func gasTotals*(xp: TxPoolRef): TxTabsGasTotals =
## Getter, retrieves the current gas limit totals per bucket.
xp.txDB.gasTotals
@ -716,22 +711,11 @@ func nItems*(xp: TxPoolRef): TxTabsItemsCount =
## some totals.
xp.txDB.nItems
func profitability*(xp: TxPoolRef): GasPrice =
## Getter, a calculation of the average *price* per gas to be rewarded after
## packing the last block (see `ethBlock`). This *price* is only based on
## execution transaction in the VM without *PoW* specific rewards. The net
## profit (as opposed to the *PoW/PoA* specifc *reward*) can be calculated
## as `gasCumulative * profitability`.
if 0 < xp.chain.gasUsed:
(xp.chain.profit div xp.chain.gasUsed.u256).truncate(uint64).GasPrice
else:
0.GasPrice
# ------------------------------------------------------------------------------
# Public functions, setters
# ------------------------------------------------------------------------------
func `baseFee=`*(xp: TxPoolRef; val: GasPrice) {.raises: [KeyError].} =
func `baseFee=`*(xp: TxPoolRef; val: GasInt) {.raises: [KeyError].} =
## Setter, sets `baseFee` explicitely witout triggering a packer update.
## Stil a database update might take place when updating account ranks.
##
@ -739,7 +723,6 @@ func `baseFee=`*(xp: TxPoolRef; val: GasPrice) {.raises: [KeyError].} =
## update would be employed to do the job figuring out the proper value
## for the `baseFee`.
xp.txDB.baseFee = val
xp.chain.baseFee = val
func `flags=`*(xp: TxPoolRef; val: set[TxPoolFlags]) =
## Setter, strategy symbols for how to process items and buckets.

View File

@ -22,84 +22,101 @@ import
../../utils/utils,
../../evm/state,
../../evm/types,
../pow/header,
../eip4844,
../pow/difficulty,
../executor,
../casper,
./tx_chain/[tx_basefee, tx_gaslimits],
./tx_item
eth/eip1559
type
TxChainPackerEnv = tuple
vmState: BaseVMState ## current tx/packer environment
receipts: seq[Receipt] ## `vmState.receipts` after packing
reward: UInt256 ## Miner balance difference after packing
profit: UInt256 ## Net reward (w/o PoW specific block rewards)
txRoot: Hash256 ## `rootHash` after packing
stateRoot: Hash256 ## `stateRoot` after packing
blobGasUsed:
Opt[uint64] ## EIP-4844 block blobGasUsed
excessBlobGas:
Opt[uint64] ## EIP-4844 block excessBlobGas
TxChainRef* = ref object ##\
## State cache of the transaction environment for creating a new\
## block. This state is typically synchrionised with the canonical\
## block chain head when updated.
com: CommonRef ## Block chain config
roAcc: ReadOnlyStateDB ## Accounts cache fixed on current sync header
gasLimit*: GasInt
txEnv: TxChainPackerEnv ## Assorted parameters, tx packer environment
prepHeader: BlockHeader ## Prepared Header from Consensus Engine
vmState: BaseVMState ## current tx/packer environment
receiptsRoot: Hash256
logsBloom: BloomFilter
txRoot: Hash256 ## `rootHash` after packing
stateRoot: Hash256 ## `stateRoot` after packing
# ------------------------------------------------------------------------------
# Private functions
# ------------------------------------------------------------------------------
func prepareHeader(dh: TxChainRef; parent: BlockHeader, timestamp: EthTime)
{.raises: [].} =
proc baseFeeGet(com: CommonRef; parent: BlockHeader): Opt[UInt256] =
## Calculates the `baseFee` of the head assuming this is the parent of a
## new block header to generate.
# Note that the baseFee is calculated for the next header
if not com.isLondonOrLater(parent.number+1):
return Opt.none(UInt256)
# If the new block is the first EIP-1559 block, return initial base fee.
if not com.isLondonOrLater(parent.number):
return Opt.some(EIP1559_INITIAL_BASE_FEE)
Opt.some calcEip1599BaseFee(
parent.gasLimit,
parent.gasUsed,
parent.baseFeePerGas.get(0.u256))
proc gasLimitsGet(com: CommonRef; parent: BlockHeader): GasInt =
if com.isLondonOrLater(parent.number+1):
var parentGasLimit = parent.gasLimit
if not com.isLondonOrLater(parent.number):
# Bump by 2x
parentGasLimit = parent.gasLimit * EIP1559_ELASTICITY_MULTIPLIER
calcGasLimit1559(parentGasLimit, desiredLimit = DEFAULT_GAS_LIMIT)
else:
computeGasLimit(
parent.gasUsed,
parent.gasLimit,
gasFloor = DEFAULT_GAS_LIMIT,
gasCeil = DEFAULT_GAS_LIMIT)
func prepareHeader(dh: TxChainRef) =
dh.com.pos.prepare(dh.prepHeader)
func prepareForSeal(dh: TxChainRef; header: var BlockHeader) {.raises: [].} =
func prepareForSeal(dh: TxChainRef; header: var BlockHeader) =
dh.com.pos.prepareForSeal(header)
func getTimestamp(dh: TxChainRef, parent: BlockHeader): EthTime =
func getTimestamp(dh: TxChainRef): EthTime =
dh.com.pos.timestamp
func feeRecipient*(dh: TxChainRef): EthAddress
proc resetTxEnv(dh: TxChainRef; parent: BlockHeader; baseFeePerGas: Opt[UInt256])
{.gcsafe,raises: [].} =
dh.txEnv.reset
func feeRecipient*(dh: TxChainRef): EthAddress =
## Getter
dh.com.pos.feeRecipient
proc resetTxEnv(dh: TxChainRef; parent: BlockHeader) =
# do hardfork transition before
# BaseVMState querying any hardfork/consensus from CommonRef
let timestamp = dh.getTimestamp(parent)
let timestamp = dh.getTimestamp()
dh.com.hardForkTransition(
parent.blockHash, parent.number+1, Opt.some(timestamp))
dh.prepareHeader(parent, timestamp)
dh.prepareHeader()
# we don't consider PoS difficulty here
# because that is handled in vmState
let blockCtx = BlockContext(
timestamp : dh.prepHeader.timestamp,
gasLimit : dh.gasLimit,
baseFeePerGas: baseFeePerGas,
gasLimit : gasLimitsGet(dh.com, parent),
baseFeePerGas: baseFeeGet(dh.com, parent),
prevRandao : dh.prepHeader.prevRandao,
difficulty : dh.prepHeader.difficulty,
coinbase : dh.feeRecipient,
excessBlobGas: calcExcessBlobGas(parent),
)
dh.txEnv.vmState = BaseVMState.new(
dh.vmState = BaseVMState.new(
parent = parent,
blockCtx = blockCtx,
com = dh.com)
dh.txEnv.txRoot = EMPTY_ROOT_HASH
dh.txEnv.stateRoot = dh.txEnv.vmState.parent.stateRoot
dh.txEnv.blobGasUsed = Opt.none(uint64)
dh.txEnv.excessBlobGas = Opt.none(uint64)
dh.txRoot = EMPTY_ROOT_HASH
dh.stateRoot = dh.vmState.parent.stateRoot
proc update(dh: TxChainRef; parent: BlockHeader)
{.gcsafe,raises: [].} =
@ -107,13 +124,10 @@ proc update(dh: TxChainRef; parent: BlockHeader)
let
db = dh.com.db
acc = LedgerRef.init(db, parent.stateRoot)
fee = baseFeeGet(dh.com, parent)
# Keep a separate accounts descriptor positioned at the sync point
dh.roAcc = ReadOnlyStateDB(acc)
dh.gasLimit = dh.com.gasLimitsGet(parent)
dh.resetTxEnv(parent, fee)
dh.resetTxEnv(parent)
# ------------------------------------------------------------------------------
# Public functions, constructor
@ -146,44 +160,61 @@ proc getNonce*(dh: TxChainRef; account: EthAddress): AccountNonce =
## relative to what has been accumulated by the current packing procedure.
dh.roAcc.getNonce(account)
func baseFee*(dh: TxChainRef): GasInt =
## Getter, baseFee for the next bock header. This value is auto-generated
## when a new insertion point is set via `head=`.
if dh.vmState.blockCtx.baseFeePerGas.isSome:
dh.vmState.blockCtx.baseFeePerGas.get.truncate(GasInt)
else:
0.GasInt
func excessBlobGas*(dh: TxChainRef): uint64 =
## Getter, baseFee for the next bock header. This value is auto-generated
## when a new insertion point is set via `head=`.
dh.vmState.blockCtx.excessBlobGas
func blobGasUsed*(dh: TxChainRef): uint64 =
dh.vmState.blobGasUsed
func gasLimit*(dh: TxChainRef): GasInt =
dh.vmState.blockCtx.gasLimit
proc getHeader*(dh: TxChainRef): BlockHeader
{.gcsafe,raises: [].} =
## Generate a new header, a child of the cached `head`
let gasUsed = if dh.txEnv.receipts.len == 0: 0.GasInt
else: dh.txEnv.receipts[^1].cumulativeGasUsed
result = BlockHeader(
parentHash: dh.txEnv.vmState.parent.blockHash,
parentHash: dh.vmState.parent.blockHash,
ommersHash: EMPTY_UNCLE_HASH,
coinbase: dh.prepHeader.coinbase,
stateRoot: dh.txEnv.stateRoot,
txRoot: dh.txEnv.txRoot,
receiptsRoot: dh.txEnv.receipts.calcReceiptsRoot,
logsBloom: dh.txEnv.receipts.createBloom,
stateRoot: dh.stateRoot,
txRoot: dh.txRoot,
receiptsRoot: dh.receiptsRoot,
logsBloom: dh.logsBloom,
difficulty: dh.prepHeader.difficulty,
number: dh.txEnv.vmState.blockNumber,
gasLimit: dh.txEnv.vmState.blockCtx.gasLimit,
gasUsed: gasUsed,
number: dh.vmState.blockNumber,
gasLimit: dh.gasLimit,
gasUsed: dh.vmState.cumulativeGasUsed,
timestamp: dh.prepHeader.timestamp,
# extraData: Blob # signing data
# mixHash: Hash256 # mining hash for given difficulty
# nonce: BlockNonce # mining free vaiable
baseFeePerGas: dh.txEnv.vmState.blockCtx.baseFeePerGas,
blobGasUsed: dh.txEnv.blobGasUsed,
excessBlobGas: dh.txEnv.excessBlobGas)
baseFeePerGas: dh.vmState.blockCtx.baseFeePerGas,
)
if dh.com.isShanghaiOrLater(result.timestamp):
result.withdrawalsRoot = Opt.some(calcWithdrawalsRoot(dh.com.pos.withdrawals))
if dh.com.isCancunOrLater(result.timestamp):
result.parentBeaconBlockRoot = Opt.some(dh.com.pos.parentBeaconBlockRoot)
result.blobGasUsed = Opt.some dh.blobGasUsed
result.excessBlobGas = Opt.some dh.excessBlobGas
dh.prepareForSeal(result)
proc clearAccounts*(dh: TxChainRef)
{.gcsafe,raises: [].} =
## Reset transaction environment, e.g. before packing a new block
dh.resetTxEnv(dh.txEnv.vmState.parent, dh.txEnv.vmState.blockCtx.baseFeePerGas)
dh.resetTxEnv(dh.vmState.parent)
# ------------------------------------------------------------------------------
# Public functions, getters
@ -195,104 +226,41 @@ func com*(dh: TxChainRef): CommonRef =
func head*(dh: TxChainRef): BlockHeader =
## Getter
dh.txEnv.vmState.parent
func feeRecipient*(dh: TxChainRef): EthAddress =
## Getter
dh.com.pos.feeRecipient
func baseFee*(dh: TxChainRef): GasPrice =
## Getter, baseFee for the next bock header. This value is auto-generated
## when a new insertion point is set via `head=`.
if dh.txEnv.vmState.blockCtx.baseFeePerGas.isSome:
dh.txEnv.vmState.blockCtx.baseFeePerGas.get.truncate(uint64).GasPrice
else:
0.GasPrice
func excessBlobGas*(dh: TxChainRef): uint64 =
## Getter, baseFee for the next bock header. This value is auto-generated
## when a new insertion point is set via `head=`.
dh.txEnv.excessBlobGas.get(0'u64)
dh.vmState.parent
func nextFork*(dh: TxChainRef): EVMFork =
## Getter, fork of next block
dh.txEnv.vmState.fork
func gasUsed*(dh: TxChainRef): GasInt =
## Getter, accumulated gas burned for collected blocks
if 0 < dh.txEnv.receipts.len:
return dh.txEnv.receipts[^1].cumulativeGasUsed
func profit*(dh: TxChainRef): UInt256 =
## Getter
dh.txEnv.profit
func receipts*(dh: TxChainRef): seq[Receipt] =
## Getter, receipts for collected blocks
dh.txEnv.receipts
func reward*(dh: TxChainRef): UInt256 =
## Getter, reward for collected blocks
dh.txEnv.reward
func stateRoot*(dh: TxChainRef): Hash256 =
## Getter, accounting DB state root hash for the next block header
dh.txEnv.stateRoot
func txRoot*(dh: TxChainRef): Hash256 =
## Getter, transaction state root hash for the next block header
dh.txEnv.txRoot
dh.vmState.fork
func vmState*(dh: TxChainRef): BaseVMState =
## Getter, `BaseVmState` descriptor based on the current insertion point.
dh.txEnv.vmState
dh.vmState
# ------------------------------------------------------------------------------
# Public functions, setters
# ------------------------------------------------------------------------------
func `baseFee=`*(dh: TxChainRef; val: GasPrice) =
## Setter, temorarily overwrites parameter until next `head=` update. This
## function would be called in exceptional cases only as this parameter is
## determined by the `head=` update.
if 0 < val or dh.com.isLondonOrLater(dh.txEnv.vmState.blockNumber):
dh.txEnv.vmState.blockCtx.baseFeePerGas = Opt.some(val.uint64.u256)
else:
dh.txEnv.vmState.blockCtx.baseFeePerGas = Opt.none UInt256
proc `head=`*(dh: TxChainRef; val: BlockHeader)
{.gcsafe,raises: [].} =
## Setter, updates descriptor. This setter re-positions the `vmState` and
## account caches to a new insertion point on the block chain database.
dh.update(val)
func `profit=`*(dh: TxChainRef; val: UInt256) =
## Setter
dh.txEnv.profit = val
func `receipts=`*(dh: TxChainRef; val: seq[Receipt]) =
func `receiptsRoot=`*(dh: TxChainRef; val: Hash256) =
## Setter, implies `gasUsed`
dh.txEnv.receipts = val
dh.receiptsRoot = val
func `reward=`*(dh: TxChainRef; val: UInt256) =
## Getter
dh.txEnv.reward = val
func `logsBloom=`*(dh: TxChainRef; val: BloomFilter) =
## Setter, implies `gasUsed`
dh.logsBloom = val
func `stateRoot=`*(dh: TxChainRef; val: Hash256) =
## Setter
dh.txEnv.stateRoot = val
dh.stateRoot = val
func `txRoot=`*(dh: TxChainRef; val: Hash256) =
## Setter
dh.txEnv.txRoot = val
func `excessBlobGas=`*(dh: TxChainRef; val: Opt[uint64]) =
## Setter
dh.txEnv.excessBlobGas = val
func `blobGasUsed=`*(dh: TxChainRef; val: Opt[uint64]) =
## Setter
dh.txEnv.blobGasUsed = val
dh.txRoot = val
# ------------------------------------------------------------------------------
# End

View File

@ -1,46 +0,0 @@
# Nimbus
# Copyright (c) 2018-2024 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.
## Block Chain Helper: Calculate Base Fee
## =======================================
##
import
../../../common/common,
../../../constants,
eth/eip1559
{.push raises: [].}
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
proc baseFeeGet*(com: CommonRef;
parent: BlockHeader): Opt[UInt256] =
## Calculates the `baseFee` of the head assuming this is the parent of a
## new block header to generate.
# Note that the baseFee is calculated for the next header
if not com.isLondonOrLater(parent.number+1):
return Opt.none(UInt256)
# If the new block is the first EIP-1559 block, return initial base fee.
if not com.isLondonOrLater(parent.number):
return Opt.some(EIP1559_INITIAL_BASE_FEE)
Opt.some calcEip1599BaseFee(
parent.gasLimit,
parent.gasUsed,
parent.baseFeePerGas.get(0.u256))
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -1,45 +0,0 @@
# Nimbus
# Copyright (c) 2018-2024 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.
## Block Chain Helper: Gas Limits
## ==============================
##
import
../../../common/common,
../../../constants,
../../pow/header,
eth/[eip1559]
{.push raises: [].}
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
proc gasLimitsGet*(com: CommonRef;
parent: BlockHeader): GasInt =
if com.isLondonOrLater(parent.number+1):
var parentGasLimit = parent.gasLimit
if not com.isLondonOrLater(parent.number):
# Bump by 2x
parentGasLimit = parent.gasLimit * EIP1559_ELASTICITY_MULTIPLIER
calcGasLimit1559(parentGasLimit, desiredLimit = DEFAULT_GAS_LIMIT)
else:
computeGasLimit(
parent.gasUsed,
parent.gasLimit,
gasFloor = DEFAULT_GAS_LIMIT,
gasCeil = DEFAULT_GAS_LIMIT)
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -1,142 +0,0 @@
# 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.
## Transaction Pool Meters
## =======================
##
import
metrics
{.push raises: [].}
const
# Provide some fall-back counters available for unit tests
FallBackMetrics4Debugging = not defined(metrics)
when FallBackMetrics4Debugging:
{.warning: "Debugging fall back mode for some gauges".}
type
DummyCounter* = ref object
value: float64
# ------------------------------------------------------------------------------
# Private settings
# ------------------------------------------------------------------------------
# Metrics for the pending pool
# core/tx_pool.go(97): pendingDiscardMeter = metrics.NewRegisteredMeter(..
declareGauge pendingDiscard, "n/a"
declareGauge pendingReplace, "n/a"
declareGauge pendingRateLimit, "n/a" # Dropped due to rate limiting
declareGauge pendingNofunds, "n/a" # Dropped due to out-of-funds
# Metrics for the queued pool
# core/tx_pool.go(103): queuedDiscardMeter = metrics.NewRegisteredMeter(..
declareGauge queuedDiscard, "n/a"
declareGauge queuedReplace, "n/a"
declareGauge queuedRateLimit, "n/a" # Dropped due to rate limiting
declareGauge queuedNofunds, "n/a" # Dropped due to out-of-funds
declareGauge evictionGauge,
"A transaction has been on the system for too long so it was removed"
declareGauge impliedEvictionGauge,
"Implied disposal for greater nonces (same sender) when base tx was removed"
# General tx metrics
# core/tx_pool.go(110): knownTxMeter = metrics.NewRegisteredMeter(..
declareGauge knownTransactions, "n/a"
declareGauge validTransactions, "n/a"
declareGauge invalidTransactions, "n/a"
declareGauge underpricedTransactions, "n/a"
declareGauge overflowedTransactions, "n/a"
# core/tx_pool.go(117): throttleTxMeter = metrics.NewRegisteredMeter(..
declareGauge throttleTransactions,
"Rejected transactions due to too-many-changes between txpool reorgs"
# core/tx_pool.go(119): reorgDurationTimer = metrics.NewRegisteredTimer(..
declareGauge reorgDurationTimer, "Measures how long time a txpool reorg takes"
# core/tx_pool.go(122): dropBetweenReorgHistogram = metrics..
declareGauge dropBetweenReorgHistogram,
"Number of expected drops between two reorg runs. It is expected that "&
"this number is pretty low, since txpool reorgs happen very frequently"
# core/tx_pool.go(124): pendingGauge = metrics.NewRegisteredGauge(..
declareGauge pendingGauge, "n/a"
declareGauge queuedGauge, "n/a"
declareGauge localGauge, "n/a"
declareGauge slotsGauge, "n/a"
# core/tx_pool.go(129): reheapTimer = metrics.NewRegisteredTimer(..
# declareGauge reheapTimer, "n/a" -- notused
# ----------------------
declareGauge unspecifiedError,
"Some error occured but was not specified in any way. This counter should "&
"stay zero."
# ------------------------------------------------------------------------------
# Exports
# ------------------------------------------------------------------------------
when FallBackMetrics4Debugging:
let
evictionMeter* = DummyCounter()
impliedEvictionMeter* = DummyCounter()
proc inc(w: DummyCounter; val: int64|float64 = 1,) =
w.value = w.value + val.float64
else:
let
evictionMeter* = evictionGauge
impliedEvictionMeter* = impliedEvictionGauge
# ------------------------------------------------------------------------------
# Global functions -- deprecated
# ------------------------------------------------------------------------------
proc pendingDiscardMeter*(n = 1i64) = pendingDiscard.inc(n)
proc pendingReplaceMeter*(n = 1i64) = pendingReplace.inc(n)
proc pendingRateLimitMeter*(n = 1i64) = pendingRateLimit.inc(n)
proc pendingNofundsMeter*(n = 1i64) = pendingNofunds.inc(n)
proc queuedDiscardMeter*(n = 1i64) = queuedDiscard.inc(n)
proc queuedReplaceMeter*(n = 1i64) = queuedReplace.inc(n)
proc queuedRateLimitMeter*(n = 1i64) = queuedRateLimit.inc(n)
proc queuedNofundsMeter*(n = 1i64) = queuedNofunds.inc(n)
proc knownTxMeter*(n = 1i64) = knownTransactions.inc(n)
proc invalidTxMeter*(n = 1i64) = invalidTransactions.inc(n)
proc validTxMeter*(n = 1i64) = validTransactions.inc(n)
proc underpricedTxMeter*(n = 1i64) = underpricedTransactions.inc(n)
proc overflowedTxMeter*(n = 1i64) = overflowedTransactions.inc(n)
proc throttleTxMeter*(n = 1i64) = throttleTransactions.inc(n)
proc unspecifiedErrorMeter*(n = 1i64) = unspecifiedError.inc(n)
proc reorgDurationTimerMeter*(n = 1i64) = reorgDurationTimer.inc(n)
proc dropBetweenReorgHistogramMeter*(n = 1i64) =
dropBetweenReorgHistogram.inc(n)
proc pendingGaugeMeter*(n = 1i64) = pendingGauge.inc(n)
proc queuedGaugeMeter*(n = 1i64) = queuedGauge.inc(n)
proc localGaugeMeter*(n = 1i64) = localGauge.inc(n)
proc slotsGaugeMeter*(n = 1i64) = slotsGauge.inc(n)
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -161,18 +161,18 @@ proc cost*(tx: Transaction): UInt256 =
# core/types/transaction.go(332): .. *Transaction) EffectiveGasTip(baseFee ..
# core/types/transaction.go(346): .. EffectiveGasTipValue(baseFee ..
proc effectiveGasTip*(tx: Transaction; baseFee: GasPrice): GasPriceEx =
proc effectiveGasTip*(tx: Transaction; baseFee: GasInt): GasPriceEx =
## The effective miner gas tip for the globally argument `baseFee`. The
## result (which is a price per gas) might well be negative.
if tx.txType < TxEip1559:
(tx.gasPrice - baseFee.GasInt).GasPriceEx
(tx.gasPrice - baseFee).GasPriceEx
else:
# London, EIP1559
min(tx.maxPriorityFeePerGas, tx.maxFeePerGas - baseFee.GasInt).GasPriceEx
min(tx.maxPriorityFeePerGas, tx.maxFeePerGas - baseFee).GasPriceEx
proc effectiveGasTip*(tx: Transaction; baseFee: UInt256): GasPriceEx =
## Variant of `effectiveGasTip()`
tx.effectiveGasTip(baseFee.truncate(uint64).GasPrice)
tx.effectiveGasTip(baseFee.truncate(GasInt))
# ------------------------------------------------------------------------------
# Public functions, item getters

View File

@ -250,7 +250,7 @@ proc reject*(xp: TxTabsRef; tx: PooledTransaction;
# Public getters
# ------------------------------------------------------------------------------
proc baseFee*(xp: TxTabsRef): GasPrice =
proc baseFee*(xp: TxTabsRef): GasInt =
## Getter
xp.bySender.baseFee
@ -270,7 +270,7 @@ proc remote*(lc: TxTabsLocality): seq[EthAddress] =
# Public functions, setters
# ------------------------------------------------------------------------------
proc `baseFee=`*(xp: TxTabsRef; val: GasPrice)
proc `baseFee=`*(xp: TxTabsRef; val: GasInt)
{.gcsafe,raises: [KeyError].} =
## Setter, update may cause database re-org
if xp.bySender.baseFee != val:

View File

@ -41,7 +41,7 @@ type
## Per address table This is table provided as a keyed queue so deletion\
## while traversing is supported and predictable.
size: int ## Total number of items
baseFee: GasPrice ## For aggregating `effectiveGasTip` => `gasTipSum`
baseFee: GasInt ## For aggregating `effectiveGasTip` => `gasTipSum`
addrList: KeyedQueue[EthAddress,TxSenderSchedRef]
TxSenderSchedule* = enum ##\
@ -120,11 +120,11 @@ proc getRank(schedData: TxSenderSchedRef): int64 =
profit.int64
proc maxProfit(item: TxItemRef; baseFee: GasPrice): float64 =
proc maxProfit(item: TxItemRef; baseFee: GasInt): float64 =
## Profit calculator
item.tx.gasLimit.float64 * item.tx.effectiveGasTip(baseFee).float64 + item.tx.getTotalBlobGas.float64
proc recalcProfit(nonceData: TxSenderNonceRef; baseFee: GasPrice) =
proc recalcProfit(nonceData: TxSenderNonceRef; baseFee: GasInt) =
## Re-calculate profit value depending on `baseFee`
nonceData.profit = 0.0
var rc = nonceData.nonceList.ge(AccountNonce.low)
@ -367,7 +367,7 @@ proc verify*(gt: var TxSenderTab): Result[void,TxInfo]
# Public getters
# ------------------------------------------------------------------------------
proc baseFee*(gt: var TxSenderTab): GasPrice =
proc baseFee*(gt: var TxSenderTab): GasInt =
## Getter
gt.baseFee
@ -375,7 +375,7 @@ proc baseFee*(gt: var TxSenderTab): GasPrice =
# Public functions, setters
# ------------------------------------------------------------------------------
proc `baseFee=`*(gt: var TxSenderTab; val: GasPrice) =
proc `baseFee=`*(gt: var TxSenderTab; val: GasInt) =
## Setter. When invoked, there is *always* a re-calculation of the profit
## values stored with the sender address.
gt.baseFee = val

View File

@ -15,7 +15,6 @@
import
std/[tables],
../tx_desc,
../tx_gauge,
../tx_info,
../tx_item,
../tx_tabs,
@ -137,7 +136,6 @@ proc addTx*(xp: TxPoolRef; item: TxItemRef): bool
block:
let rc = xp.txDB.insert(item)
if rc.isOk:
validTxMeter(1)
return item.status == txItemStaged
vetted = rc.error
@ -145,23 +143,12 @@ proc addTx*(xp: TxPoolRef; item: TxItemRef): bool
if vetted == txInfoErrSenderNonceIndex:
let rc = xp.supersede(item)
if rc.isOk:
validTxMeter(1)
return
vetted = rc.error
# Error processing => store in waste basket
xp.txDB.reject(item, vetted)
# update gauge
case vetted:
of txInfoErrAlreadyKnown:
knownTxMeter(1)
of txInfoErrInvalidSender:
invalidTxMeter(1)
else:
unspecifiedErrorMeter(1)
# core/tx_pool.go(848): func (pool *TxPool) AddLocals(txs []..
# core/tx_pool.go(854): func (pool *TxPool) AddLocals(txs []..
# core/tx_pool.go(864): func (pool *TxPool) AddRemotes(txs []..
@ -195,7 +182,6 @@ proc addTxs*(xp: TxPoolRef;
# move item to waste basket
reason = txInfoErrInvalidBlob
xp.txDB.reject(tx, reason, txItemPending, res.error)
invalidTxMeter(1)
continue
# Create tx item wrapper, preferably recovered from waste basket
@ -215,15 +201,6 @@ proc addTxs*(xp: TxPoolRef;
# move item to waste basket
xp.txDB.reject(tx, reason, txItemPending, info)
# update gauge
case reason:
of txInfoErrAlreadyKnown:
knownTxMeter(1)
of txInfoErrInvalidSender:
invalidTxMeter(1)
else:
unspecifiedErrorMeter(1)
# Add sorted transaction items
for itemList in accTab.mvalues:
var

View File

@ -107,7 +107,7 @@ proc txFeesCovered(xp: TxPoolRef; item: TxItemRef): bool =
## Ensure that the user was willing to at least pay the base fee
## And to at least pay the current data gasprice
if item.tx.txType >= TxEip1559:
if item.tx.maxFeePerGas.GasPriceEx < xp.chain.baseFee:
if item.tx.maxFeePerGas < xp.chain.baseFee:
debug "invalid tx: maxFee is smaller than baseFee",
maxFee = item.tx.maxFeePerGas,
baseFee = xp.chain.baseFee

View File

@ -1,5 +1,5 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Copyright (c) 2018-2024 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)
@ -15,7 +15,6 @@
import
std/[times],
../tx_desc,
../tx_gauge,
../tx_info,
../tx_item,
../tx_tabs,
@ -50,7 +49,6 @@ proc deleteOtherNonces(xp: TxPoolRef; item: TxItemRef; newerThan: Time): bool
# only delete non-expired items
if newerThan < other.timeStamp:
discard xp.txDB.dispose(other, txInfoErrTxExpiredImplied)
impliedEvictionMeter.inc
result = true
# ------------------------------------------------------------------------------
@ -82,7 +80,6 @@ proc disposeExpiredItems*(xp: TxPoolRef) {.gcsafe,raises: [KeyError].} =
# Note: it is ok to delete the current item
discard xp.txDB.dispose(item, txInfoErrTxExpired)
evictionMeter.inc
# Also delete all non-expired items with higher nonces.
if xp.deleteOtherNonces(item, deadLine):

View File

@ -15,14 +15,13 @@
{.push raises: [].}
import
chronicles,
eth/[keys, rlp],
stew/sorted_set,
../../../db/[ledger, core_db],
../../../common/common,
../../../utils/utils,
../../../constants,
"../.."/[dao, executor, validate, casper],
"../.."/[executor, validate, casper],
../../../transaction/call_evm,
../../../transaction,
../../../evm/state,
@ -31,14 +30,10 @@ import
"."/[tx_bucket, tx_classify]
type
TxPackerError* = object of CatchableError
## Catch and relay exception error
TxPackerStateRef = ref object
xp: TxPoolRef
tr: CoreDbMptRef
cleanState: bool
balance: UInt256
numBlobPerBlock: int
const
@ -46,25 +41,10 @@ const
## Number of slots to extend the `receipts[]` at the same time.
20
logScope:
topics = "tx-pool packer"
# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------
when false:
template safeExecutor(info: string; code: untyped) =
try:
code
except CatchableError as e:
raise (ref CatchableError)(msg: e.msg)
except Defect as e:
raise (ref Defect)(msg: e.msg)
except:
let e = getCurrentException()
raise newException(TxPackerError, info & "(): " & $e.name & " -- " & e.msg)
proc persist(pst: TxPackerStateRef)
{.gcsafe,raises: [].} =
## Smart wrapper
@ -130,7 +110,7 @@ proc runTxCommit(pst: TxPackerStateRef; item: TxItemRef; gasBurned: GasInt)
vmState.receipts[inx] = vmState.makeReceipt(item.tx.txType)
# Update txRoot
pst.tr.merge(rlp.encode(inx), rlp.encode(item.tx)).isOkOr:
pst.tr.merge(rlp.encode(inx.uint64), rlp.encode(item.tx)).isOkOr:
raiseAssert "runTxCommit(): merge failed, " & $$error
# Add the item to the `packed` bucket. This implicitely increases the
@ -150,11 +130,6 @@ proc vmExecInit(xp: TxPoolRef): Result[TxPackerStateRef, string]
# reset blockValue before adding any tx
xp.blockValue = 0.u256
if xp.chain.com.daoForkSupport and
xp.chain.com.daoForkBlock.get == xp.chain.head.number + 1:
xp.chain.vmState.mutateStateDB:
db.applyDAOHardFork()
# EIP-4788
if xp.chain.nextFork >= FkCancun:
let beaconRoot = xp.chain.com.pos.parentBeaconBlockRoot
@ -164,7 +139,6 @@ proc vmExecInit(xp: TxPoolRef): Result[TxPackerStateRef, string]
let packer = TxPackerStateRef( # return value
xp: xp,
tr: AristoDbMemory.newCoreDbRef().ctx.getGeneric(clearData=true),
balance: xp.chain.vmState.readOnlyStateDB.getBalance(xp.chain.feeRecipient),
numBlobPerBlock: 0,
)
ok(packer)
@ -246,23 +220,12 @@ proc vmExecCommit(pst: TxPackerStateRef)
let nItems = xp.txDB.byStatus.eq(txItemPacked).nItems
vmState.receipts.setLen(nItems)
xp.chain.receipts = vmState.receipts
xp.chain.receiptsRoot = vmState.receipts.calcReceiptsRoot
xp.chain.logsBloom = vmState.receipts.createBloom
xp.chain.txRoot = pst.tr.state(updateOk=true).valueOr:
raiseAssert "vmExecCommit(): state() failed " & $$error
xp.chain.stateRoot = vmState.stateDB.rootHash
if xp.chain.nextFork >= FkCancun:
# EIP-4844
xp.chain.excessBlobGas = Opt.some(vmState.blockCtx.excessBlobGas)
xp.chain.blobGasUsed = Opt.some(vmState.blobGasUsed)
proc balanceDelta: UInt256 =
let postBalance = vmState.readOnlyStateDB.getBalance(xp.chain.feeRecipient)
if pst.balance < postBalance:
return postBalance - pst.balance
xp.chain.profit = balanceDelta()
xp.chain.reward = balanceDelta()
# ------------------------------------------------------------------------------
# Public functions

View File

@ -10,7 +10,7 @@
import
std/[os, strformat, sequtils, strutils, times],
../../nimbus/core/tx_pool/[tx_chain, tx_desc, tx_gauge, tx_item, tx_tabs],
../../nimbus/core/tx_pool/[tx_chain, tx_desc, tx_item, tx_tabs],
../../nimbus/core/tx_pool/tx_tasks/[tx_packer, tx_recover],
../replay/[pp, undump_blocks_gz],
chronicles,
@ -25,14 +25,10 @@ export
tx_chain.clearAccounts,
tx_chain.com,
tx_chain.nextFork,
tx_chain.profit,
tx_chain.receipts,
tx_chain.reward,
tx_chain.vmState,
tx_desc.chain,
tx_desc.txDB,
tx_desc.verify,
tx_gauge,
tx_packer.packerVmExec,
tx_recover.recoverItem,
tx_tabs.TxTabsRef,