mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-14 22:34:23 +00:00
103656dbb5
details: For documentation, see comments in the file tx_pool.nim. For prettified manual pages run 'make docs' in the nimbus directory and point your web browser to the newly created 'docs' directory.
188 lines
5.4 KiB
Nim
188 lines
5.4 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 Table: `rank` ~ `sender`
|
|
## =========================================
|
|
##
|
|
|
|
import
|
|
std/[tables],
|
|
../tx_info,
|
|
eth/[common],
|
|
stew/[results, sorted_set]
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
type
|
|
TxRank* = ##\
|
|
## Order relation, determins how the `EthAddresses` are ranked
|
|
distinct int64
|
|
|
|
TxRankAddrRef* = ##\
|
|
## Set of adresses having the same rank.
|
|
TableRef[EthAddress,TxRank]
|
|
|
|
TxRankTab* = object ##\
|
|
## Descriptor for `TxRank` <-> `EthAddress` mapping.
|
|
rankList: SortedSet[TxRank,TxRankAddrRef]
|
|
addrTab: Table[EthAddress,TxRank]
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Private helpers
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc cmp(a,b: TxRank): int {.borrow.}
|
|
## mixin for SortedSet
|
|
|
|
proc `==`(a,b: TxRank): bool {.borrow.}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public constructor
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc init*(rt: var TxRankTab) =
|
|
## Constructor
|
|
rt.rankList.init
|
|
|
|
proc clear*(rt: var TxRankTab) =
|
|
## Flush tables
|
|
rt.rankList.clear
|
|
rt.addrTab.clear
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, base management operations
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc insert*(rt: var TxRankTab; rank: TxRank; sender: EthAddress): bool
|
|
{.gcsafe,raises: [Defect,KeyError].} =
|
|
## Add or update a new ranked address. This function returns `true` it the
|
|
## address exists already with the current rank.
|
|
|
|
# Does this address exists already?
|
|
if rt.addrTab.hasKey(sender):
|
|
let oldRank = rt.addrTab[sender]
|
|
if oldRank == rank:
|
|
return false
|
|
|
|
# Delete address from oldRank address set
|
|
let oldRankSet = rt.rankList.eq(oldRank).value.data
|
|
if 1 < oldRankSet.len:
|
|
oldRankSet.del(sender)
|
|
else:
|
|
discard rt.rankList.delete(oldRank)
|
|
|
|
# Add new ranked address
|
|
var newRankSet: TxRankAddrRef
|
|
let rc = rt.rankList.insert(rank)
|
|
if rc.isOK:
|
|
newRankSet = newTable[EthAddress,TxRank](1)
|
|
rc.value.data = newRankSet
|
|
else:
|
|
newRankSet = rt.rankList.eq(rank).value.data
|
|
|
|
newRankSet[sender] = rank
|
|
rt.addrTab[sender] = rank
|
|
true
|
|
|
|
|
|
proc delete*(rt: var TxRankTab; sender: EthAddress): bool
|
|
{.gcsafe,raises: [Defect,KeyError].} =
|
|
## Delete argument address `sender` from rank table.
|
|
if rt.addrTab.hasKey(sender):
|
|
let
|
|
rankNum = rt.addrTab[sender]
|
|
rankSet = rt.rankList.eq(rankNum).value.data
|
|
|
|
# Delete address from oldRank address set
|
|
if 1 < rankSet.len:
|
|
rankSet.del(sender)
|
|
else:
|
|
discard rt.rankList.delete(rankNum)
|
|
|
|
rt.addrTab.del(sender)
|
|
return true
|
|
|
|
|
|
proc verify*(rt: var TxRankTab): Result[void,TxInfo]
|
|
{.gcsafe,raises: [Defect,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`
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc len*(rt: var TxRankTab): int =
|
|
## Number of ranks available
|
|
rt.rankList.len
|
|
|
|
proc eq*(rt: var TxRankTab; rank: TxRank):
|
|
SortedSetResult[TxRank,TxRankAddrRef] =
|
|
rt.rankList.eq(rank)
|
|
|
|
proc ge*(rt: var TxRankTab; rank: TxRank):
|
|
SortedSetResult[TxRank,TxRankAddrRef] =
|
|
rt.rankList.ge(rank)
|
|
|
|
proc gt*(rt: var TxRankTab; rank: TxRank):
|
|
SortedSetResult[TxRank,TxRankAddrRef] =
|
|
rt.rankList.gt(rank)
|
|
|
|
proc le*(rt: var TxRankTab; rank: TxRank):
|
|
SortedSetResult[TxRank,TxRankAddrRef] =
|
|
rt.rankList.le(rank)
|
|
|
|
proc lt*(rt: var TxRankTab; rank: TxRank):
|
|
SortedSetResult[TxRank,TxRankAddrRef] =
|
|
rt.rankList.lt(rank)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions: `EthAddress` > `TxRank`
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc nItems*(rt: var TxRankTab): int =
|
|
## Total number of address items registered
|
|
rt.addrTab.len
|
|
|
|
proc eq*(rt: var TxRankTab; sender: EthAddress):
|
|
SortedSetResult[EthAddress,TxRank]
|
|
{.gcsafe,raises: [Defect,KeyError].} =
|
|
if rt.addrTab.hasKey(sender):
|
|
return toSortedSetResult(key = sender, data = rt.addrTab[sender])
|
|
err(rbNotFound)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# End
|
|
# ------------------------------------------------------------------------------
|