Simplify txPool gasLimit calculator (#2498)

Our need is only a baseline tx pool gasLimit calculator.
If need we can expand it in the future.
But for now, a simple but understandable tx pool is more important.
This commit is contained in:
andri lim 2024-07-17 20:48:35 +07:00 committed by GitHub
parent 17391b58d0
commit 8d1e21bbae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 13 additions and 208 deletions

View File

@ -678,11 +678,6 @@ func gasTotals*(xp: TxPoolRef): TxTabsGasTotals =
## Getter, retrieves the current gas limit totals per bucket.
xp.txDB.gasTotals
func lwmTrgPercent*(xp: TxPoolRef): int =
## Getter, `trgGasLimit` percentage for `lwmGasLimit` which is
## `max(minGasLimit, trgGasLimit * lwmTrgPercent / 100)`
xp.chain.lhwm.lwmTrg
func flags*(xp: TxPoolRef): set[TxPoolFlags] =
## Getter, retrieves strategy symbols for how to process items and buckets.
xp.pFlags
@ -693,15 +688,6 @@ func head*(xp: TxPoolRef): BlockHeader =
## middle of a mining update.)
xp.chain.head
func hwmMaxPercent*(xp: TxPoolRef): int =
## Getter, `maxGasLimit` percentage for `hwmGasLimit` which is
## `max(trgGasLimit, maxGasLimit * hwmMaxPercent / 100)`
xp.chain.lhwm.hwmMax
func maxGasLimit*(xp: TxPoolRef): GasInt =
## Getter, hard size limit when packing blocks (see also `trgGasLimit`.)
xp.chain.limits.maxLimit
# core/tx_pool.go(435): func (pool *TxPool) GasPrice() *big.Int {
func minFeePrice*(xp: TxPoolRef): GasPrice =
## Getter, retrieves minimum for the current gas fee enforced by the
@ -741,11 +727,6 @@ func profitability*(xp: TxPoolRef): GasPrice =
else:
0.GasPrice
func trgGasLimit*(xp: TxPoolRef): GasInt =
## Getter, soft size limit when packing blocks (might be extended to
## `maxGasLimit`)
xp.chain.limits.trgLimit
# ------------------------------------------------------------------------------
# Public functions, setters
# ------------------------------------------------------------------------------
@ -760,30 +741,10 @@ func `baseFee=`*(xp: TxPoolRef; val: GasPrice) {.raises: [KeyError].} =
xp.txDB.baseFee = val
xp.chain.baseFee = val
func `lwmTrgPercent=`*(xp: TxPoolRef; val: int) =
## Setter, `val` arguments outside `0..100` are ignored
if 0 <= val and val <= 100:
xp.chain.lhwm = (
lwmTrg: val,
hwmMax: xp.chain.lhwm.hwmMax,
gasFloor: xp.chain.lhwm.gasFloor,
gasCeil: xp.chain.lhwm.gasCeil
)
func `flags=`*(xp: TxPoolRef; val: set[TxPoolFlags]) =
## Setter, strategy symbols for how to process items and buckets.
xp.pFlags = val
func `hwmMaxPercent=`*(xp: TxPoolRef; val: int) =
## Setter, `val` arguments outside `0..100` are ignored
if 0 <= val and val <= 100:
xp.chain.lhwm = (
lwmTrg: xp.chain.lhwm.lwmTrg,
hwmMax: val,
gasFloor: xp.chain.lhwm.gasFloor,
gasCeil: xp.chain.lhwm.gasCeil
)
func `maxRejects=`*(xp: TxPoolRef; val: int) =
## Setter, the size of the waste basket. This setting becomes effective with
## the next move of an item into the waste basket.

View File

@ -29,21 +29,6 @@ import
./tx_chain/[tx_basefee, tx_gaslimits],
./tx_item
export
TxChainGasLimits,
TxChainGasLimitsPc
const
TRG_THRESHOLD_PER_CENT = ##\
## VM executor may stop if this per centage of `trgLimit` has
## been reached.
90
MAX_THRESHOLD_PER_CENT = ##\
## VM executor may stop if this per centage of `maxLimit` has
## been reached.
90
type
TxChainPackerEnv = tuple
vmState: BaseVMState ## current tx/packer environment
@ -62,11 +47,8 @@ type
## block. This state is typically synchrionised with the canonical\
## block chain head when updated.
com: CommonRef ## Block chain config
lhwm: TxChainGasLimitsPc ## Hwm/lwm gas limit percentage
maxMode: bool ## target or maximal limit for next block header
roAcc: ReadOnlyStateDB ## Accounts cache fixed on current sync header
limits: TxChainGasLimits ## Gas limits for packer and next header
gasLimit*: GasInt
txEnv: TxChainPackerEnv ## Assorted parameters, tx packer environment
prepHeader: BlockHeader ## Prepared Header from Consensus Engine
@ -101,7 +83,7 @@ proc resetTxEnv(dh: TxChainRef; parent: BlockHeader; baseFeePerGas: Opt[UInt256]
# because that is handled in vmState
let blockCtx = BlockContext(
timestamp : dh.prepHeader.timestamp,
gasLimit : (if dh.maxMode: dh.limits.maxLimit else: dh.limits.trgLimit),
gasLimit : dh.gasLimit,
baseFeePerGas: baseFeePerGas,
prevRandao : dh.prepHeader.prevRandao,
difficulty : dh.prepHeader.difficulty,
@ -130,7 +112,7 @@ proc update(dh: TxChainRef; parent: BlockHeader)
# Keep a separate accounts descriptor positioned at the sync point
dh.roAcc = ReadOnlyStateDB(acc)
dh.limits = dh.com.gasLimitsGet(parent, dh.lhwm)
dh.gasLimit = dh.com.gasLimitsGet(parent)
dh.resetTxEnv(parent, fee)
# ------------------------------------------------------------------------------
@ -143,10 +125,6 @@ proc new*(T: type TxChainRef; com: CommonRef): T
new result
result.com = com
result.lhwm.lwmTrg = TRG_THRESHOLD_PER_CENT
result.lhwm.hwmMax = MAX_THRESHOLD_PER_CENT
result.lhwm.gasFloor = DEFAULT_GAS_LIMIT
result.lhwm.gasCeil = DEFAULT_GAS_LIMIT
result.update(com.db.getCanonicalHead)
# ------------------------------------------------------------------------------
@ -219,18 +197,6 @@ func head*(dh: TxChainRef): BlockHeader =
## Getter
dh.txEnv.vmState.parent
func limits*(dh: TxChainRef): TxChainGasLimits =
## Getter
dh.limits
func lhwm*(dh: TxChainRef): TxChainGasLimitsPc =
## Getter
dh.lhwm
func maxMode*(dh: TxChainRef): bool =
## Getter
dh.maxMode
func feeRecipient*(dh: TxChainRef): EthAddress =
## Getter
dh.com.pos.feeRecipient
@ -300,24 +266,6 @@ proc `head=`*(dh: TxChainRef; val: BlockHeader)
## account caches to a new insertion point on the block chain database.
dh.update(val)
func `lhwm=`*(dh: TxChainRef; val: TxChainGasLimitsPc) =
## Setter, tuple `(lwmTrg,hwmMax)` will allow the packer to continue
## up until the percentage level has been reached of the `trgLimit`, or
## `maxLimit` depending on what has been activated.
if dh.lhwm != val:
dh.lhwm = val
let parent = dh.txEnv.vmState.parent
dh.limits = dh.com.gasLimitsGet(parent, dh.limits.gasLimit, dh.lhwm)
dh.txEnv.vmState.blockCtx.gasLimit = if dh.maxMode: dh.limits.maxLimit
else: dh.limits.trgLimit
func `maxMode=`*(dh: TxChainRef; val: bool) =
## Setter, the packing mode (maximal or target limit) for the next block
## header
dh.maxMode = val
dh.txEnv.vmState.blockCtx.gasLimit = if dh.maxMode: dh.limits.maxLimit
else: dh.limits.trgLimit
func `profit=`*(dh: TxChainRef; val: UInt256) =
## Setter
dh.txEnv.profit = val

View File

@ -13,7 +13,6 @@
##
import
std/[math],
../../../common/common,
../../../constants,
../../pow/header,
@ -21,110 +20,25 @@ import
{.push raises: [].}
type
TxChainGasLimitsPc* = tuple
lwmTrg: int ##\
## VM executor may stop if this per centage of `trgLimit` has
## been reached.
hwmMax: int ##\
## VM executor may stop if this per centage of `maxLimit` has
## been reached.
gasFloor: GasInt
## minimum desired gas limit
gasCeil: GasInt
## maximum desired gas limit
TxChainGasLimits* = tuple
gasLimit: GasInt ## Parent gas limit, used as a base for others
minLimit: GasInt ## Minimum `gasLimit` for the packer
lwmLimit: GasInt ## Low water mark for VM/exec packer
trgLimit: GasInt ## The `gasLimit` for the packer, soft limit
hwmLimit: GasInt ## High water mark for VM/exec packer
maxLimit: GasInt ## May increase the `gasLimit` a bit, hard limit
const
PRE_LONDON_GAS_LIMIT_TRG = ##\
## https://ethereum.org/en/developers/docs/blocks/#block-size
15_000_000.GasInt
PRE_LONDON_GAS_LIMIT_MAX = ##\
## https://ethereum.org/en/developers/docs/blocks/#block-size
30_000_000.GasInt
# ------------------------------------------------------------------------------
# Private functions
# ------------------------------------------------------------------------------
proc setPostLondonLimits(gl: var TxChainGasLimits) =
## EIP-1559 conformant gas limit update
gl.trgLimit = max(gl.gasLimit, GAS_LIMIT_MINIMUM)
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
# find in box: block.gas_used
let delta = gl.trgLimit.floorDiv(GAS_LIMIT_ADJUSTMENT_FACTOR)
gl.minLimit = gl.trgLimit + delta
gl.maxLimit = gl.trgLimit - delta
# Fringe case: use the middle between min/max
if gl.minLimit <= GAS_LIMIT_MINIMUM:
gl.minLimit = GAS_LIMIT_MINIMUM
gl.trgLimit = (gl.minLimit + gl.maxLimit) div 2
proc setPreLondonLimits(gl: var TxChainGasLimits) =
## Pre-EIP-1559 conformant gas limit update
gl.maxLimit = PRE_LONDON_GAS_LIMIT_MAX
const delta = (PRE_LONDON_GAS_LIMIT_TRG - GAS_LIMIT_MINIMUM) div 2
# Just made up to be convenient for the packer
if gl.gasLimit <= GAS_LIMIT_MINIMUM + delta:
gl.minLimit = max(gl.gasLimit, GAS_LIMIT_MINIMUM)
gl.trgLimit = PRE_LONDON_GAS_LIMIT_TRG
else:
# This setting preserves the setting from the parent block
gl.minLimit = gl.gasLimit - delta
gl.trgLimit = gl.gasLimit
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
proc gasLimitsGet*(com: CommonRef; parent: BlockHeader; parentLimit: GasInt;
pc: TxChainGasLimitsPc): TxChainGasLimits =
## Calculate gas limits for the next block header.
result.gasLimit = parentLimit
proc gasLimitsGet*(com: CommonRef;
parent: BlockHeader): GasInt =
if com.isLondonOrLater(parent.number+1):
result.setPostLondonLimits
else:
result.setPreLondonLimits
# VM/exec low/high water marks, optionally provided for packer
result.lwmLimit = max(
result.minLimit, (result.trgLimit * pc.lwmTrg.GasInt + 50) div 100)
result.hwmLimit = max(
result.trgLimit, (result.maxLimit * pc.hwmMax.GasInt + 50) div 100)
# override trgLimit, see https://github.com/status-im/nimbus-eth1/issues/1032
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
result.trgLimit = calcGasLimit1559(parentGasLimit, desiredLimit = pc.gasCeil)
calcGasLimit1559(parentGasLimit, desiredLimit = DEFAULT_GAS_LIMIT)
else:
result.trgLimit = computeGasLimit(
computeGasLimit(
parent.gasUsed,
parent.gasLimit,
gasFloor = pc.gasFloor,
gasCeil = pc.gasCeil)
proc gasLimitsGet*(com: CommonRef; parent: BlockHeader;
pc: TxChainGasLimitsPc): TxChainGasLimits =
## Variant of `gasLimitsGet()`
com.gasLimitsGet(parent, parent.gasLimit, pc)
gasFloor = DEFAULT_GAS_LIMIT,
gasCeil = DEFAULT_GAS_LIMIT)
# ------------------------------------------------------------------------------
# End

View File

@ -95,7 +95,7 @@ proc txNonceActive(xp: TxPoolRef; item: TxItemRef): bool
proc txGasCovered(xp: TxPoolRef; item: TxItemRef): bool =
## Check whether the max gas consumption is within the gas limit (aka block
## size).
let trgLimit = xp.chain.limits.trgLimit
let trgLimit = xp.chain.gasLimit
if trgLimit < item.tx.gasLimit:
debug "invalid tx: gasLimit exceeded",
maxLimit = trgLimit,
@ -227,10 +227,7 @@ proc classifyValidatePacked*(xp: TxPoolRef;
roDB = vmState.readOnlyStateDB
baseFee = xp.chain.baseFee.uint64.u256
fork = xp.chain.nextFork
gasLimit = if packItemsMaxGasLimit in xp.pFlags:
xp.chain.limits.maxLimit
else:
xp.chain.limits.trgLimit
gasLimit = xp.chain.gasLimit
tx = item.tx.eip1559TxNormalization(xp.chain.baseFee.GasInt)
excessBlobGas = calcExcessBlobGas(vmState.parent)
@ -242,10 +239,7 @@ proc classifyPacked*(xp: TxPoolRef; gasBurned, moreBurned: GasInt): bool =
## in the VM.) This function checks whether the sum of the arguments
## `gasBurned` and `moreGasBurned` is within acceptable constraints.
let totalGasUsed = gasBurned + moreBurned
if packItemsMaxGasLimit in xp.pFlags:
totalGasUsed < xp.chain.limits.maxLimit
else:
totalGasUsed < xp.chain.limits.trgLimit
totalGasUsed < xp.chain.gasLimit
proc classifyPackedNext*(xp: TxPoolRef; gasBurned, moreBurned: GasInt): bool =
## Classifier for *packing* (i.e. adding up `gasUsed` values after executing
@ -256,10 +250,8 @@ proc classifyPackedNext*(xp: TxPoolRef; gasBurned, moreBurned: GasInt): bool =
## `classifyPack()`.
if packItemsTryHarder notin xp.pFlags:
xp.classifyPacked(gasBurned, moreBurned)
elif packItemsMaxGasLimit in xp.pFlags:
gasBurned < xp.chain.limits.hwmLimit
else:
gasBurned < xp.chain.limits.lwmLimit
gasBurned < xp.chain.gasLimit
# ------------------------------------------------------------------------------
# Public functionss

View File

@ -150,8 +150,6 @@ proc vmExecInit(xp: TxPoolRef): Result[TxPackerStateRef, string]
# reset blockValue before adding any tx
xp.blockValue = 0.u256
xp.chain.maxMode = (packItemsMaxGasLimit in xp.pFlags)
if xp.chain.com.daoForkSupport and
xp.chain.com.daoForkBlock.get == xp.chain.head.number + 1:
xp.chain.vmState.mutateStateDB:

View File

@ -22,11 +22,8 @@ import
# to import `tx_pool/*` sup-modules
export
pp,
tx_chain.TxChainGasLimits,
tx_chain.`maxMode=`,
tx_chain.clearAccounts,
tx_chain.com,
tx_chain.limits,
tx_chain.nextFork,
tx_chain.profit,
tx_chain.receipts,
@ -175,11 +172,6 @@ proc pp*(w: TxTabsItemsCount): string =
proc pp*(w: TxTabsGasTotals): string =
&"{w.pending}/{w.staged}/{w.packed}"
proc pp*(w: TxChainGasLimits): string =
&"min={w.minLimit}" &
&" trg={w.lwmLimit}:{w.trgLimit}" &
&" max={w.hwmLimit}:{w.maxLimit}"
# ------------------------------------------------------------------------------
# Public functions, other
# ------------------------------------------------------------------------------