TxPool: Replace GasPrice and GasPriceEx with GasInt (#2537)

* TxPool: Replace GasPrice and GasPriceEx with GasInt
This commit is contained in:
andri lim 2024-07-31 14:33:30 +07:00 committed by GitHub
parent 947f629903
commit e331c9e9b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 23 additions and 214 deletions

View File

@ -288,20 +288,6 @@
## The `flags` parameter holds a set of strategy symbols for how to process ## The `flags` parameter holds a set of strategy symbols for how to process
## items and buckets. ## items and buckets.
## ##
## *stageItems1559MinFee*
## Stage tx items with `tx.maxFee` at least `minFeePrice`. Other items are
## left or set pending. This symbol affects post-London tx items, only.
##
## *stageItems1559MinTip*
## Stage tx items with `tx.effectiveGasTip(baseFee)` at least
## `minTipPrice`. Other items are considered underpriced and left or set
## pending. This symbol affects post-London tx items, only.
##
## *stageItemsPlMinPrice*
## Stage tx items with `tx.gasPrice` at least `minPreLondonGasPrice`.
## Other items are considered underpriced and left or set pending. This
## symbol affects pre-London tx items, only.
##
## *packItemsMaxGasLimit* ## *packItemsMaxGasLimit*
## It set, the *packer* will execute and collect additional items from ## It set, the *packer* will execute and collect additional items from
## the `staged` bucket while accumulating `gasUsed` as long as ## the `staged` bucket while accumulating `gasUsed` as long as
@ -351,11 +337,6 @@
## Applies no EIP-1559 txs only. Txs are packed if `maxFee` is at least ## Applies no EIP-1559 txs only. Txs are packed if `maxFee` is at least
## that value. ## that value.
## ##
## minTipPrice
## For EIP-1559, txs are packed if the expected tip (see `estimatedGasTip()`)
## is at least that value. In compatibility mode for legacy txs, this
## degenerates to `gasPrice - baseFee`.
##
## minPreLondonGasPrice ## minPreLondonGasPrice
## For pre-London or legacy txs, this parameter has precedence over ## For pre-London or legacy txs, this parameter has precedence over
## `minTipPrice`. Txs are packed if the `gasPrice` is at least that value. ## `minTipPrice`. Txs are packed if the `gasPrice` is at least that value.
@ -449,9 +430,6 @@ export
results, results,
tx_desc.startDate, tx_desc.startDate,
tx_info, tx_info,
tx_item.GasPrice,
tx_item.`<=`,
tx_item.`<`,
tx_item.effectiveGasTip, tx_item.effectiveGasTip,
tx_item.info, tx_item.info,
tx_item.itemID, tx_item.itemID,
@ -680,25 +658,6 @@ func head*(xp: TxPoolRef): BlockHeader =
## middle of a mining update.) ## middle of a mining update.)
xp.chain.head xp.chain.head
# 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
## transaction pool for txs to be packed. This is an EIP-1559 only
## parameter (see `stage1559MinFee` strategy.)
xp.pMinFeePrice
func minPreLondonGasPrice*(xp: TxPoolRef): GasPrice =
## Getter. retrieves, the current gas price enforced by the transaction
## pool. This is a pre-London parameter (see `packedPlMinPrice` strategy.)
xp.pMinPlGasPrice
func minTipPrice*(xp: TxPoolRef): GasPrice =
## Getter, retrieves minimum for the current gas tip (or priority fee)
## enforced by the transaction pool. This is an EIP-1559 parameter but it
## comes with a fall back interpretation (see `stage1559MinTip` strategy.)
## for legacy transactions.
xp.pMinTipPrice
# core/tx_pool.go(474): func (pool SetGasPrice,*TxPool) Stats() (int, int) { # core/tx_pool.go(474): func (pool SetGasPrice,*TxPool) Stats() (int, int) {
# core/tx_pool.go(1728): func (t *txLookup) Count() int { # core/tx_pool.go(1728): func (t *txLookup) Count() int {
# core/tx_pool.go(1737): func (t *txLookup) LocalCount() int { # core/tx_pool.go(1737): func (t *txLookup) LocalCount() int {
@ -730,30 +689,6 @@ func `maxRejects=`*(xp: TxPoolRef; val: int) =
## the next move of an item into the waste basket. ## the next move of an item into the waste basket.
xp.txDB.maxRejects = val xp.txDB.maxRejects = val
# core/tx_pool.go(444): func (pool *TxPool) SetGasPrice(price *big.Int) {
func `minFeePrice=`*(xp: TxPoolRef; val: GasPrice) =
## Setter for `minFeePrice`. If there was a value change, this function
## implies `triggerReorg()`.
if xp.pMinFeePrice != val:
xp.pMinFeePrice = val
xp.pDirtyBuckets = true
# core/tx_pool.go(444): func (pool *TxPool) SetGasPrice(price *big.Int) {
func `minPreLondonGasPrice=`*(xp: TxPoolRef; val: GasPrice) =
## Setter for `minPlGasPrice`. If there was a value change, this function
## implies `triggerReorg()`.
if xp.pMinPlGasPrice != val:
xp.pMinPlGasPrice = val
xp.pDirtyBuckets = true
# core/tx_pool.go(444): func (pool *TxPool) SetGasPrice(price *big.Int) {
func `minTipPrice=`*(xp: TxPoolRef; val: GasPrice) =
## Setter for `minTipPrice`. If there was a value change, this function
## implies `triggerReorg()`.
if xp.pMinTipPrice != val:
xp.pMinTipPrice = val
xp.pDirtyBuckets = true
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public functions, per-tx-item operations # Public functions, per-tx-item operations
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -25,29 +25,9 @@ import
{.push raises: [].} {.push raises: [].}
type type
TxPoolCallBackRecursion* = object of Defect
## Attempt to recurse a call back function
TxPoolFlags* = enum ##\ TxPoolFlags* = enum ##\
## Processing strategy selector symbols ## Processing strategy selector symbols
stageItems1559MinFee ##\
## Stage tx items with `tx.maxFee` at least `minFeePrice`. Other items
## are left or set pending. This symbol affects post-London tx items,
## only.
stageItems1559MinTip ##\
## Stage tx items with `tx.effectiveGasTip(baseFee)` at least
## `minTipPrice`. Other items are considered underpriced and left
## or set pending. This symbol affects post-London tx items, only.
stageItemsPlMinPrice ##\
## Stage tx items with `tx.gasPrice` at least `minPreLondonGasPrice`.
## Other items are considered underpriced and left or set pending.
## This symbol affects pre-London tx items, only.
# -----------
packItemsMaxGasLimit ##\ packItemsMaxGasLimit ##\
## It set, the *packer* will execute and collect additional items from ## It set, the *packer* will execute and collect additional items from
## the `staged` bucket while accumulating `gasUsed` as long as ## the `staged` bucket while accumulating `gasUsed` as long as
@ -81,9 +61,6 @@ type
## at least `lifeTime` ago. ## at least `lifeTime` ago.
TxPoolParam* = tuple ## Getter/setter accessible parameters TxPoolParam* = tuple ## Getter/setter accessible parameters
minFeePrice: GasPrice ## Gas price enforced by the pool, `gasFeeCap`
minTipPrice: GasPrice ## Desired tip-per-tx target, `effectiveGasTip`
minPlGasPrice: GasPrice ## Desired pre-London min `gasPrice`
dirtyBuckets: bool ## Buckets need to be updated dirtyBuckets: bool ## Buckets need to be updated
doubleCheck: seq[TxItemRef] ## Check items after moving block chain head doubleCheck: seq[TxItemRef] ## Check items after moving block chain head
flags: set[TxPoolFlags] ## Processing strategy symbols flags: set[TxPoolFlags] ## Processing strategy symbols
@ -114,12 +91,7 @@ const
## core/tx_pool.go(177) of the geth implementation. ## core/tx_pool.go(177) of the geth implementation.
10u 10u
txMinFeePrice = 1.GasPrice txPoolFlags = {packItemsTryHarder,
txMinTipPrice = 1.GasPrice
txPoolFlags = {stageItems1559MinTip,
stageItems1559MinFee,
stageItemsPlMinPrice,
packItemsTryHarder,
autoUpdateBucketsDB, autoUpdateBucketsDB,
autoZombifyUnpacked} autoZombifyUnpacked}
@ -139,8 +111,6 @@ proc init*(xp: TxPoolRef; com: CommonRef)
xp.priceBump = txPriceBump xp.priceBump = txPriceBump
xp.param.reset xp.param.reset
xp.param.minFeePrice = txMinFeePrice
xp.param.minTipPrice = txMinTipPrice
xp.param.flags = txPoolFlags xp.param.flags = txPoolFlags
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -164,18 +134,6 @@ func pDoubleCheck*(xp: TxPoolRef): seq[TxItemRef] =
## Getter, cached block chain head was moved back ## Getter, cached block chain head was moved back
xp.param.doubleCheck xp.param.doubleCheck
func pMinFeePrice*(xp: TxPoolRef): GasPrice =
## Getter
xp.param.minFeePrice
func pMinTipPrice*(xp: TxPoolRef): GasPrice =
## Getter
xp.param.minTipPrice
func pMinPlGasPrice*(xp: TxPoolRef): GasPrice =
## Getter
xp.param.minPlGasPrice
func startDate*(xp: TxPoolRef): Time = func startDate*(xp: TxPoolRef): Time =
## Getter ## Getter
xp.startDate xp.startDate
@ -204,18 +162,6 @@ func `pFlags=`*(xp: TxPoolRef; val: set[TxPoolFlags]) =
## Install a set of algorithm strategy symbols for labelling items as`packed` ## Install a set of algorithm strategy symbols for labelling items as`packed`
xp.param.flags = val xp.param.flags = val
func `pMinFeePrice=`*(xp: TxPoolRef; val: GasPrice) =
## Setter
xp.param.minFeePrice = val
func `pMinTipPrice=`*(xp: TxPoolRef; val: GasPrice) =
## Setter
xp.param.minTipPrice = val
func `pMinPlGasPrice=`*(xp: TxPoolRef; val: GasPrice) =
## Setter
xp.param.minPlGasPrice = val
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public functions, heplers (debugging only) # Public functions, heplers (debugging only)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -16,6 +16,7 @@ import
std/[hashes, times], std/[hashes, times],
../../utils/ec_recover, ../../utils/ec_recover,
../../utils/utils, ../../utils/utils,
../../transaction,
./tx_info, ./tx_info,
eth/[common, keys], eth/[common, keys],
results results
@ -23,16 +24,6 @@ import
{.push raises: [].} {.push raises: [].}
type type
GasPrice* = ##|
## Handy definition distinct from `GasInt` which is a commodity unit while
## the `GasPrice` is the commodity valuation per unit of gas, similar to a
## kind of currency.
distinct uint64
GasPriceEx* = ##\
## Similar to `GasPrice` but is allowed to be negative.
distinct int64
TxItemStatus* = enum ##\ TxItemStatus* = enum ##\
## Current status of a transaction as seen by the pool. ## Current status of a transaction as seen by the pool.
txItemPending = 0 txItemPending = 0
@ -57,50 +48,6 @@ type
proc utcTime: Time = proc utcTime: Time =
getTime().utc.toTime getTime().utc.toTime
# ------------------------------------------------------------------------------
# Public helpers supporting distinct types
# ------------------------------------------------------------------------------
proc `$`*(a: GasPrice): string {.borrow.}
proc `<`*(a, b: GasPrice): bool {.borrow.}
proc `<=`*(a, b: GasPrice): bool {.borrow.}
proc `==`*(a, b: GasPrice): bool {.borrow.}
proc `+`*(a, b: GasPrice): GasPrice {.borrow.}
proc `-`*(a, b: GasPrice): GasPrice {.borrow.}
proc `$`*(a: GasPriceEx): string {.borrow.}
proc `<`*(a, b: GasPriceEx): bool {.borrow.}
proc `<=`*(a, b: GasPriceEx): bool {.borrow.}
proc `==`*(a, b: GasPriceEx): bool {.borrow.}
proc `+`*(a, b: GasPriceEx): GasPriceEx {.borrow.}
proc `-`*(a, b: GasPriceEx): GasPriceEx {.borrow.}
proc `+=`*(a: var GasPriceEx; b: GasPriceEx) {.borrow.}
proc `-=`*(a: var GasPriceEx; b: GasPriceEx) {.borrow.}
# Multiplication/division of *price* and *commodity unit*
proc `*`*(a: GasPrice; b: SomeUnsignedInt): GasPrice {.borrow.}
proc `*`*(a: SomeUnsignedInt; b: GasPrice): GasPrice {.borrow.}
proc `div`*(a: GasPrice; b: SomeUnsignedInt): GasPrice =
(a.uint64 div b).GasPrice # beware of zero denominator
proc `*`*(a: SomeInteger; b: GasPriceEx): GasPriceEx =
(a * b.int64).GasPriceEx # beware of under/overflow
# Mixed stuff, convenience ops
proc `-`*(a: GasPrice; b: SomeUnsignedInt): GasPrice {.borrow.}
proc `<`*(a: GasPriceEx; b: SomeSignedInt): bool =
a.int64 < b
proc `<`*(a: GasPriceEx|SomeSignedInt; b: GasPrice): bool =
if a.int64 < 0: true else: a.GasPrice < b
proc `<=`*(a: SomeSignedInt; b: GasPriceEx): bool =
a < b.int64
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public functions, Constructor # Public functions, Constructor
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -159,20 +106,8 @@ proc cost*(tx: Transaction): UInt256 =
## Getter (go/ref compat): gas * gasPrice + value. ## Getter (go/ref compat): gas * gasPrice + value.
(tx.gasPrice * tx.gasLimit).u256 + tx.value (tx.gasPrice * tx.gasLimit).u256 + tx.value
# core/types/transaction.go(332): .. *Transaction) EffectiveGasTip(baseFee .. func effectiveGasTip*(tx: Transaction; baseFee: GasInt): GasInt =
# core/types/transaction.go(346): .. EffectiveGasTipValue(baseFee .. effectiveGasTip(tx, Opt.some(baseFee.u256))
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).GasPriceEx
else:
# London, EIP1559
min(tx.maxPriorityFeePerGas, tx.maxFeePerGas - baseFee).GasPriceEx
proc effectiveGasTip*(tx: Transaction; baseFee: UInt256): GasPriceEx =
## Variant of `effectiveGasTip()`
tx.effectiveGasTip(baseFee.truncate(GasInt))
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public functions, item getters # Public functions, item getters

