125 lines
4.1 KiB
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
|
|
# ------------------------------------------------------------------------------
|