2022-01-18 14:40:02 +00:00
|
|
|
# Nimbus
|
Core db and aristo updates for destructor and tx logic (#1894)
* Disable `TransactionID` related functions from `state_db.nim`
why:
Functions `getCommittedStorage()` and `updateOriginalRoot()` from
the `state_db` module are nowhere used. The emulation of a legacy
`TransactionID` type functionality is administratively expensive to
provide by `Aristo` (the legacy DB version is only partially
implemented, anyway).
As there is no other place where `TransactionID`s are used, they will
not be provided by the `Aristo` variant of the `CoreDb`. For the
legacy DB API, nothing will change.
* Fix copyright headers in source code
* Get rid of compiler warning
* Update Aristo code, remove unused `merge()` variant, export `hashify()`
why:
Adapt to upcoming `CoreDb` wrapper
* Remove synced tx feature from `Aristo`
why:
+ This feature allowed to synchronise transaction methods like begin,
commit, and rollback for a group of descriptors.
+ The feature is over engineered and not needed for `CoreDb`, neither
is it complete (some convergence features missing.)
* Add debugging helpers to `Kvt`
also:
Update database iterator, add count variable yield argument similar
to `Aristo`.
* Provide optional destructors for `CoreDb` API
why;
For the upcoming Aristo wrapper, this allows to control when certain
smart destruction and update can take place. The auto destructor works
fine in general when the storage/cache strategy is known and acceptable
when creating descriptors.
* Add update option for `CoreDb` API function `hash()`
why;
The hash function is typically used to get the state root of the MPT.
Due to lazy hashing, this might be not available on the `Aristo` DB.
So the `update` function asks for re-hashing the gurrent state changes
if needed.
* Update API tracking log mode: `info` => `debug
* Use shared `Kvt` descriptor in new Ledger API
why:
No need to create a new descriptor all the time
2023-11-16 19:35:03 +00:00
|
|
|
# Copyright (c) 2022-2023 Status Research & Development GmbH
|
2022-01-18 14:40:02 +00:00
|
|
|
# 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-12-02 04:39:12 +00:00
|
|
|
../../nimbus/core/tx_pool/[tx_chain, tx_desc, tx_gauge, tx_item, tx_tabs],
|
|
|
|
../../nimbus/core/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,
|
2022-12-02 04:39:12 +00:00
|
|
|
tx_chain.com,
|
2022-01-18 14:40:02 +00:00
|
|
|
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.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,
|
2023-04-21 21:11:04 +00:00
|
|
|
undumpBlocks
|
2022-01-18 14:40:02 +00:00
|
|
|
|
|
|
|
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
|
2023-06-12 04:29:03 +00:00
|
|
|
if tx.value.isZero.not:
|
2022-01-18 14:40:02 +00:00
|
|
|
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
|
|
|
|
# ------------------------------------------------------------------------------
|