mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-14 06:15:57 +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.
232 lines
7.7 KiB
Nim
232 lines
7.7 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 Item Container & Wrapper
|
|
## =========================================
|
|
##
|
|
|
|
import
|
|
std/[hashes, sequtils, strutils, times],
|
|
../ec_recover,
|
|
../utils_defs,
|
|
./tx_info,
|
|
eth/[common, keys],
|
|
stew/results
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
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 ##\
|
|
## Current status of a transaction as seen by the pool.
|
|
txItemPending = 0
|
|
txItemStaged
|
|
txItemPacked
|
|
|
|
TxItemRef* = ref object of RootObj ##\
|
|
## Data container with transaction and meta data. Entries are *read-only*\
|
|
## by default, for some there is a setter available.
|
|
tx: Transaction ## Transaction data
|
|
itemID: Hash256 ## Transaction hash
|
|
timeStamp: Time ## Time when added
|
|
sender: EthAddress ## Sender account address
|
|
info: string ## Whatever
|
|
status: TxItemStatus ## Transaction status (setter available)
|
|
reject: TxInfo ## Reason for moving to waste basket
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Private, helpers for debugging and pretty printing
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc utcTime: Time =
|
|
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
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc init*(item: TxItemRef; status: TxItemStatus; info: string) =
|
|
## Update item descriptor.
|
|
item.info = info
|
|
item.status = status
|
|
item.timeStamp = utcTime()
|
|
item.reject = txInfoOk
|
|
|
|
proc new*(T: type TxItemRef; tx: Transaction; itemID: Hash256;
|
|
status: TxItemStatus; info: string): Result[T,void] =
|
|
## Create item descriptor.
|
|
let rc = tx.ecRecover
|
|
if rc.isErr:
|
|
return err()
|
|
ok(T(itemID: itemID,
|
|
tx: tx,
|
|
sender: rc.value,
|
|
timeStamp: utcTime(),
|
|
info: info,
|
|
status: status))
|
|
|
|
proc new*(T: type TxItemRef; tx: Transaction;
|
|
reject: TxInfo; status: TxItemStatus; info: string): T =
|
|
## Create incomplete item descriptor, so meta-data can be stored (e.g.
|
|
## for holding in the waste basket to be investigated later.)
|
|
T(tx: tx,
|
|
timeStamp: utcTime(),
|
|
info: info,
|
|
status: status)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, Table ID helper
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc hash*(item: TxItemRef): Hash =
|
|
## Needed if `TxItemRef` is used as hash-`Table` index.
|
|
cast[pointer](item).hash
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, transaction getters
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc itemID*(tx: Transaction): Hash256 =
|
|
## Getter, transaction ID
|
|
tx.rlpHash
|
|
|
|
# core/types/transaction.go(297): func (tx *Transaction) Cost() *big.Int {
|
|
proc cost*(tx: Transaction): UInt256 =
|
|
## Getter (go/ref compat): gas * gasPrice + value.
|
|
(tx.gasPrice * tx.gasLimit).u256 + tx.value
|
|
|
|
# core/types/transaction.go(332): .. *Transaction) EffectiveGasTip(baseFee ..
|
|
# core/types/transaction.go(346): .. EffectiveGasTipValue(baseFee ..
|
|
proc effectiveGasTip*(tx: Transaction; baseFee: GasPrice): 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.int64).GasPriceEx
|
|
else:
|
|
# London, EIP1559
|
|
min(tx.maxPriorityFee, tx.maxFee - baseFee.int64).GasPriceEx
|
|
|
|
proc effectiveGasTip*(tx: Transaction; baseFee: UInt256): GasPriceEx =
|
|
## Variant of `effectiveGasTip()`
|
|
tx.effectiveGasTip(baseFee.truncate(uint64).GasPrice)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, item getters
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc dup*(item: TxItemRef): TxItemRef =
|
|
## Getter, provide contents copy
|
|
item.deepCopy
|
|
|
|
proc info*(item: TxItemRef): string =
|
|
## Getter
|
|
item.info
|
|
|
|
proc itemID*(item: TxItemRef): Hash256 =
|
|
## Getter
|
|
item.itemID
|
|
|
|
proc reject*(item: TxItemRef): TxInfo =
|
|
## Getter
|
|
item.reject
|
|
|
|
proc sender*(item: TxItemRef): EthAddress =
|
|
## Getter
|
|
item.sender
|
|
|
|
proc status*(item: TxItemRef): TxItemStatus =
|
|
## Getter
|
|
item.status
|
|
|
|
proc timeStamp*(item: TxItemRef): Time =
|
|
## Getter
|
|
item.timeStamp
|
|
|
|
proc tx*(item: TxItemRef): Transaction =
|
|
## Getter
|
|
item.tx
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, setters
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc `status=`*(item: TxItemRef; val: TxItemStatus) =
|
|
## Setter
|
|
item.status = val
|
|
|
|
proc `reject=`*(item: TxItemRef; val: TxInfo) =
|
|
## Setter
|
|
item.reject = val
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, pretty printing and debugging
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc `$`*(w: TxItemRef): string =
|
|
## Visualise item ID (use for debugging)
|
|
"<" & w.itemID.data.mapIt(it.toHex(2)).join[24 .. 31].toLowerAscii & ">"
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# End
|
|
# ------------------------------------------------------------------------------
|