2022-01-18 14:40:02 +00:00
|
|
|
# Nimbus
|
|
|
|
# Copyright (c) 2018-2019 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.
|
|
|
|
|
|
|
|
import
|
2022-04-04 08:34:59 +00:00
|
|
|
std/[os, strformat, sequtils, strutils, times],
|
2022-01-18 14:40:02 +00:00
|
|
|
../../nimbus/utils/tx_pool/[tx_chain, tx_desc, tx_gauge, tx_item, tx_tabs],
|
|
|
|
../../nimbus/utils/tx_pool/tx_tasks/[tx_packer, tx_recover],
|
2022-08-24 13:44:18 +00:00
|
|
|
../replay/[pp, undump_blocks],
|
2022-04-04 08:34:59 +00:00
|
|
|
chronicles,
|
2022-01-18 14:40:02 +00:00
|
|
|
eth/[common, keys],
|
|
|
|
stew/[keyed_queue, sorted_set],
|
|
|
|
stint
|
|
|
|
|
|
|
|
# Make sure that the runner can stay on public view without the need
|
|
|
|
# to import `tx_pool/*` sup-modules
|
|
|
|
export
|
2022-02-11 16:28:39 +00:00
|
|
|
pp,
|
2022-01-18 14:40:02 +00:00
|
|
|
tx_chain.TxChainGasLimits,
|
|
|
|
tx_chain.`maxMode=`,
|
|
|
|
tx_chain.clearAccounts,
|
|
|
|
tx_chain.db,
|
|
|
|
tx_chain.limits,
|
|
|
|
tx_chain.nextFork,
|
|
|
|
tx_chain.profit,
|
|
|
|
tx_chain.receipts,
|
|
|
|
tx_chain.reward,
|
|
|
|
tx_chain.vmState,
|
|
|
|
tx_desc.chain,
|
|
|
|
tx_desc.txDB,
|
|
|
|
tx_desc.verify,
|
|
|
|
tx_gauge,
|
|
|
|
tx_packer.packerVmExec,
|
|
|
|
tx_recover.recoverItem,
|
|
|
|
tx_tabs.TxTabsRef,
|
|
|
|
tx_tabs.any,
|
|
|
|
tx_tabs.decAccount,
|
|
|
|
tx_tabs.dispose,
|
|
|
|
tx_tabs.eq,
|
|
|
|
tx_tabs.flushRejects,
|
|
|
|
tx_tabs.gasLimits,
|
|
|
|
tx_tabs.ge,
|
|
|
|
tx_tabs.gt,
|
|
|
|
tx_tabs.incAccount,
|
|
|
|
tx_tabs.incNonce,
|
|
|
|
tx_tabs.le,
|
|
|
|
tx_tabs.len,
|
|
|
|
tx_tabs.lt,
|
|
|
|
tx_tabs.nItems,
|
|
|
|
tx_tabs.reassign,
|
|
|
|
tx_tabs.reject,
|
|
|
|
tx_tabs.verify,
|
|
|
|
undumpNextGroup
|
|
|
|
|
|
|
|
const
|
|
|
|
# pretty printing
|
|
|
|
localInfo* = block:
|
|
|
|
var rc: array[bool,string]
|
|
|
|
rc[true] = "L"
|
|
|
|
rc[false] = "R"
|
|
|
|
rc
|
|
|
|
|
|
|
|
statusInfo* = block:
|
|
|
|
var rc: array[TxItemStatus,string]
|
|
|
|
rc[txItemPending] = "*"
|
|
|
|
rc[txItemStaged] = "S"
|
|
|
|
rc[txItemPacked] = "P"
|
|
|
|
rc
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Helpers
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
proc joinXX(s: string): string =
|
|
|
|
if s.len <= 30:
|
|
|
|
return s
|
|
|
|
if (s.len and 1) == 0:
|
|
|
|
result = s[0 ..< 8]
|
|
|
|
else:
|
|
|
|
result = "0" & s[0 ..< 7]
|
|
|
|
result &= "..(" & $((s.len + 1) div 2) & ").." & s[s.len-16 ..< s.len]
|
|
|
|
|
|
|
|
proc joinXX(q: seq[string]): string =
|
|
|
|
q.join("").joinXX
|
|
|
|
|
|
|
|
proc toXX[T](s: T): string =
|
|
|
|
s.toHex.strip(leading=true,chars={'0'}).toLowerAscii
|
|
|
|
|
|
|
|
proc toXX(q: Blob): string =
|
|
|
|
q.mapIt(it.toHex(2)).join(":")
|
|
|
|
|
|
|
|
proc toXX(a: EthAddress): string =
|
|
|
|
a.mapIt(it.toHex(2)).joinXX
|
|
|
|
|
|
|
|
proc toXX(h: Hash256): string =
|
|
|
|
h.data.mapIt(it.toHex(2)).joinXX
|
|
|
|
|
|
|
|
proc toXX(v: int64; r,s: UInt256): string =
|
|
|
|
v.toXX & ":" & ($r).joinXX & ":" & ($s).joinXX
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions, pretty printer
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
proc pp*(q: seq[(EthAddress,int)]): string =
|
|
|
|
"[" & q.mapIt(&"{it[0].pp}:{it[1]:03d}").join(",") & "]"
|
|
|
|
|
|
|
|
proc pp*(w: TxItemStatus): string =
|
|
|
|
($w).replace("txItem")
|
|
|
|
|
|
|
|
proc pp*(tx: Transaction): string =
|
|
|
|
## Pretty print transaction (use for debugging)
|
|
|
|
result = "(txType=" & $tx.txType
|
|
|
|
|
|
|
|
if tx.chainId.uint64 != 0:
|
|
|
|
result &= ",chainId=" & $tx.chainId.uint64
|
|
|
|
|
|
|
|
result &= ",nonce=" & tx.nonce.toXX
|
|
|
|
if tx.gasPrice != 0:
|
|
|
|
result &= ",gasPrice=" & tx.gasPrice.toKMG
|
|
|
|
if tx.maxPriorityFee != 0:
|
|
|
|
result &= ",maxPrioFee=" & tx.maxPriorityFee.toKMG
|
|
|
|
if tx.maxFee != 0:
|
|
|
|
result &= ",maxFee=" & tx.maxFee.toKMG
|
|
|
|
if tx.gasLimit != 0:
|
|
|
|
result &= ",gasLimit=" & tx.gasLimit.toKMG
|
|
|
|
if tx.to.isSome:
|
|
|
|
result &= ",to=" & tx.to.get.toXX
|
|
|
|
if tx.value != 0:
|
|
|
|
result &= ",value=" & tx.value.toKMG
|
|
|
|
if 0 < tx.payload.len:
|
|
|
|
result &= ",payload=" & tx.payload.toXX
|
|
|
|
if 0 < tx.accessList.len:
|
|
|
|
result &= ",accessList=" & $tx.accessList
|
|
|
|
|
|
|
|
result &= ",VRS=" & tx.V.toXX(tx.R,tx.S)
|
|
|
|
result &= ")"
|
|
|
|
|
|
|
|
proc pp*(w: TxItemRef): string =
|
|
|
|
## Pretty print item (use for debugging)
|
|
|
|
let s = w.tx.pp
|
|
|
|
result = "(timeStamp=" & ($w.timeStamp).replace(' ','_') &
|
|
|
|
",hash=" & w.itemID.toXX &
|
|
|
|
",status=" & w.status.pp &
|
|
|
|
"," & s[1 ..< s.len]
|
|
|
|
|
|
|
|
proc pp*(txs: openArray[Transaction]; pfx = ""): string =
|
|
|
|
let txt = block:
|
|
|
|
var rc = ""
|
|
|
|
if 0 < txs.len:
|
|
|
|
rc = "[" & txs[0].pp
|
|
|
|
for n in 1 ..< txs.len:
|
|
|
|
rc &= ";" & txs[n].pp
|
|
|
|
rc &= "]"
|
|
|
|
rc
|
|
|
|
txt.multiReplace([
|
|
|
|
(",", &",\n {pfx}"),
|
|
|
|
(";", &",\n {pfx}")])
|
|
|
|
|
|
|
|
proc pp*(txs: openArray[Transaction]; pfxLen: int): string =
|
|
|
|
txs.pp(" ".repeat(pfxLen))
|
|
|
|
|
|
|
|
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}"
|
|
|
|
|
|
|
|
proc pp*(w: TxChainGasLimits): string =
|
|
|
|
&"min={w.minLimit}" &
|
|
|
|
&" trg={w.lwmLimit}:{w.trgLimit}" &
|
|
|
|
&" max={w.hwmLimit}:{w.maxLimit}"
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions, other
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
proc isOK*(rc: ValidationResult): bool =
|
|
|
|
rc == ValidationResult.OK
|
|
|
|
|
|
|
|
proc toHex*(acc: EthAddress): string =
|
|
|
|
acc.toSeq.mapIt(it.toHex(2)).join
|
|
|
|
|
|
|
|
proc say*(noisy = false; pfx = "***"; args: varargs[string, `$`]) =
|
|
|
|
if noisy:
|
|
|
|
if args.len == 0:
|
|
|
|
echo "*** ", pfx
|
|
|
|
elif 0 < pfx.len and pfx[^1] != ' ':
|
|
|
|
echo pfx, " ", args.toSeq.join
|
|
|
|
else:
|
|
|
|
echo pfx, args.toSeq.join
|
|
|
|
|
2022-04-04 08:34:59 +00:00
|
|
|
proc setTraceLevel* =
|
|
|
|
discard
|
|
|
|
when defined(chronicles_runtime_filtering) and loggingEnabled:
|
|
|
|
setLogLevel(LogLevel.TRACE)
|
|
|
|
|
|
|
|
proc setErrorLevel* =
|
|
|
|
discard
|
|
|
|
when defined(chronicles_runtime_filtering) and loggingEnabled:
|
|
|
|
setLogLevel(LogLevel.ERROR)
|
|
|
|
|
|
|
|
proc findFilePath*(file: string;
|
|
|
|
baseDir, repoDir: openArray[string]): Result[string,void] =
|
|
|
|
for dir in baseDir:
|
|
|
|
for repo in repoDir:
|
|
|
|
let path = dir / repo / file
|
|
|
|
if path.fileExists:
|
|
|
|
return ok(path)
|
2022-08-12 15:42:07 +00:00
|
|
|
err()
|
2022-04-04 08:34:59 +00:00
|
|
|
|
2022-01-18 14:40:02 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# End
|
|
|
|
# ------------------------------------------------------------------------------
|