View File

@ -22,7 +22,6 @@ import
results, results,
../../eip4844 ../../eip4844
type type
TxSenderNonceRef* = ref object ##\ TxSenderNonceRef* = ref object ##\
## Sub-list ordered by `AccountNonce` values containing transaction\ ## Sub-list ordered by `AccountNonce` values containing transaction\
@ -534,7 +533,7 @@ proc maxProfit*(nonceData: TxSenderNonceRef): float64 =
proc maxProfit*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef]): proc maxProfit*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef]):
float64 = float64 =
## Variant of `profit()`, returns `GasPriceEx.low` if `rc.isErr` ## Variant of `profit()`
## evaluates `true`. ## evaluates `true`.
if rc.isOk: if rc.isOk:
return rc.value.data.profit return rc.value.data.profit

View File

@ -25,7 +25,7 @@ import
chronicles, chronicles,
eth/keys eth/keys
import ../../../transaction except GasPrice, GasPriceEx # already in tx_item import ../../../transaction
{.push raises: [].} {.push raises: [].}
@ -148,27 +148,21 @@ proc txPreLondonAcceptableGasPrice(xp: TxPoolRef; item: TxItemRef): bool =
## For legacy transactions check whether minimum gas price and tip are ## For legacy transactions check whether minimum gas price and tip are
## high enough. These checks are optional. ## high enough. These checks are optional.
if item.tx.txType < TxEip1559: if item.tx.txType < TxEip1559:
if item.tx.gasPrice < 0:
if stageItemsPlMinPrice in xp.pFlags:
if item.tx.gasPrice.GasPriceEx < xp.pMinPlGasPrice:
return false return false
elif stageItems1559MinTip in xp.pFlags:
# Fall back transaction selector scheme # Fall back transaction selector scheme
if item.tx.effectiveGasTip(xp.chain.baseFee) < xp.pMinTipPrice: if item.tx.effectiveGasTip(xp.chain.baseFee) < 1.GasInt:
return false return false
true true
proc txPostLondonAcceptableTipAndFees(xp: TxPoolRef; item: TxItemRef): bool = proc txPostLondonAcceptableTipAndFees(xp: TxPoolRef; item: TxItemRef): bool =
## Helper for `classifyTxPacked()` ## Helper for `classifyTxPacked()`
if item.tx.txType >= TxEip1559: if item.tx.txType >= TxEip1559:
if item.tx.effectiveGasTip(xp.chain.baseFee) < 1.GasInt:
if stageItems1559MinTip in xp.pFlags:
if item.tx.effectiveGasTip(xp.chain.baseFee) < xp.pMinTipPrice:
return false return false
if stageItems1559MinFee in xp.pFlags: if item.tx.maxFeePerGas < 1.GasInt:
if item.tx.maxFeePerGas.GasPriceEx < xp.pMinFeePrice:
return false return false
true true
@ -197,7 +191,7 @@ proc classifyActive*(xp: TxPoolRef; item: TxItemRef): bool
if not xp.txNonceActive(item): if not xp.txNonceActive(item):
return false return false
if item.tx.effectiveGasTip(xp.chain.baseFee) <= 0.GasPriceEx: if item.tx.effectiveGasTip(xp.chain.baseFee) <= 0.GasInt:
return false return false
if not xp.txGasCovered(item): if not xp.txGasCovered(item):

