Refactor txpool: reduce complexity (#2542)
This commit is contained in:
parent
63d13182c1
commit
ec118a438a
|
@ -425,7 +425,6 @@ export
|
|||
TxItemStatus,
|
||||
TxPoolFlags,
|
||||
TxPoolRef,
|
||||
TxTabsGasTotals,
|
||||
TxTabsItemsCount,
|
||||
results,
|
||||
tx_desc.startDate,
|
||||
|
@ -644,10 +643,6 @@ proc assembleBlock*(
|
|||
blk: blk,
|
||||
blobsBundle: blobsBundleOpt)
|
||||
|
||||
func gasTotals*(xp: TxPoolRef): TxTabsGasTotals =
|
||||
## Getter, retrieves the current gas limit totals per bucket.
|
||||
xp.txDB.gasTotals
|
||||
|
||||
func flags*(xp: TxPoolRef): set[TxPoolFlags] =
|
||||
## Getter, retrieves strategy symbols for how to process items and buckets.
|
||||
xp.pFlags
|
||||
|
|
|
@ -16,11 +16,9 @@ import
|
|||
std/[times],
|
||||
../../common/common,
|
||||
./tx_chain,
|
||||
./tx_info,
|
||||
./tx_item,
|
||||
./tx_tabs,
|
||||
./tx_tabs/tx_sender, # for verify()
|
||||
eth/keys
|
||||
./tx_tabs/tx_sender
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
|
@ -162,53 +160,6 @@ func `pFlags=`*(xp: TxPoolRef; val: set[TxPoolFlags]) =
|
|||
## Install a set of algorithm strategy symbols for labelling items as`packed`
|
||||
xp.param.flags = val
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions, heplers (debugging only)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc verify*(xp: TxPoolRef): Result[void,TxInfo]
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
## Verify descriptor and subsequent data structures.
|
||||
|
||||
block:
|
||||
let rc = xp.txDB.verify
|
||||
if rc.isErr:
|
||||
return rc
|
||||
|
||||
# verify consecutive nonces per sender
|
||||
var
|
||||
initOk = false
|
||||
lastSender: EthAddress
|
||||
lastNonce: AccountNonce
|
||||
lastSublist: TxSenderSchedRef
|
||||
|
||||
for (_,nonceList) in xp.txDB.incAccount:
|
||||
for item in nonceList.incNonce:
|
||||
if not initOk or lastSender != item.sender:
|
||||
initOk = true
|
||||
lastSender = item.sender
|
||||
lastNonce = item.tx.nonce
|
||||
lastSublist = xp.txDB.bySender.eq(item.sender).value.data
|
||||
elif lastNonce + 1 == item.tx.nonce:
|
||||
lastNonce = item.tx.nonce
|
||||
else:
|
||||
return err(txInfoVfyNonceChain)
|
||||
|
||||
# verify bucket boundary conditions
|
||||
case item.status:
|
||||
of txItemPending:
|
||||
discard
|
||||
of txItemStaged:
|
||||
if lastSublist.eq(txItemPending).eq(item.tx.nonce - 1).isOk:
|
||||
return err(txInfoVfyNonceChain)
|
||||
of txItemPacked:
|
||||
if lastSublist.eq(txItemPending).eq(item.tx.nonce - 1).isOk:
|
||||
return err(txInfoVfyNonceChain)
|
||||
if lastSublist.eq(txItemStaged).eq(item.tx.nonce - 1).isOk:
|
||||
return err(txInfoVfyNonceChain)
|
||||
|
||||
ok()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -20,12 +20,12 @@ import
|
|||
./tx_item,
|
||||
./tx_tabs/[tx_sender, tx_rank, tx_status],
|
||||
eth/[common, keys],
|
||||
stew/[keyed_queue, keyed_queue/kq_debug, sorted_set],
|
||||
stew/[keyed_queue, sorted_set],
|
||||
results
|
||||
|
||||
export
|
||||
# bySender/byStatus index operations
|
||||
sub, eq, ge, gt, le, len, lt, nItems, gasLimits
|
||||
sub, eq, ge, gt, le, len, lt, nItems
|
||||
|
||||
type
|
||||
TxTabsItemsCount* = tuple
|
||||
|
@ -33,9 +33,6 @@ type
|
|||
total: int ## excluding rejects
|
||||
disposed: int ## waste basket
|
||||
|
||||
TxTabsGasTotals* = tuple
|
||||
pending, staged, packed: GasInt ## sum => total
|
||||
|
||||
TxTabsRef* = ref object ##\
|
||||
## Base descriptor
|
||||
maxRejects: int ##\
|
||||
|
@ -284,11 +281,6 @@ proc nItems*(xp: TxTabsRef): TxTabsItemsCount =
|
|||
result.total = xp.byItemID.len
|
||||
result.disposed = xp.byRejects.len
|
||||
|
||||
proc gasTotals*(xp: TxTabsRef): TxTabsGasTotals =
|
||||
result.pending = xp.byStatus.eq(txItemPending).gasLimits
|
||||
result.staged = xp.byStatus.eq(txItemStaged).gasLimits
|
||||
result.packed = xp.byStatus.eq(txItemPacked).gasLimits
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public iterators, `TxRank` > `(EthAddress,TxStatusNonceRef)`
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -345,41 +337,6 @@ iterator packingOrderAccounts*(xp: TxTabsRef; bucket: TxItemStatus):
|
|||
for (account,nonceList) in xp.decAccount(bucket):
|
||||
yield (account,nonceList)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public iterators, `TxRank` > `(EthAddress,TxSenderNonceRef)`
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
iterator incAccount*(xp: TxTabsRef;
|
||||
fromRank = TxRank.low): (EthAddress,TxSenderNonceRef)
|
||||
{.gcsafe,raises: [KeyError].} =
|
||||
## Variant of `incAccount()` without bucket restriction.
|
||||
var rcRank = xp.byRank.ge(fromRank)
|
||||
while rcRank.isOk:
|
||||
let (rank, addrList) = (rcRank.value.key, rcRank.value.data)
|
||||
|
||||
# Try all sender adresses found
|
||||
for account in addrList.keys:
|
||||
yield (account, xp.bySender.eq(account).sub.value.data)
|
||||
|
||||
# Get next ranked address list (top down index walk)
|
||||
rcRank = xp.byRank.gt(rank) # potenially modified database
|
||||
|
||||
|
||||
iterator decAccount*(xp: TxTabsRef;
|
||||
fromRank = TxRank.high): (EthAddress,TxSenderNonceRef)
|
||||
{.gcsafe,raises: [KeyError].} =
|
||||
## Variant of `decAccount()` without bucket restriction.
|
||||
var rcRank = xp.byRank.le(fromRank)
|
||||
while rcRank.isOk:
|
||||
let (rank, addrList) = (rcRank.value.key, rcRank.value.data)
|
||||
|
||||
# Try all sender adresses found
|
||||
for account in addrList.keys:
|
||||
yield (account, xp.bySender.eq(account).sub.value.data)
|
||||
|
||||
# Get next ranked address list (top down index walk)
|
||||
rcRank = xp.byRank.lt(rank) # potenially modified database
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Public second stage iterators: nonce-ordered item lists.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
@ -404,84 +361,6 @@ iterator incNonce*(nonceList: TxStatusNonceRef;
|
|||
yield item
|
||||
rc = nonceList.gt(nonce) # potenially modified database
|
||||
|
||||
#[
|
||||
# There is currently no use for nonce count down traversal
|
||||
|
||||
iterator decNonce*(nonceList: TxSenderNonceRef;
|
||||
nonceFrom = AccountNonce.high): TxItemRef
|
||||
{.gcsafe, raises: [KeyError].} =
|
||||
## Similar to `incNonce()` but visiting items in reverse order.
|
||||
var rc = nonceList.le(nonceFrom)
|
||||
while rc.isOk:
|
||||
let (nonce, item) = (rc.value.key, rc.value.data)
|
||||
yield item
|
||||
rc = nonceList.lt(nonce) # potenially modified database
|
||||
|
||||
|
||||
iterator decNonce*(nonceList: TxStatusNonceRef;
|
||||
nonceFrom = AccountNonce.high): TxItemRef =
|
||||
## Variant of `decNonce()` for the `TxStatusNonceRef` list.
|
||||
var rc = nonceList.le(nonceFrom)
|
||||
while rc.isOk:
|
||||
let (nonce, item) = (rc.value.key, rc.value.data)
|
||||
yield item
|
||||
rc = nonceList.lt(nonce) # potenially modified database
|
||||
]#
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions, debugging
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
proc verify*(xp: TxTabsRef): Result[void,TxInfo]
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
## Verify descriptor and subsequent data structures.
|
||||
block:
|
||||
let rc = xp.bySender.verify
|
||||
if rc.isErr:
|
||||
return rc
|
||||
block:
|
||||
let rc = xp.byItemID.verify
|
||||
if rc.isErr:
|
||||
return err(txInfoVfyItemIdList)
|
||||
block:
|
||||
let rc = xp.byRejects.verify
|
||||
if rc.isErr:
|
||||
return err(txInfoVfyRejectsList)
|
||||
block:
|
||||
let rc = xp.byStatus.verify
|
||||
if rc.isErr:
|
||||
return rc
|
||||
block:
|
||||
let rc = xp.byRank.verify
|
||||
if rc.isErr:
|
||||
return rc
|
||||
|
||||
for status in TxItemStatus:
|
||||
var
|
||||
statusCount = 0
|
||||
statusAllGas = 0.GasInt
|
||||
for (account,nonceList) in xp.incAccount(status):
|
||||
let bySenderStatusList = xp.bySender.eq(account).eq(status)
|
||||
statusAllGas += bySenderStatusList.gasLimits
|
||||
statusCount += bySenderStatusList.nItems
|
||||
if bySenderStatusList.nItems != nonceList.nItems:
|
||||
return err(txInfoVfyStatusSenderTotal)
|
||||
|
||||
if xp.byStatus.eq(status).nItems != statusCount:
|
||||
return err(txInfoVfyStatusSenderTotal)
|
||||
if xp.byStatus.eq(status).gasLimits != statusAllGas:
|
||||
return err(txInfoVfyStatusSenderGasLimits)
|
||||
|
||||
if xp.byItemID.len != xp.bySender.nItems:
|
||||
return err(txInfoVfySenderTotal)
|
||||
|
||||
if xp.byItemID.len != xp.byStatus.nItems:
|
||||
return err(txInfoVfyStatusTotal)
|
||||
|
||||
if xp.bySender.len != xp.byRank.nItems:
|
||||
return err(txInfoVfyRankTotal)
|
||||
ok()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
import
|
||||
std/[tables],
|
||||
../tx_info,
|
||||
eth/common,
|
||||
stew/[sorted_set],
|
||||
results
|
||||
|
@ -111,36 +110,6 @@ proc delete*(rt: var TxRankTab; sender: EthAddress): bool
|
|||
rt.addrTab.del(sender)
|
||||
return true
|
||||
|
||||
|
||||
proc verify*(rt: var TxRankTab): Result[void,TxInfo]
|
||||
{.gcsafe,raises: [CatchableError].} =
|
||||
|
||||
var
|
||||
seen: Table[EthAddress,TxRank]
|
||||
rc = rt.rankList.ge(TxRank.low)
|
||||
|
||||
while rc.isOk:
|
||||
let (key, addrTab) = (rc.value.key, rc.value.data)
|
||||
rc = rt.rankList.gt(key)
|
||||
|
||||
for (sender,rank) in addrTab.pairs:
|
||||
if key != rank:
|
||||
return err(txInfoVfyRankAddrMismatch)
|
||||
|
||||
if not rt.addrTab.hasKey(sender):
|
||||
return err(txInfoVfyRankReverseLookup)
|
||||
if rank != rt.addrTab[sender]:
|
||||
return err(txInfoVfyRankReverseMismatch)
|
||||
|
||||
if seen.hasKey(sender):
|
||||
return err(txInfoVfyRankDuplicateAddr)
|
||||
seen[sender] = rank
|
||||
|
||||
if seen.len != rt.addrTab.len:
|
||||
return err(txInfoVfyReverseZombies)
|
||||
|
||||
ok()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions: `TxRank` > `EthAddress`
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
##
|
||||
|
||||
import
|
||||
../tx_info,
|
||||
../tx_item,
|
||||
eth/common,
|
||||
stew/[keyed_queue, keyed_queue/kq_debug, sorted_set],
|
||||
stew/[keyed_queue, sorted_set],
|
||||
results,
|
||||
../../eip4844
|
||||
|
||||
|
@ -27,7 +26,7 @@ type
|
|||
## Sub-list ordered by `AccountNonce` values containing transaction\
|
||||
## item lists.
|
||||
gasLimits: GasInt ## Accumulated gas limits
|
||||
profit: float64 ## Aggregated `effectiveGasTip*gasLimit` values
|
||||
profit: GasInt ## Aggregated `effectiveGasTip*gasLimit` values
|
||||
nonceList: SortedSet[AccountNonce,TxItemRef]
|
||||
|
||||
TxSenderSchedRef* = ref object ##\
|
||||
|
@ -74,19 +73,6 @@ proc nActive(rq: TxSenderSchedRef): int =
|
|||
if not rq.statusList[status].isNil:
|
||||
result.inc
|
||||
|
||||
func differs(a, b: float64): bool =
|
||||
## Syntactic sugar, crude comparator for large integer values a and b coded
|
||||
## as `float64`. This function is mainly provided for the `verify()` function.
|
||||
# note that later NIM compilers also provide `almostEqual()`
|
||||
const
|
||||
epsilon = 1.0e+15'f64 # just arbitrary, something small
|
||||
let
|
||||
x = max(a, b)
|
||||
y = min(a, b)
|
||||
z = if x == 0: 1'f64 else: x # 1f64 covers the case x == y == 0.0
|
||||
epsilon < (x - y) / z
|
||||
|
||||
|
||||
func toSenderSchedule(status: TxItemStatus): TxSenderSchedule =
|
||||
case status
|
||||
of txItemPending:
|
||||
|
@ -109,23 +95,21 @@ proc getRank(schedData: TxSenderSchedRef): int64 =
|
|||
|
||||
if gasLimits <= 0:
|
||||
return int64.low
|
||||
let profit = maxProfit / gasLimits.float64
|
||||
let profit = maxProfit div gasLimits
|
||||
|
||||
# Beware of under/overflow
|
||||
if profit < int64.low.float64:
|
||||
return int64.low
|
||||
if int64.high.float64 < profit:
|
||||
if int64.high.GasInt < profit:
|
||||
return int64.high
|
||||
|
||||
profit.int64
|
||||
|
||||
proc maxProfit(item: TxItemRef; baseFee: GasInt): float64 =
|
||||
proc maxProfit(item: TxItemRef; baseFee: GasInt): GasInt =
|
||||
## Profit calculator
|
||||
item.tx.gasLimit.float64 * item.tx.effectiveGasTip(baseFee).float64 + item.tx.getTotalBlobGas.float64
|
||||
item.tx.gasLimit * item.tx.effectiveGasTip(baseFee) + item.tx.getTotalBlobGas
|
||||
|
||||
proc recalcProfit(nonceData: TxSenderNonceRef; baseFee: GasInt) =
|
||||
## Re-calculate profit value depending on `baseFee`
|
||||
nonceData.profit = 0.0
|
||||
nonceData.profit = 0
|
||||
var rc = nonceData.nonceList.ge(AccountNonce.low)
|
||||
while rc.isOk:
|
||||
let item = rc.value.data
|
||||
|
@ -252,116 +236,6 @@ proc delete*(gt: var TxSenderTab; item: TxItemRef): bool
|
|||
inx.statusNonce.profit -= tip
|
||||
return true
|
||||
|
||||
|
||||
proc verify*(gt: var TxSenderTab): Result[void,TxInfo]
|
||||
{.gcsafe,raises: [CatchableError].} =
|
||||
## Walk `EthAddress` > `TxSenderLocus` > `AccountNonce` > items
|
||||
|
||||
block:
|
||||
let rc = gt.addrList.verify
|
||||
if rc.isErr:
|
||||
return err(txInfoVfySenderRbTree)
|
||||
|
||||
var totalCount = 0
|
||||
for p in gt.addrList.nextPairs:
|
||||
let schedData = p.data
|
||||
#var addrCount = 0 -- notused
|
||||
# at least one of status lists must be available
|
||||
if schedData.nActive == 0:
|
||||
return err(txInfoVfySenderLeafEmpty)
|
||||
if schedData.allList.isNil:
|
||||
return err(txInfoVfySenderLeafEmpty)
|
||||
|
||||
# status list
|
||||
# ----------------------------------------------------------------
|
||||
var
|
||||
statusCount = 0
|
||||
statusGas = 0.GasInt
|
||||
statusProfit = 0.0
|
||||
for status in TxItemStatus:
|
||||
let statusData = schedData.statusList[status]
|
||||
|
||||
if not statusData.isNil:
|
||||
block:
|
||||
let rc = statusData.nonceList.verify
|
||||
if rc.isErr:
|
||||
return err(txInfoVfySenderRbTree)
|
||||
|
||||
var
|
||||
rcNonce = statusData.nonceList.ge(AccountNonce.low)
|
||||
bucketProfit = 0.0
|
||||
while rcNonce.isOk:
|
||||
let (nonceKey, item) = (rcNonce.value.key, rcNonce.value.data)
|
||||
rcNonce = statusData.nonceList.gt(nonceKey)
|
||||
|
||||
statusGas += item.tx.gasLimit
|
||||
statusCount.inc
|
||||
|
||||
bucketProfit += item.maxProfit(gt.baseFee)
|
||||
|
||||
statusProfit += bucketProfit
|
||||
|
||||
if differs(statusData.profit, bucketProfit):
|
||||
echo "*** verify (1) ", statusData.profit," != ", bucketProfit
|
||||
return err(txInfoVfySenderProfits)
|
||||
|
||||
# verify that `recalcProfit()` works
|
||||
statusData.recalcProfit(gt.baseFee)
|
||||
if differs(statusData.profit, bucketProfit):
|
||||
echo "*** verify (2) ", statusData.profit," != ", bucketProfit
|
||||
return err(txInfoVfySenderProfits)
|
||||
|
||||
# allList
|
||||
# ----------------------------------------------------------------
|
||||
var
|
||||
allCount = 0
|
||||
allGas = 0.GasInt
|
||||
allProfit = 0.0
|
||||
block:
|
||||
var allData = schedData.allList
|
||||
|
||||
block:
|
||||
let rc = allData.nonceList.verify
|
||||
if rc.isErr:
|
||||
return err(txInfoVfySenderRbTree)
|
||||
|
||||
var rcNonce = allData.nonceList.ge(AccountNonce.low)
|
||||
while rcNonce.isOk:
|
||||
let (nonceKey, item) = (rcNonce.value.key, rcNonce.value.data)
|
||||
rcNonce = allData.nonceList.gt(nonceKey)
|
||||
|
||||
allProfit += item.maxProfit(gt.baseFee)
|
||||
allGas += item.tx.gasLimit
|
||||
allCount.inc
|
||||
|
||||
if differs(allData.profit, allProfit):
|
||||
echo "*** verify (3) ", allData.profit," != ", allProfit
|
||||
return err(txInfoVfySenderProfits)
|
||||
|
||||
# verify that `recalcProfit()` works
|
||||
allData.recalcProfit(gt.baseFee)
|
||||
if differs(allData.profit, allProfit):
|
||||
echo "*** verify (4) ", allData.profit," != ", allProfit
|
||||
return err(txInfoVfySenderProfits)
|
||||
|
||||
if differs(allProfit, statusProfit):
|
||||
echo "*** verify (5) ", allProfit," != ", statusProfit
|
||||
return err(txInfoVfySenderProfits)
|
||||
if allGas != statusGas:
|
||||
return err(txInfoVfySenderTotal)
|
||||
if statusCount != schedData.size:
|
||||
return err(txInfoVfySenderTotal)
|
||||
if allCount != schedData.size:
|
||||
return err(txInfoVfySenderTotal)
|
||||
|
||||
totalCount += allCount
|
||||
|
||||
# end while
|
||||
if totalCount != gt.size:
|
||||
return err(txInfoVfySenderTotal)
|
||||
|
||||
ok()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public getters
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -508,38 +382,6 @@ proc nItems*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef]): int =
|
|||
return rc.value.data.nItems
|
||||
0
|
||||
|
||||
|
||||
proc gasLimits*(nonceData: TxSenderNonceRef): GasInt =
|
||||
## Getter, aggregated valued of `gasLimit` for all items in the
|
||||
## argument list.
|
||||
nonceData.gasLimits
|
||||
|
||||
proc gasLimits*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef]):
|
||||
GasInt =
|
||||
## Getter variant of `gasLimits()`, returns `0` if `rc.isErr`
|
||||
## evaluates `true`.
|
||||
if rc.isOk:
|
||||
return rc.value.data.gasLimits
|
||||
0
|
||||
|
||||
|
||||
proc maxProfit*(nonceData: TxSenderNonceRef): float64 =
|
||||
## Getter, maximum profit value for the current item list. This is the
|
||||
## aggregated value of `item.effectiveGasTip(baseFee) * item.gasLimit`
|
||||
## over all items in the argument list `nonceData`. Note that this value
|
||||
## is typically pretty large and sort of rounded due to the resolution
|
||||
## of the `float64` data type.
|
||||
nonceData.profit
|
||||
|
||||
proc maxProfit*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef]):
|
||||
float64 =
|
||||
## Variant of `profit()`
|
||||
## evaluates `true`.
|
||||
if rc.isOk:
|
||||
return rc.value.data.profit
|
||||
float64.low
|
||||
|
||||
|
||||
proc eq*(nonceData: TxSenderNonceRef; nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
nonceData.nonceList.eq(nonce)
|
||||
|
@ -575,30 +417,6 @@ proc gt*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef];
|
|||
return rc.value.data.gt(nonce)
|
||||
err(rc.error)
|
||||
|
||||
|
||||
proc le*(nonceData: TxSenderNonceRef; nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
nonceData.nonceList.le(nonce)
|
||||
|
||||
proc le*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef];
|
||||
nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
if rc.isOk:
|
||||
return rc.value.data.le(nonce)
|
||||
err(rc.error)
|
||||
|
||||
|
||||
proc lt*(nonceData: TxSenderNonceRef; nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
nonceData.nonceList.lt(nonce)
|
||||
|
||||
proc lt*(rc: SortedSetResult[TxSenderSchedule,TxSenderNonceRef];
|
||||
nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
if rc.isOk:
|
||||
return rc.value.data.lt(nonce)
|
||||
err(rc.error)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public iterators
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -13,10 +13,9 @@
|
|||
##
|
||||
|
||||
import
|
||||
../tx_info,
|
||||
../tx_item,
|
||||
eth/common,
|
||||
stew/[keyed_queue, keyed_queue/kq_debug, sorted_set],
|
||||
stew/[keyed_queue, sorted_set],
|
||||
results
|
||||
|
||||
{.push raises: [].}
|
||||
|
@ -30,7 +29,6 @@ type
|
|||
## Per address table. This table is provided as a keyed queue so deletion\
|
||||
## while traversing is supported and predictable.
|
||||
size: int ## Total number of items
|
||||
gasLimits: GasInt ## Accumulated gas limits
|
||||
addrList: KeyedQueue[EthAddress,TxStatusNonceRef]
|
||||
|
||||
TxStatusTab* = object ##\
|
||||
|
@ -121,7 +119,6 @@ proc insert*(sq: var TxStatusTab; item: TxItemRef): bool
|
|||
let inx = rc.value
|
||||
sq.size.inc
|
||||
inx.addrData.size.inc
|
||||
inx.addrData.gasLimits += item.tx.gasLimit
|
||||
return true
|
||||
|
||||
|
||||
|
@ -133,7 +130,6 @@ proc delete*(sq: var TxStatusTab; item: TxItemRef): bool
|
|||
|
||||
sq.size.dec
|
||||
inx.addrData.size.dec
|
||||
inx.addrData.gasLimits -= item.tx.gasLimit
|
||||
|
||||
discard inx.nonceData.nonceList.delete(item.tx.nonce)
|
||||
if inx.nonceData.nonceList.len == 0:
|
||||
|
@ -144,53 +140,6 @@ proc delete*(sq: var TxStatusTab; item: TxItemRef): bool
|
|||
|
||||
return true
|
||||
|
||||
|
||||
proc verify*(sq: var TxStatusTab): Result[void,TxInfo]
|
||||
{.gcsafe,raises: [CatchableError].} =
|
||||
## walk `TxItemStatus` > `EthAddress` > `AccountNonce`
|
||||
|
||||
var totalCount = 0
|
||||
for status in TxItemStatus:
|
||||
let addrData = sq.statusList[status]
|
||||
if not addrData.isNil:
|
||||
|
||||
block:
|
||||
let rc = addrData.addrList.verify
|
||||
if rc.isErr:
|
||||
return err(txInfoVfyStatusSenderList)
|
||||
var
|
||||
addrCount = 0
|
||||
gasLimits = 0.GasInt
|
||||
for p in addrData.addrList.nextPairs:
|
||||
# let (addrKey, nonceData) = (p.key, p.data) -- notused
|
||||
let nonceData = p.data
|
||||
|
||||
block:
|
||||
let rc = nonceData.nonceList.verify
|
||||
if rc.isErr:
|
||||
return err(txInfoVfyStatusNonceList)
|
||||
|
||||
var rcNonce = nonceData.nonceList.ge(AccountNonce.low)
|
||||
while rcNonce.isOk:
|
||||
let (nonceKey, item) = (rcNonce.value.key, rcNonce.value.data)
|
||||
rcNonce = nonceData.nonceList.gt(nonceKey)
|
||||
|
||||
gasLimits += item.tx.gasLimit
|
||||
addrCount.inc
|
||||
|
||||
if addrCount != addrData.size:
|
||||
return err(txInfoVfyStatusTotal)
|
||||
if gasLimits != addrData.gasLimits:
|
||||
return err(txInfoVfyStatusGasLimits)
|
||||
|
||||
totalCount += addrCount
|
||||
|
||||
# end while
|
||||
if totalCount != sq.size:
|
||||
return err(txInfoVfyStatusTotal)
|
||||
|
||||
ok()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public array ops -- `TxItemStatus` (level 0)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -222,17 +171,6 @@ proc nItems*(rc: SortedSetResult[TxItemStatus,TxStatusSenderRef]): int =
|
|||
return rc.value.data.nItems
|
||||
0
|
||||
|
||||
|
||||
proc gasLimits*(addrData: TxStatusSenderRef): GasInt =
|
||||
## Getter, accumulated `gasLimit` values
|
||||
addrData.gasLimits
|
||||
|
||||
proc gasLimits*(rc: SortedSetResult[TxItemStatus,TxStatusSenderRef]): GasInt =
|
||||
if rc.isOk:
|
||||
return rc.value.data.gasLimits
|
||||
0
|
||||
|
||||
|
||||
proc eq*(addrData: TxStatusSenderRef; sender: EthAddress):
|
||||
SortedSetResult[EthAddress,TxStatusNonceRef]
|
||||
{.gcsafe,raises: [KeyError].} =
|
||||
|
@ -297,28 +235,6 @@ proc gt*(rc: SortedSetResult[EthAddress,TxStatusNonceRef]; nonce: AccountNonce):
|
|||
return rc.value.data.gt(nonce)
|
||||
err(rc.error)
|
||||
|
||||
|
||||
proc le*(nonceData: TxStatusNonceRef; nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
nonceData.nonceList.le(nonce)
|
||||
|
||||
proc le*(rc: SortedSetResult[EthAddress,TxStatusNonceRef]; nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
if rc.isOk:
|
||||
return rc.value.data.le(nonce)
|
||||
err(rc.error)
|
||||
|
||||
|
||||
proc lt*(nonceData: TxStatusNonceRef; nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
nonceData.nonceList.lt(nonce)
|
||||
|
||||
proc lt*(rc: SortedSetResult[EthAddress,TxStatusNonceRef]; nonce: AccountNonce):
|
||||
SortedSetResult[AccountNonce,TxItemRef] =
|
||||
if rc.isOk:
|
||||
return rc.value.data.lt(nonce)
|
||||
err(rc.error)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# End
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -222,7 +222,7 @@ proc classifyValidatePacked*(xp: TxPoolRef;
|
|||
baseFee = xp.chain.baseFee.uint64.u256
|
||||
fork = xp.chain.nextFork
|
||||
gasLimit = xp.chain.gasLimit
|
||||
tx = item.tx.eip1559TxNormalization(xp.chain.baseFee.GasInt)
|
||||
tx = item.tx.eip1559TxNormalization(xp.chain.baseFee)
|
||||
excessBlobGas = calcExcessBlobGas(vmState.parent)
|
||||
|
||||
roDB.validateTransaction(
|
||||
|
|
|
@ -62,7 +62,7 @@ proc runTx(pst: TxPackerStateRef; item: TxItemRef): GasInt =
|
|||
## `gasUsed` after executing the transaction.
|
||||
let
|
||||
baseFee = pst.xp.chain.baseFee
|
||||
tx = item.tx.eip1559TxNormalization(baseFee.GasInt)
|
||||
tx = item.tx.eip1559TxNormalization(baseFee)
|
||||
|
||||
let gasUsed = tx.txCallEvm(item.sender, pst.xp.chain.vmState)
|
||||
pst.cleanState = false
|
||||
|
|
|
@ -28,7 +28,6 @@ export
|
|||
tx_chain.vmState,
|
||||
tx_desc.chain,
|
||||
tx_desc.txDB,
|
||||
tx_desc.verify,
|
||||
tx_packer.packerVmExec,
|
||||
tx_recover.recoverItem,
|
||||
tx_tabs.TxTabsRef,
|
||||
|
@ -36,7 +35,6 @@ export
|
|||
tx_tabs.dispose,
|
||||
tx_tabs.eq,
|
||||
tx_tabs.flushRejects,
|
||||
tx_tabs.gasLimits,
|
||||
tx_tabs.ge,
|
||||
tx_tabs.gt,
|
||||
tx_tabs.incAccount,
|
||||
|
@ -47,7 +45,6 @@ export
|
|||
tx_tabs.nItems,
|
||||
tx_tabs.reassign,
|
||||
tx_tabs.reject,
|
||||
tx_tabs.verify,
|
||||
undumpBlocksGz
|
||||
|
||||
const
|
||||
|
@ -165,9 +162,6 @@ proc pp*(txs: openArray[Transaction]; pfxLen: int): string =
|
|||
proc pp*(w: TxTabsItemsCount): string =
|
||||
&"{w.pending}/{w.staged}/{w.packed}:{w.total}/{w.disposed}"
|
||||
|
||||
proc pp*(w: TxTabsGasTotals): string =
|
||||
&"{w.pending}/{w.staged}/{w.packed}"
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions, other
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue