nimbus-eth1/nimbus/utils/tx_pool/tx_tasks/tx_dispose.nim

125 lines
4.1 KiB
Nim

# 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 Tasklet: Dispose expired items
## ===============================================
##
import
std/[times],
../tx_desc,
../tx_gauge,
../tx_info,
../tx_item,
../tx_tabs,
chronicles,
eth/[common, keys],
stew/keyed_queue
{.push raises: [Defect].}
logScope:
topics = "tx-pool dispose expired"
# ------------------------------------------------------------------------------
# Private functions
# ------------------------------------------------------------------------------
proc utcNow: Time =
getTime().utc.toTime
#proc pp(t: Time): string =
# t.format("yyyy-MM-dd'T'HH:mm:ss'.'fff", utc())
# ------------------------------------------------------------------------------
# Private functions
# ------------------------------------------------------------------------------
proc deleteOtherNonces(xp: TxPoolRef; item: TxItemRef; newerThan: Time): bool
{.gcsafe,raises: [Defect,KeyError].} =
let rc = xp.txDB.bySender.eq(item.sender).any
if rc.isOk:
for other in rc.value.data.incNonce(item.tx.nonce):
# only delete non-expired items
if newerThan < other.timeStamp:
discard xp.txDB.dispose(other, txInfoErrTxExpiredImplied)
impliedEvictionMeter.inc
result = true
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
# core/tx_pool.go(384): for addr := range pool.queue {
proc disposeExpiredItems*(xp: TxPoolRef) {.gcsafe,raises: [Defect,KeyError].} =
## Any non-local transaction old enough will be removed. This will not
## apply to items in the packed queue.
let
deadLine = utcNow() - xp.lifeTime
dspPacked = autoZombifyPacked in xp.pFlags
dspUnpacked = autoZombifyUnpacked in xp.pFlags
var rc = xp.txDB.byItemID.first
while rc.isOk:
let (key, item) = (rc.value.key, rc.value.data)
if deadLine < item.timeStamp:
break
rc = xp.txDB.byItemID.next(key)
if item.status == txItemPacked:
if not dspPacked:
continue
else:
if not dspUnpacked:
continue
# 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):
if rc.isOk:
# If one of the "other" just deleted items was the "next(key)", the
# loop would have stooped anyway at the "if deadLine < item.timeStamp:"
# clause at the while() loop header.
if not xp.txDB.byItemID.hasKey(rc.value.key):
break
proc disposeItemAndHigherNonces*(xp: TxPoolRef; item: TxItemRef;
reason, otherReason: TxInfo): int
{.gcsafe,raises: [Defect,CatchableError].} =
## Move item and higher nonces per sender to wastebasket.
if xp.txDB.dispose(item, reason):
result = 1
# For the current sender, delete all items with higher nonces
let rc = xp.txDB.bySender.eq(item.sender).any
if rc.isOk:
let nonceList = rc.value.data
for otherItem in nonceList.incNonce(item.tx.nonce):
if xp.txDB.dispose(otherItem, otherReason):
result.inc
proc disposeById*(xp: TxPoolRef; itemIDs: openArray[Hash256]; reason: TxInfo)
{.gcsafe,raises: [Defect,KeyError].}=
## Dispose items by item ID wihtout checking whether this makes other items
## unusable (e.g. with higher nonces for the same sender.)
for itemID in itemIDs:
let rcItem = xp.txDB.byItemID.eq(itemID)
if rcItem.isOK:
discard xp.txDB.dispose(rcItem.value, reason)
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------