Jordan Hrycaj c47f021596
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

310 lines
12 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.
## Unify different ledger management APIs.
{.push raises: [].}
import
eth/common,
chronicles,
../../../stateless/multi_keys,
../core_db,
./base/[base_desc, validate]
type
ReadOnlyStateDB* = distinct LedgerRef
export
LedgerType,
LedgerRef,
LedgerSpRef
when defined(release):
const AutoValidateDescriptors = false
else:
const AutoValidateDescriptors = true
const
EnableApiTracking = true and false
## When enabled, API functions are logged. Tracking is enabled by setting
## the `trackApi` flag to `true`.
# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------
when EnableApiTracking:
import std/strutils, chronicles, stew/byteutils
{.warning: "*** Provided API logging for Ledger (disabled by default)".}
template apiTxt(info: static[string]): static[string] =
"Ledger API " & info
template ifTrackApi(ldg: LedgerRef; code: untyped) =
when EnableApiTracking:
if ldg.trackApi:
code
proc oaToStr(w: openArray[byte]): string =
w.toHex.toLowerAscii
proc toStr(w: EthAddress): string =
w.oaToStr
proc toStr(w: Hash256): string =
w.data.oaToStr
proc toStr(w: Blob): string =
if 0 < w.len and w.len < 5: "<" & w.oaToStr & ">"
else: "Blob[" & $w.len & "]"
proc toStr(w: seq[Log]): string =
"Logs[" & $w.len & "]"
else:
template ifTrackApi(ldg: LedgerRef; code: untyped) = discard
# ------------------------------------------------------------------------------
# Public constructor helper
# ------------------------------------------------------------------------------
proc bless*(ldg: LedgerRef; db: CoreDbRef): LedgerRef =
when AutoValidateDescriptors:
ldg.validate()
when EnableApiTracking:
ldg.trackApi = db.trackLedgerApi
if ldg.trackApi:
debug apiTxt "LedgerRef.init()", ldgType=ldg.ldgType
ldg
# ------------------------------------------------------------------------------
# Public methods
# ------------------------------------------------------------------------------
proc accessList*(ldg: LedgerRef, eAddr: EthAddress) =
ldg.methods.accessListFn(eAddr)
ldg.ifTrackApi: debug apiTxt "accessList()", eAddr=eAddr.toStr
proc accessList*(ldg: LedgerRef, eAddr: EthAddress, slot: UInt256) =
ldg.methods.accessList2Fn(eAddr, slot)
ldg.ifTrackApi: debug apiTxt "accessList()", eAddr=eAddr.toStr, slot
proc accountExists*(ldg: LedgerRef, eAddr: EthAddress): bool =
result = ldg.methods.accountExistsFn(eAddr)
ldg.ifTrackApi: debug apiTxt "accountExists()", eAddr=eAddr.toStr, result
proc addBalance*(ldg: LedgerRef, eAddr: EthAddress, delta: UInt256) =
ldg.methods.addBalanceFn(eAddr, delta)
ldg.ifTrackApi: debug apiTxt "addBalance()", eAddr=eAddr.toStr, delta
proc addLogEntry*(ldg: LedgerRef, log: Log) =
ldg.methods.addLogEntryFn(log)
ldg.ifTrackApi: debug apiTxt "addLogEntry()"
proc beginSavepoint*(ldg: LedgerRef): LedgerSpRef =
result = ldg.methods.beginSavepointFn()
ldg.ifTrackApi: debug apiTxt "beginSavepoint()"
proc clearStorage*(ldg: LedgerRef, eAddr: EthAddress) =
ldg.methods.clearStorageFn(eAddr)
ldg.ifTrackApi: debug apiTxt "clearStorage()", eAddr=eAddr.toStr
proc clearTransientStorage*(ldg: LedgerRef) =
ldg.methods.clearTransientStorageFn()
ldg.ifTrackApi: debug apiTxt "clearTransientStorage()"
proc collectWitnessData*(ldg: LedgerRef) =
ldg.methods.collectWitnessDataFn()
ldg.ifTrackApi: debug apiTxt "collectWitnessData()"
proc commit*(ldg: LedgerRef, sp: LedgerSpRef) =
ldg.methods.commitFn(sp)
ldg.ifTrackApi: debug apiTxt "commit()"
proc deleteAccount*(ldg: LedgerRef, eAddr: EthAddress) =
ldg.methods.deleteAccountFn(eAddr)
ldg.ifTrackApi: debug apiTxt "deleteAccount()", eAddr=eAddr.toStr
proc dispose*(ldg: LedgerRef, sp: LedgerSpRef) =
ldg.methods.disposeFn(sp)
ldg.ifTrackApi: debug apiTxt "dispose()"
proc getAndClearLogEntries*(ldg: LedgerRef): seq[Log] =
result = ldg.methods.getAndClearLogEntriesFn()
ldg.ifTrackApi: debug apiTxt "getAndClearLogEntries()"
proc getBalance*(ldg: LedgerRef, eAddr: EthAddress): UInt256 =
result = ldg.methods.getBalanceFn(eAddr)
ldg.ifTrackApi: debug apiTxt "getBalance()", eAddr=eAddr.toStr, result
proc getCode*(ldg: LedgerRef, eAddr: EthAddress): Blob =
result = ldg.methods.getCodeFn(eAddr)
ldg.ifTrackApi:
debug apiTxt "getCode()", eAddr=eAddr.toStr, result=result.toStr
proc getCodeHash*(ldg: LedgerRef, eAddr: EthAddress): Hash256 =
result = ldg.methods.getCodeHashFn(eAddr)
ldg.ifTrackApi:
debug apiTxt "getCodeHash()", eAddr=eAddr.toStr, result=result.toStr
proc getCodeSize*(ldg: LedgerRef, eAddr: EthAddress): int =
result = ldg.methods.getCodeSizeFn(eAddr)
ldg.ifTrackApi: debug apiTxt "getCodeSize()", eAddr=eAddr.toStr, result
proc getCommittedStorage*(ldg: LedgerRef, eAddr: EthAddress, slot: UInt256): UInt256 =
result = ldg.methods.getCommittedStorageFn(eAddr, slot)
ldg.ifTrackApi:
debug apiTxt "getCommittedStorage()", eAddr=eAddr.toStr, slot, result
proc getNonce*(ldg: LedgerRef, eAddr: EthAddress): AccountNonce =
result = ldg.methods.getNonceFn(eAddr)
ldg.ifTrackApi: debug apiTxt "getNonce()", eAddr=eAddr.toStr, result
proc getStorage*(ldg: LedgerRef, eAddr: EthAddress, slot: UInt256): UInt256 =
result = ldg.methods.getStorageFn(eAddr, slot)
ldg.ifTrackApi: debug apiTxt "getStorage()", eAddr=eAddr.toStr, slot, result
proc getStorageRoot*(ldg: LedgerRef, eAddr: EthAddress): Hash256 =
result = ldg.methods.getStorageRootFn(eAddr)
ldg.ifTrackApi:
debug apiTxt "getStorageRoot()", eAddr=eAddr.toStr, result=result.toStr
proc getTransientStorage*(ldg: LedgerRef, eAddr: EthAddress, slot: UInt256): UInt256 =
result = ldg.methods.getTransientStorageFn(eAddr, slot)
ldg.ifTrackApi:
debug apiTxt "getTransientStorage()", eAddr=eAddr.toStr, slot, result
proc hasCodeOrNonce*(ldg: LedgerRef, eAddr: EthAddress): bool =
result = ldg.methods.hasCodeOrNonceFn(eAddr)
ldg.ifTrackApi: debug apiTxt "hasCodeOrNonce()", eAddr=eAddr.toStr, result
proc inAccessList*(ldg: LedgerRef, eAddr: EthAddress): bool =
result = ldg.methods.inAccessListFn(eAddr)
ldg.ifTrackApi: debug apiTxt "inAccessList()", eAddr=eAddr.toStr, result
proc inAccessList*(ldg: LedgerRef, eAddr: EthAddress, slot: UInt256): bool =
result = ldg.methods.inAccessList2Fn(eAddr, slot)
ldg.ifTrackApi: debug apiTxt "inAccessList()", eAddr=eAddr.toStr, slot, result
proc incNonce*(ldg: LedgerRef, eAddr: EthAddress) =
ldg.methods.incNonceFn(eAddr)
ldg.ifTrackApi: debug apiTxt "incNonce()", eAddr=eAddr.toStr
proc isDeadAccount*(ldg: LedgerRef, eAddr: EthAddress): bool =
result = ldg.methods.isDeadAccountFn(eAddr)
ldg.ifTrackApi: debug apiTxt "isDeadAccount()", eAddr=eAddr.toStr, result
proc isEmptyAccount*(ldg: LedgerRef, eAddr: EthAddress): bool =
result = ldg.methods.isEmptyAccountFn(eAddr)
ldg.ifTrackApi: debug apiTxt "isEmptyAccount()", eAddr=eAddr.toStr, result
proc isTopLevelClean*(ldg: LedgerRef): bool =
result = ldg.methods.isTopLevelCleanFn()
ldg.ifTrackApi: debug apiTxt "isTopLevelClean()", result
proc logEntries*(ldg: LedgerRef): seq[Log] =
result = ldg.methods.logEntriesFn()
ldg.ifTrackApi: debug apiTxt "logEntries()", result=result.toStr
proc makeMultiKeys*(ldg: LedgerRef): MultikeysRef =
result = ldg.methods.makeMultiKeysFn()
ldg.ifTrackApi: debug apiTxt "makeMultiKeys()"
proc persist*(ldg: LedgerRef, clearEmptyAccount = false, clearCache = true) =
ldg.methods.persistFn(clearEmptyAccount, clearCache)
ldg.ifTrackApi: debug apiTxt "persist()", clearEmptyAccount, clearCache
proc ripemdSpecial*(ldg: LedgerRef) =
ldg.methods.ripemdSpecialFn()
ldg.ifTrackApi: debug apiTxt "ripemdSpecial()"
proc rollback*(ldg: LedgerRef, sp: LedgerSpRef) =
ldg.methods.rollbackFn(sp)
ldg.ifTrackApi: debug apiTxt "rollback()"
proc rootHash*(ldg: LedgerRef): Hash256 =
result = ldg.methods.rootHashFn()
ldg.ifTrackApi: debug apiTxt "rootHash()", result=result.toStr
proc safeDispose*(ldg: LedgerRef, sp: LedgerSpRef) =
ldg.methods.safeDisposeFn(sp)
ldg.ifTrackApi: debug apiTxt "safeDispose()"
proc selfDestruct*(ldg: LedgerRef, eAddr: EthAddress) =
ldg.methods.selfDestructFn(eAddr)
ldg.ifTrackApi: debug apiTxt "selfDestruct()"
proc selfDestruct6780*(ldg: LedgerRef, eAddr: EthAddress) =
ldg.methods.selfDestruct6780Fn(eAddr)
ldg.ifTrackApi: debug apiTxt "selfDestruct6780()"
proc selfDestructLen*(ldg: LedgerRef): int =
result = ldg.methods.selfDestructLenFn()
ldg.ifTrackApi: debug apiTxt "selfDestructLen()", result
proc setBalance*(ldg: LedgerRef, eAddr: EthAddress, balance: UInt256) =
ldg.methods.setBalanceFn(eAddr, balance)
ldg.ifTrackApi: debug apiTxt "setBalance()", eAddr=eAddr.toStr, balance
proc setCode*(ldg: LedgerRef, eAddr: EthAddress, code: Blob) =
ldg.methods.setCodeFn(eAddr, code)
ldg.ifTrackApi: debug apiTxt "setCode()", eAddr=eAddr.toStr, code=code.toStr
proc setNonce*(ldg: LedgerRef, eAddr: EthAddress, nonce: AccountNonce) =
ldg.methods.setNonceFn(eAddr, nonce)
ldg.ifTrackApi: debug apiTxt "setNonce()", eAddr=eAddr.toStr, nonce
proc setStorage*(ldg: LedgerRef, eAddr: EthAddress, slot, val: UInt256) =
ldg.methods.setStorageFn(eAddr, slot, val)
ldg.ifTrackApi: debug apiTxt "setStorage()", eAddr=eAddr.toStr, slot, val
proc setTransientStorage*(ldg: LedgerRef, eAddr: EthAddress, slot, val: UInt256) =
ldg.methods.setTransientStorageFn(eAddr, slot, val)
ldg.ifTrackApi:
debug apiTxt "setTransientStorage()", eAddr=eAddr.toStr, slot, val
proc subBalance*(ldg: LedgerRef, eAddr: EthAddress, delta: UInt256) =
ldg.methods.subBalanceFn(eAddr, delta)
ldg.ifTrackApi: debug apiTxt "setTransientStorage()", eAddr=eAddr.toStr, delta
# ------------------------------------------------------------------------------
# Public methods, extensions to go away
# ------------------------------------------------------------------------------
proc rawRootHash*(ldg: LedgerRef): Hash256 =
result = ldg.extras.rawRootHashFn()
ldg.ifTrackApi: debug apiTxt "rawRootHash()", result=result.toStr
# ------------------------------------------------------------------------------
# Public virtual read-only methods
# ------------------------------------------------------------------------------
proc rootHash*(db: ReadOnlyStateDB): KeccakHash {.borrow.}
proc getCodeHash*(db: ReadOnlyStateDB, eAddr: EthAddress): Hash256 {.borrow.}
proc getStorageRoot*(db: ReadOnlyStateDB, eAddr: EthAddress): Hash256 {.borrow.}
proc getBalance*(db: ReadOnlyStateDB, eAddr: EthAddress): UInt256 {.borrow.}
proc getStorage*(db: ReadOnlyStateDB, eAddr: EthAddress, slot: UInt256): UInt256 {.borrow.}
proc getNonce*(db: ReadOnlyStateDB, eAddr: EthAddress): AccountNonce {.borrow.}
proc getCode*(db: ReadOnlyStateDB, eAddr: EthAddress): seq[byte] {.borrow.}
proc getCodeSize*(db: ReadOnlyStateDB, eAddr: EthAddress): int {.borrow.}
proc hasCodeOrNonce*(db: ReadOnlyStateDB, eAddr: EthAddress): bool {.borrow.}
proc accountExists*(db: ReadOnlyStateDB, eAddr: EthAddress): bool {.borrow.}
proc isDeadAccount*(db: ReadOnlyStateDB, eAddr: EthAddress): bool {.borrow.}
proc isEmptyAccount*(db: ReadOnlyStateDB, eAddr: EthAddress): bool {.borrow.}
proc getCommittedStorage*(db: ReadOnlyStateDB, eAddr: EthAddress, slot: UInt256): UInt256 {.borrow.}
func inAccessList*(db: ReadOnlyStateDB, eAddr: EthAddress): bool {.borrow.}
func inAccessList*(db: ReadOnlyStateDB, eAddr: EthAddress, slot: UInt256): bool {.borrow.}
func getTransientStorage*(db: ReadOnlyStateDB, eAddr: EthAddress, slot: UInt256): UInt256 {.borrow.}
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------