View File

@ -52,7 +52,7 @@ var
statCount: array[TxItemStatus,int] # per status bucket statCount: array[TxItemStatus,int] # per status bucket
txList: seq[TxItemRef] txList: seq[TxItemRef]
effGasTips: seq[GasPriceEx] effGasTips: seq[GasPrice]
# Running block chain # Running block chain
bcCom: CommonRef bcCom: CommonRef
@ -484,16 +484,16 @@ proc runTxPackerTests(noisy = true) =
test "Calculate some non-trivial base fee": test "Calculate some non-trivial base fee":
var var
feesList = SortedSet[GasPriceEx,bool].init() feesList = SortedSet[GasPrice,bool].init()
# provide a sorted list of gas fees # provide a sorted list of gas fees
for item in txList: for item in txList:
discard feesList.insert(item.tx.effectiveGasTip(0.GasPrice)) discard feesList.insert(item.tx.effectiveGasTip(0.GasPrice))
let let
minKey = max(0, feesList.ge(GasPriceEx.low).value.key.int64) minKey = max(0, feesList.ge(GasPrice.low).value.key.int64)
lowKey = feesList.gt(minKey.GasPriceEx).value.key.uint64 lowKey = feesList.gt(minKey.GasPrice).value.key.uint64
highKey = feesList.le(GasPriceEx.high).value.key.uint64 highKey = feesList.le(GasPrice.high).value.key.uint64
keyRange = highKey - lowKey keyRange = highKey - lowKey
keyStep = max(1u64, keyRange div 500_000) keyStep = max(1u64, keyRange div 500_000)
@ -505,7 +505,7 @@ proc runTxPackerTests(noisy = true) =
# the following might throw an exception if the table is de-generated # the following might throw an exception if the table is de-generated
var nextKey = ntBaseFee var nextKey = ntBaseFee
for _ in [1, 2, 3]: for _ in [1, 2, 3]:
let rcNextKey = feesList.gt(nextKey.GasPriceEx) let rcNextKey = feesList.gt(nextKey.GasPrice)
check rcNextKey.isOk check rcNextKey.isOk
nextKey = rcNextKey.value.key.uint64.GasPrice nextKey = rcNextKey.value.key.uint64.GasPrice