Core db reorg (#2444)
* CoreDb: Merged all sub-descriptors into `base_desc` module * Dissolve `aristo_db/common_desc.nim` * No need to export `Aristo` methods in `CoreDb` * Resolve/tighten methods in `aristo_db` sub-moduled why: So they can be straihgt implemented into the `base` module * Moved/re-implemented `KVT` methods into `base` module * Moved/re-implemented `MPT` methods into `base` module * Moved/re-implemented account methods into `base` module * Moved/re-implemented `CTX` methods into `base` module * Moved/re-implemented `handler_{aristo,kvt}` into `aristo_db` module * Moved/re-implemented `TX` methods into `base` module * Moved/re-implemented base methods into `base` module * Replaced `toAristoSavedStateBlockNumber()` by proper base method why: Was the last for keeping reason for keeping low level backend access methods * Remove dedicated low level access to `Aristo` backend why: Not needed anymore, for debugging the descriptors can be accessed directly also: some clean up stuff * Re-factor `CoreDb` descriptor layout and adjust base methods * Moved/re-implemented iterators into `base_iterator*` modules * Update docu
This commit is contained in:
parent
b1ff4ef3a5
commit
ea7c756a9d
|
@ -23,6 +23,7 @@ import
|
||||||
export
|
export
|
||||||
MemBackendRef,
|
MemBackendRef,
|
||||||
VoidBackendRef,
|
VoidBackendRef,
|
||||||
|
finish,
|
||||||
init
|
init
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
|
@ -384,7 +384,7 @@ type
|
||||||
## is returned if there was any.
|
## is returned if there was any.
|
||||||
|
|
||||||
AristoApiTxBeginFn* =
|
AristoApiTxBeginFn* =
|
||||||
proc(db: AristoDbRef
|
proc(db: AristoDbRef;
|
||||||
): Result[AristoTxRef,AristoError]
|
): Result[AristoTxRef,AristoError]
|
||||||
{.noRaise.}
|
{.noRaise.}
|
||||||
## Starts a new transaction.
|
## Starts a new transaction.
|
||||||
|
@ -397,6 +397,12 @@ type
|
||||||
## ... continue using db ...
|
## ... continue using db ...
|
||||||
## tx.commit()
|
## tx.commit()
|
||||||
|
|
||||||
|
AristoApiTxLevelFn* =
|
||||||
|
proc(tx: AristoTxRef;
|
||||||
|
): int
|
||||||
|
{.noRaise.}
|
||||||
|
## Getter, positive nesting level of transaction argument `tx`
|
||||||
|
|
||||||
AristoApiTxTopFn* =
|
AristoApiTxTopFn* =
|
||||||
proc(db: AristoDbRef;
|
proc(db: AristoDbRef;
|
||||||
): Result[AristoTxRef,AristoError]
|
): Result[AristoTxRef,AristoError]
|
||||||
|
@ -445,6 +451,7 @@ type
|
||||||
reCentre*: AristoApiReCentreFn
|
reCentre*: AristoApiReCentreFn
|
||||||
rollback*: AristoApiRollbackFn
|
rollback*: AristoApiRollbackFn
|
||||||
txBegin*: AristoApiTxBeginFn
|
txBegin*: AristoApiTxBeginFn
|
||||||
|
txLevel*: AristoApiTxLevelFn
|
||||||
txTop*: AristoApiTxTopFn
|
txTop*: AristoApiTxTopFn
|
||||||
|
|
||||||
|
|
||||||
|
@ -491,6 +498,7 @@ type
|
||||||
AristoApiProfReCentreFn = "reCentre"
|
AristoApiProfReCentreFn = "reCentre"
|
||||||
AristoApiProfRollbackFn = "rollback"
|
AristoApiProfRollbackFn = "rollback"
|
||||||
AristoApiProfTxBeginFn = "txBegin"
|
AristoApiProfTxBeginFn = "txBegin"
|
||||||
|
AristoApiProfTxLevelFn = "txLevel"
|
||||||
AristoApiProfTxTopFn = "txTop"
|
AristoApiProfTxTopFn = "txTop"
|
||||||
|
|
||||||
AristoApiProfBeGetVtxFn = "be/getVtx"
|
AristoApiProfBeGetVtxFn = "be/getVtx"
|
||||||
|
@ -554,6 +562,7 @@ when AutoValidateApiHooks:
|
||||||
doAssert not api.reCentre.isNil
|
doAssert not api.reCentre.isNil
|
||||||
doAssert not api.rollback.isNil
|
doAssert not api.rollback.isNil
|
||||||
doAssert not api.txBegin.isNil
|
doAssert not api.txBegin.isNil
|
||||||
|
doAssert not api.txLevel.isNil
|
||||||
doAssert not api.txTop.isNil
|
doAssert not api.txTop.isNil
|
||||||
|
|
||||||
proc validate(prf: AristoApiProfRef) =
|
proc validate(prf: AristoApiProfRef) =
|
||||||
|
@ -621,6 +630,7 @@ func init*(api: var AristoApiObj) =
|
||||||
api.reCentre = reCentre
|
api.reCentre = reCentre
|
||||||
api.rollback = rollback
|
api.rollback = rollback
|
||||||
api.txBegin = txBegin
|
api.txBegin = txBegin
|
||||||
|
api.txLevel = txLevel
|
||||||
api.txTop = txTop
|
api.txTop = txTop
|
||||||
when AutoValidateApiHooks:
|
when AutoValidateApiHooks:
|
||||||
api.validate
|
api.validate
|
||||||
|
@ -670,6 +680,7 @@ func dup*(api: AristoApiRef): AristoApiRef =
|
||||||
reCentre: api.reCentre,
|
reCentre: api.reCentre,
|
||||||
rollback: api.rollback,
|
rollback: api.rollback,
|
||||||
txBegin: api.txBegin,
|
txBegin: api.txBegin,
|
||||||
|
txLevel: api.txLevel,
|
||||||
txTop: api.txTop)
|
txTop: api.txTop)
|
||||||
when AutoValidateApiHooks:
|
when AutoValidateApiHooks:
|
||||||
api.validate
|
api.validate
|
||||||
|
@ -861,6 +872,11 @@ func init*(
|
||||||
AristoApiProfTxBeginFn.profileRunner:
|
AristoApiProfTxBeginFn.profileRunner:
|
||||||
result = api.txBegin(a)
|
result = api.txBegin(a)
|
||||||
|
|
||||||
|
profApi.txLevel =
|
||||||
|
proc(a: AristoTxRef): auto =
|
||||||
|
AristoApiProfTxLevelFn.profileRunner:
|
||||||
|
result = api.txLevel(a)
|
||||||
|
|
||||||
profApi.txTop =
|
profApi.txTop =
|
||||||
proc(a: AristoDbRef): auto =
|
proc(a: AristoDbRef): auto =
|
||||||
AristoApiProfTxTopFn.profileRunner:
|
AristoApiProfTxTopFn.profileRunner:
|
||||||
|
|
|
@ -31,7 +31,7 @@ func isTop*(tx: AristoTxRef): bool =
|
||||||
## level transaction.
|
## level transaction.
|
||||||
tx.txFrameIsTop()
|
tx.txFrameIsTop()
|
||||||
|
|
||||||
func level*(tx: AristoTxRef): int =
|
func txLevel*(tx: AristoTxRef): int =
|
||||||
## Getter, positive nesting level of transaction argument `tx`
|
## Getter, positive nesting level of transaction argument `tx`
|
||||||
tx.txFrameLevel()
|
tx.txFrameLevel()
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, typetraits],
|
std/sequtils,
|
||||||
eth/common,
|
eth/common,
|
||||||
results,
|
results,
|
||||||
"."/[aristo_constants, aristo_desc, aristo_get, aristo_hike, aristo_layers]
|
"."/[aristo_constants, aristo_desc, aristo_get, aristo_hike, aristo_layers]
|
||||||
|
|
|
@ -1,84 +1,26 @@
|
||||||
Core database replacement wrapper object
|
Core database
|
||||||
========================================
|
=============
|
||||||
This wrapper replaces the *TrieDatabaseRef* and its derivatives by the new
|
|
||||||
object *CoreDbRef*.
|
|
||||||
|
|
||||||
# **out of date**
|
Layout of `CoreDb` descriptor objects
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
### Objects dependence:
|
||||||
|
|
||||||
Relations to current *TrieDatabaseRef* implementation
|
CoreDbRef -- Base descriptor
|
||||||
-----------------------------------------------------
|
|
||||||
Here are some incomplete translations for objects and constructors.
|
|
||||||
|
|
||||||
### Object types:
|
|
||||||
|
|
||||||
| **Legacy notation** | **CoreDbRef based replacement** |
|
|
||||||
|:----------------------------|:--------------------------------------|
|
|
||||||
| | |
|
|
||||||
| ChainDB | (don't use/avoid) |
|
|
||||||
| ChainDbRef | CoreDbRef |
|
|
||||||
| TrieDatabaseRef | CoreDbKvtRef |
|
|
||||||
| HexaryTrie | CoreDbMptRef |
|
|
||||||
| SecureHexaryTrie | CoreDbPhkRef |
|
|
||||||
| DbTransaction | CoreDbTxRef |
|
|
||||||
| TransactionID | CoreDbTxID |
|
|
||||||
|
|
||||||
|
|
||||||
### Constructors:
|
|
||||||
|
|
||||||
| **Legacy notation** | **CoreDbRef based replacement** |
|
|
||||||
|:----------------------------|:--------------------------------------|
|
|
||||||
| | |
|
|
||||||
| trieDB newChainDB("..") | newCoreDbRef(LegacyDbPersistent,"..") |
|
|
||||||
| newMemoryDB() | newCoreDbRef(LegacyDbMemory) |
|
|
||||||
| -- | |
|
|
||||||
| initHexaryTrie(db,..) | db.mpt(..) (no pruning) |
|
|
||||||
| | db.mptPrune(..) (w/pruning true/false)|
|
|
||||||
| -- | |
|
|
||||||
| initSecureHexaryTrie(db,..) | db.phk(..) (no pruning) |
|
|
||||||
| | db.phkPrune(..) (w/pruning true/false)|
|
|
||||||
| -- | |
|
|
||||||
| newCaptureDB(db,memDB) | db.capture() (see below) |
|
|
||||||
|
|
||||||
|
|
||||||
Usage of the replacement wrapper
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
### Objects pedigree:
|
|
||||||
|
|
||||||
CoreDbRef -- base descriptor
|
|
||||||
| | |
|
| | |
|
||||||
| | +--- CoreDbCtxRef -- MPT context descriptor
|
| | +--- CoreDbCtxRef -- Context descriptor
|
||||||
| | | |
|
| | | | | |
|
||||||
| | | +-- CoreDbMptRef -- hexary trie instance
|
| | | | | +--- CoreDbKvtRef -- Key-value table
|
||||||
| | | | : :
|
| | | | |
|
||||||
| | | +-- CoreDbMptRef -- hexary trie instance
|
| | | | +----- CoreDbMptRef -- Generic MPT
|
||||||
| | |
|
| | | |
|
||||||
| | |
|
| | | +------- CoreDbAccRef -- Accounts database
|
||||||
| | +---- CoreDbPhkRef -- pre-hashed key hexary trie instance
|
| | |
|
||||||
| | | : :
|
| | +--------- CoreDbTxRef -- Transaction handle
|
||||||
| | +---- CoreDbPhkRef -- pre-hashed key hexary trie instance
|
|
||||||
| |
|
| |
|
||||||
| |
|
| +----- CoreDbCtxRef
|
||||||
| +------ CoreDbKvtRef -- single static key-value table
|
| : : : :
|
||||||
|
|
|
|
||||||
|
|
+------- CoreDbCtxRef
|
||||||
+-------- CoreDbCaptRef -- tracer support descriptor
|
: : : :
|
||||||
|
|
||||||
### Instantiating legacy standard database object descriptors works as follows:
|
|
||||||
|
|
||||||
let
|
|
||||||
db = newCoreDbRef(..) # new base descriptor
|
|
||||||
mpt = db.mpt(..) # hexary trie/Merkle Patricia Tree
|
|
||||||
phk = db.phk(..) # pre-hashed key hexary trie/MPT
|
|
||||||
kvt = db.kvt # key-value table
|
|
||||||
|
|
||||||
### Tracer support setup by hiding the current *CoreDbRef* behind a replacement:
|
|
||||||
|
|
||||||
let
|
|
||||||
capture = db.capture()
|
|
||||||
db = capture.recorder # use the recorder in place of db
|
|
||||||
...
|
|
||||||
|
|
||||||
for key,value in capture.recorder.kvt:
|
|
||||||
... # process recorded data
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
* Re-implement *getOldestJournalBlockNumber()* and
|
* Refactor `handlers_tracer`. This module can reliably work only as a genuine
|
||||||
*getLatestJournalBlockNumber()* (from the `core_apps` module) via the CoreDb
|
logger. The restore features were ill concieved, an attempt to be as close
|
||||||
base api. Currently this api is bypassed (via the *backend()* directive). The
|
as possible to the legacy tracer.
|
||||||
functionality is directly provided by the `Aristo` backend.
|
|
||||||
|
|
|
@ -11,196 +11,38 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/tables,
|
|
||||||
eth/common,
|
|
||||||
../../aristo as use_ari,
|
../../aristo as use_ari,
|
||||||
../../aristo/[aristo_walk, aristo_serialise],
|
../../aristo/[aristo_init/memory_only, aristo_walk],
|
||||||
../../kvt as use_kvt,
|
../../kvt as use_kvt,
|
||||||
../../kvt/[kvt_init/memory_only, kvt_walk],
|
../../kvt/[kvt_init/memory_only, kvt_walk],
|
||||||
".."/[base, base/base_desc],
|
".."/[base, base/base_desc]
|
||||||
./aristo_db/[common_desc, handlers_aristo, handlers_kvt]
|
|
||||||
|
|
||||||
import
|
|
||||||
../../aristo/aristo_init/memory_only as aristo_memory_only
|
|
||||||
|
|
||||||
# Caveat:
|
|
||||||
# additional direct include(s) -- not import(s) -- is placed near
|
|
||||||
# the end of this source file
|
|
||||||
|
|
||||||
# Annotation helper(s)
|
|
||||||
{.pragma: noRaise, gcsafe, raises: [].}
|
|
||||||
{.pragma: rlpRaise, gcsafe, raises: [AristoApiRlpError].}
|
|
||||||
|
|
||||||
export
|
|
||||||
AristoApiRlpError,
|
|
||||||
AristoCoreDbKvtBE,
|
|
||||||
isAristo
|
|
||||||
|
|
||||||
type
|
|
||||||
AristoCoreDbRef* = ref object of CoreDbRef
|
|
||||||
## Main descriptor
|
|
||||||
kdbBase: KvtBaseRef ## Kvt subsystem
|
|
||||||
adbBase: AristoBaseRef ## Aristo subsystem
|
|
||||||
#tracer: AristoTracerRef ## Currently active recorder
|
|
||||||
|
|
||||||
#AristoTracerRef = ref object of TraceRecorderRef
|
|
||||||
# ## Sub-handle for tracer
|
|
||||||
# parent: AristoCoreDbRef
|
|
||||||
|
|
||||||
proc newAristoVoidCoreDbRef*(): CoreDbRef {.noRaise.}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private tx and base methods
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc txMethods(
|
|
||||||
db: AristoCoreDbRef;
|
|
||||||
aTx: AristoTxRef;
|
|
||||||
kTx: KvtTxRef;
|
|
||||||
): CoreDbTxFns =
|
|
||||||
## To be constructed by some `CoreDbBaseFns` function
|
|
||||||
let
|
|
||||||
adbBase = db.adbBase
|
|
||||||
kdbBase = db.kdbBase
|
|
||||||
|
|
||||||
adbApi = adbBase.api
|
|
||||||
kdbApi = kdbBase.api
|
|
||||||
|
|
||||||
CoreDbTxFns(
|
|
||||||
levelFn: proc(): int =
|
|
||||||
aTx.level,
|
|
||||||
|
|
||||||
commitFn: proc() =
|
|
||||||
const info = "commitFn()"
|
|
||||||
adbApi.commit(aTx).isOkOr:
|
|
||||||
raiseAssert info & ": " & $error
|
|
||||||
kdbApi.commit(kTx).isOkOr:
|
|
||||||
raiseAssert info & ": " & $error
|
|
||||||
discard,
|
|
||||||
|
|
||||||
rollbackFn: proc() =
|
|
||||||
const info = "rollbackFn()"
|
|
||||||
adbApi.rollback(aTx).isOkOr:
|
|
||||||
raiseAssert info & ": " & $error
|
|
||||||
kdbApi.rollback(kTx).isOkOr:
|
|
||||||
raiseAssert info & ": " & $error
|
|
||||||
discard,
|
|
||||||
|
|
||||||
disposeFn: proc() =
|
|
||||||
const info = "disposeFn()"
|
|
||||||
if adbApi.isTop(aTx):
|
|
||||||
adbApi.rollback(aTx).isOkOr:
|
|
||||||
raiseAssert info & ": " & $error
|
|
||||||
if kdbApi.isTop(kTx):
|
|
||||||
kdbApi.rollback(kTx).isOkOr:
|
|
||||||
raiseAssert info & ": " & $error
|
|
||||||
discard)
|
|
||||||
|
|
||||||
when false: # currently disabled
|
|
||||||
proc cptMethods(
|
|
||||||
tracer: AristoTracerRef;
|
|
||||||
): CoreDbCaptFns =
|
|
||||||
let
|
|
||||||
tr = tracer # So it can savely be captured
|
|
||||||
db = tr.parent # Will not change and can be captured
|
|
||||||
log = tr.topInst() # Ditto
|
|
||||||
|
|
||||||
CoreDbCaptFns(
|
|
||||||
recorderFn: proc(): CoreDbRef =
|
|
||||||
db,
|
|
||||||
|
|
||||||
logDbFn: proc(): TableRef[Blob,Blob] =
|
|
||||||
log.kLog,
|
|
||||||
|
|
||||||
getFlagsFn: proc(): set[CoreDbCaptFlags] =
|
|
||||||
log.flags,
|
|
||||||
|
|
||||||
forgetFn: proc() =
|
|
||||||
if not tracer.pop():
|
|
||||||
tr.parent.tracer = AristoTracerRef(nil)
|
|
||||||
tr.restore())
|
|
||||||
|
|
||||||
|
|
||||||
proc baseMethods(db: AristoCoreDbRef): CoreDbBaseFns =
|
|
||||||
let
|
|
||||||
aBase = db.adbBase
|
|
||||||
kBase = db.kdbBase
|
|
||||||
|
|
||||||
when false: # currently disabled
|
|
||||||
proc tracerSetup(flags: set[CoreDbCaptFlags]): CoreDbCaptRef =
|
|
||||||
if db.tracer.isNil:
|
|
||||||
db.tracer = AristoTracerRef(parent: db)
|
|
||||||
db.tracer.init(kBase, aBase, flags)
|
|
||||||
else:
|
|
||||||
db.tracer.push(flags)
|
|
||||||
CoreDbCaptRef(methods: db.tracer.cptMethods)
|
|
||||||
|
|
||||||
proc persistent(bn: Opt[BlockNumber]): CoreDbRc[void] =
|
|
||||||
const info = "persistentFn()"
|
|
||||||
let sid =
|
|
||||||
if bn.isNone: 0u64
|
|
||||||
else: bn.unsafeGet
|
|
||||||
? kBase.persistent info
|
|
||||||
? aBase.persistent(sid, info)
|
|
||||||
ok()
|
|
||||||
|
|
||||||
CoreDbBaseFns(
|
|
||||||
destroyFn: proc(eradicate: bool) =
|
|
||||||
aBase.destroy(eradicate)
|
|
||||||
kBase.destroy(eradicate),
|
|
||||||
|
|
||||||
levelFn: proc(): int =
|
|
||||||
aBase.getLevel,
|
|
||||||
|
|
||||||
errorPrintFn: proc(e: CoreDbErrorRef): string =
|
|
||||||
e.errorPrint(),
|
|
||||||
|
|
||||||
newKvtFn: proc(): CoreDbRc[CoreDbKvtRef] =
|
|
||||||
kBase.newKvtHandler("newKvtFn()"),
|
|
||||||
|
|
||||||
newCtxFn: proc(): CoreDbCtxRef =
|
|
||||||
aBase.ctx,
|
|
||||||
|
|
||||||
newCtxFromTxFn: proc(r: Hash256; k: CoreDbColType): CoreDbRc[CoreDbCtxRef] =
|
|
||||||
CoreDbCtxRef.init(db.adbBase, r, k),
|
|
||||||
|
|
||||||
swapCtxFn: proc(ctx: CoreDbCtxRef): CoreDbCtxRef =
|
|
||||||
aBase.swapCtx(ctx),
|
|
||||||
|
|
||||||
beginFn: proc(): CoreDbTxRef =
|
|
||||||
const info = "beginFn()"
|
|
||||||
let
|
|
||||||
aTx = aBase.txBegin info
|
|
||||||
kTx = kBase.txBegin info
|
|
||||||
dsc = CoreDbTxRef(methods: db.txMethods(aTx, kTx))
|
|
||||||
db.bless(dsc),
|
|
||||||
|
|
||||||
# # currently disabled
|
|
||||||
# newCaptureFn: proc(flags:set[CoreDbCaptFlags]): CoreDbRc[CoreDbCaptRef] =
|
|
||||||
# ok(db.bless flags.tracerSetup()),
|
|
||||||
|
|
||||||
persistentFn: proc(bn: Opt[BlockNumber]): CoreDbRc[void] =
|
|
||||||
persistent(bn))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public constructor and helper
|
# Public constructor and helper
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc create*(dbType: CoreDbType; kdb: KvtDbRef; adb: AristoDbRef): CoreDbRef =
|
proc create*(dbType: CoreDbType; kvt: KvtDbRef; mpt: AristoDbRef): CoreDbRef =
|
||||||
## Constructor helper
|
## Constructor helper
|
||||||
|
var db = CoreDbRef(dbType: dbType)
|
||||||
|
db.defCtx = db.bless CoreDbCtxRef(mpt: mpt, kvt: kvt)
|
||||||
|
|
||||||
# Local extensions
|
when CoreDbEnableApiTracking:
|
||||||
var db = AristoCoreDbRef()
|
db.kvtApi = KvtApiRef.init()
|
||||||
db.adbBase = AristoBaseRef.init(db, adb)
|
db.ariApi = AristoApiRef.init()
|
||||||
db.kdbBase = KvtBaseRef.init(db, kdb)
|
|
||||||
|
|
||||||
# Base descriptor
|
when CoreDbEnableApiProfiling:
|
||||||
db.dbType = dbType
|
block:
|
||||||
db.methods = db.baseMethods()
|
let profApi = KvtApiProfRef.init(db.kvtApi, kvt.backend)
|
||||||
db.bless()
|
db.kvtApi = profApi
|
||||||
|
kvt.backend = profApi.be
|
||||||
|
block:
|
||||||
|
let profApi = AristoApiProfRef.init(db.ariApi, mpt.backend)
|
||||||
|
db.ariApi = profApi
|
||||||
|
mpt.backend = profApi.be
|
||||||
|
bless db
|
||||||
|
|
||||||
proc newAristoMemoryCoreDbRef*(): CoreDbRef =
|
proc newAristoMemoryCoreDbRef*(): CoreDbRef =
|
||||||
AristoDbMemory.create(
|
result = AristoDbMemory.create(
|
||||||
KvtDbRef.init(use_kvt.MemBackendRef),
|
KvtDbRef.init(use_kvt.MemBackendRef),
|
||||||
AristoDbRef.init(use_ari.MemBackendRef))
|
AristoDbRef.init(use_ari.MemBackendRef))
|
||||||
|
|
||||||
|
@ -209,99 +51,6 @@ proc newAristoVoidCoreDbRef*(): CoreDbRef =
|
||||||
KvtDbRef.init(use_kvt.VoidBackendRef),
|
KvtDbRef.init(use_kvt.VoidBackendRef),
|
||||||
AristoDbRef.init(use_ari.VoidBackendRef))
|
AristoDbRef.init(use_ari.VoidBackendRef))
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public helpers, e.g. for direct backend access
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func toAristoProfData*(
|
|
||||||
db: CoreDbRef;
|
|
||||||
): tuple[aristo: AristoDbProfListRef, kvt: KvtDbProfListRef] =
|
|
||||||
when CoreDbEnableApiProfiling:
|
|
||||||
if db.isAristo:
|
|
||||||
result.aristo = db.AristoCoreDbRef.adbBase.api.AristoApiProfRef.data
|
|
||||||
result.kvt = db.AristoCoreDbRef.kdbBase.api.KvtApiProfRef.data
|
|
||||||
|
|
||||||
func toAristoApi*(kvt: CoreDbKvtRef): KvtApiRef =
|
|
||||||
if kvt.parent.isAristo:
|
|
||||||
return AristoCoreDbRef(kvt.parent).kdbBase.api
|
|
||||||
|
|
||||||
func toAristoApi*(mpt: CoreDbMptRef): AristoApiRef =
|
|
||||||
if mpt.parent.isAristo:
|
|
||||||
return mpt.to(AristoApiRef)
|
|
||||||
|
|
||||||
func toAristo*(kBe: CoreDbKvtBackendRef): KvtDbRef =
|
|
||||||
if not kBe.isNil and kBe.parent.isAristo:
|
|
||||||
return kBe.AristoCoreDbKvtBE.kdb
|
|
||||||
|
|
||||||
func toAristo*(mBe: CoreDbMptBackendRef): AristoDbRef =
|
|
||||||
if not mBe.isNil and mBe.parent.isAristo:
|
|
||||||
return mBe.AristoCoreDbMptBE.adb
|
|
||||||
|
|
||||||
func toAristo*(mBe: CoreDbAccBackendRef): AristoDbRef =
|
|
||||||
if not mBe.isNil and mBe.parent.isAristo:
|
|
||||||
return mBe.AristoCoreDbAccBE.adb
|
|
||||||
|
|
||||||
proc toAristoSavedStateBlockNumber*(
|
|
||||||
mBe: CoreDbMptBackendRef;
|
|
||||||
): BlockNumber =
|
|
||||||
if not mBe.isNil and mBe.parent.isAristo:
|
|
||||||
let rc = mBe.parent.AristoCoreDbRef.adbBase.getSavedState()
|
|
||||||
if rc.isOk:
|
|
||||||
return rc.value.serial.BlockNumber
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public aristo iterators
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
include
|
|
||||||
./aristo_db/aristo_replicate
|
|
||||||
|
|
||||||
# ------------------------
|
|
||||||
|
|
||||||
iterator aristoKvtPairsVoid*(dsc: CoreDbKvtRef): (Blob,Blob) {.rlpRaise.} =
|
|
||||||
let
|
|
||||||
api = dsc.toAristoApi()
|
|
||||||
p = api.forkTx(dsc.to(KvtDbRef),0).valueOrApiError "aristoKvtPairs()"
|
|
||||||
defer: discard api.forget(p)
|
|
||||||
for (k,v) in use_kvt.VoidBackendRef.walkPairs p:
|
|
||||||
yield (k,v)
|
|
||||||
|
|
||||||
iterator aristoKvtPairsMem*(dsc: CoreDbKvtRef): (Blob,Blob) {.rlpRaise.} =
|
|
||||||
let
|
|
||||||
api = dsc.toAristoApi()
|
|
||||||
p = api.forkTx(dsc.to(KvtDbRef),0).valueOrApiError "aristoKvtPairs()"
|
|
||||||
defer: discard api.forget(p)
|
|
||||||
for (k,v) in use_kvt.MemBackendRef.walkPairs p:
|
|
||||||
yield (k,v)
|
|
||||||
|
|
||||||
iterator aristoMptPairs*(dsc: CoreDbMptRef): (Blob,Blob) {.noRaise.} =
|
|
||||||
let
|
|
||||||
api = dsc.to(AristoApiRef)
|
|
||||||
mpt = dsc.to(AristoDbRef)
|
|
||||||
for (path,data) in mpt.rightPairsGeneric dsc.rootID:
|
|
||||||
yield (api.pathAsBlob(path), data)
|
|
||||||
|
|
||||||
iterator aristoSlotPairs*(
|
|
||||||
dsc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): (Blob,Blob)
|
|
||||||
{.noRaise.} =
|
|
||||||
let
|
|
||||||
api = dsc.to(AristoApiRef)
|
|
||||||
mpt = dsc.to(AristoDbRef)
|
|
||||||
for (path,data) in mpt.rightPairsStorage accPath:
|
|
||||||
yield (api.pathAsBlob(path), data)
|
|
||||||
|
|
||||||
iterator aristoReplicateMem*(dsc: CoreDbMptRef): (Blob,Blob) {.rlpRaise.} =
|
|
||||||
## Instantiation for `MemBackendRef`
|
|
||||||
for k,v in aristoReplicate[use_ari.MemBackendRef](dsc):
|
|
||||||
yield (k,v)
|
|
||||||
|
|
||||||
iterator aristoReplicateVoid*(dsc: CoreDbMptRef): (Blob,Blob) {.rlpRaise.} =
|
|
||||||
## Instantiation for `VoidBackendRef`
|
|
||||||
for k,v in aristoReplicate[use_ari.VoidBackendRef](dsc):
|
|
||||||
yield (k,v)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
* Refactor `handlers_tracer`. This module can reliably work only as a genuine
|
|
||||||
logger. The restore features were ill concieved, an attempt to be as close
|
|
||||||
as possible to the legacy tracer.
|
|
|
@ -1,40 +0,0 @@
|
||||||
# Nimbus
|
|
||||||
# Copyright (c) 2023-2024 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.
|
|
||||||
|
|
||||||
## Generic iterator, prototype to be included (rather than imported). Using
|
|
||||||
## an include file avoids duplicating code because the `T` argument is not
|
|
||||||
## bound to any object type. Otherwise all object types would be required
|
|
||||||
## when providing this iterator for import.
|
|
||||||
##
|
|
||||||
## This is not wanted here, because the import of a **pesistent** object
|
|
||||||
## would always require extra linking.
|
|
||||||
|
|
||||||
template valueOrApiError[U,V](rc: Result[U,V]; info: static[string]): U =
|
|
||||||
rc.valueOr: raise (ref AristoApiRlpError)(msg: info)
|
|
||||||
|
|
||||||
iterator aristoReplicate[T](
|
|
||||||
dsc: CoreDbMptRef;
|
|
||||||
): (Blob,Blob)
|
|
||||||
{.gcsafe, raises: [AristoApiRlpError].} =
|
|
||||||
## Generic iterator used for building dedicated backend iterators.
|
|
||||||
##
|
|
||||||
let
|
|
||||||
root = dsc.rootID
|
|
||||||
mpt = dsc.to(AristoDbRef)
|
|
||||||
api = dsc.to(AristoApiRef)
|
|
||||||
p = api.forkTx(mpt,0).valueOrApiError "aristoReplicate()"
|
|
||||||
defer: discard api.forget(p)
|
|
||||||
for (vid,key,vtx,node) in T.replicate(p):
|
|
||||||
if key.len == 32:
|
|
||||||
yield (@(key.data), node.encode)
|
|
||||||
elif vid == root:
|
|
||||||
yield (@(key.to(Hash256).data), node.encode)
|
|
||||||
|
|
||||||
# End
|
|
|
@ -1,62 +0,0 @@
|
||||||
# Nimbus
|
|
||||||
# Copyright (c) 2023-2024 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.
|
|
||||||
|
|
||||||
{.push raises: [].}
|
|
||||||
|
|
||||||
import
|
|
||||||
std/strutils,
|
|
||||||
../../../../errors,
|
|
||||||
"../../.."/[aristo, kvt],
|
|
||||||
../../base/base_desc
|
|
||||||
|
|
||||||
type
|
|
||||||
AristoApiRlpError* = object of CoreDbApiError
|
|
||||||
## For re-routing exceptions in iterator closure
|
|
||||||
|
|
||||||
AristoCoreDbError* = ref object of CoreDbErrorRef
|
|
||||||
## Error return code
|
|
||||||
ctx*: string ## Context where the exception or error occured
|
|
||||||
case isAristo*: bool
|
|
||||||
of true:
|
|
||||||
vid*: VertexID
|
|
||||||
aErr*: AristoError
|
|
||||||
else:
|
|
||||||
kErr*: KvtError
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public helpers
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func isAristo*(db: CoreDbRef): bool =
|
|
||||||
db.dbType in {AristoDbMemory, AristoDbRocks, AristoDbVoid}
|
|
||||||
|
|
||||||
func toStr*(n: VertexID): string =
|
|
||||||
result = "$"
|
|
||||||
if n.isValid:
|
|
||||||
result &= n.uint64.toHex.strip(
|
|
||||||
leading=true, trailing=false, chars={'0'}).toLowerAscii
|
|
||||||
else:
|
|
||||||
result &= "ø"
|
|
||||||
|
|
||||||
func errorPrint*(e: CoreDbErrorRef): string =
|
|
||||||
if not e.isNil:
|
|
||||||
let e = e.AristoCoreDbError
|
|
||||||
result = if e.isAristo: "Aristo" else: "Kvt"
|
|
||||||
result &= ", ctx=" & $e.ctx & ", "
|
|
||||||
if e.isAristo:
|
|
||||||
if e.vid.isValid:
|
|
||||||
result &= "vid=" & e.vid.toStr & ", "
|
|
||||||
result &= "error=" & $e.aErr
|
|
||||||
else:
|
|
||||||
result &= "error=" & $e.kErr
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# End
|
|
||||||
# ------------------------------------------------------------------------------
|
|
|
@ -1,580 +0,0 @@
|
||||||
# Nimbus
|
|
||||||
# Copyright (c) 2023-2024 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.
|
|
||||||
|
|
||||||
{.push raises: [].}
|
|
||||||
|
|
||||||
import
|
|
||||||
std/typetraits,
|
|
||||||
eth/common,
|
|
||||||
stew/byteutils,
|
|
||||||
../../../aristo,
|
|
||||||
../../../aristo/aristo_desc,
|
|
||||||
../../base,
|
|
||||||
../../base/base_desc,
|
|
||||||
./common_desc
|
|
||||||
|
|
||||||
type
|
|
||||||
AristoBaseRef* = ref object
|
|
||||||
parent: CoreDbRef ## Opaque top level descriptor
|
|
||||||
api*: AristoApiRef ## Api functions can be re-directed
|
|
||||||
ctx*: AristoCoreDbCtxRef ## Currently active context
|
|
||||||
|
|
||||||
AristoCoreDbCtxRef* = ref object of CoreDbCtxRef
|
|
||||||
base: AristoBaseRef ## Local base descriptor
|
|
||||||
mpt*: AristoDbRef ## Aristo MPT database
|
|
||||||
|
|
||||||
AristoCoreDbAccRef = ref object of CoreDbAccRef
|
|
||||||
base: AristoBaseRef ## Local base descriptor
|
|
||||||
|
|
||||||
AristoCoreDbMptRef = ref object of CoreDbMptRef
|
|
||||||
base: AristoBaseRef ## Local base descriptor
|
|
||||||
mptRoot: VertexID ## State root, may be zero unless account
|
|
||||||
|
|
||||||
AristoCoreDbMptBE* = ref object of CoreDbMptBackendRef
|
|
||||||
adb*: AristoDbRef
|
|
||||||
|
|
||||||
AristoCoreDbAccBE* = ref object of CoreDbAccBackendRef
|
|
||||||
adb*: AristoDbRef
|
|
||||||
|
|
||||||
static:
|
|
||||||
doAssert high(CoreDbColType).ord < LEAST_FREE_VID
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private helpers
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func toError(
|
|
||||||
e: AristoError;
|
|
||||||
base: AristoBaseRef;
|
|
||||||
info: string;
|
|
||||||
error = Unspecified;
|
|
||||||
): CoreDbErrorRef =
|
|
||||||
base.parent.bless(error, AristoCoreDbError(
|
|
||||||
ctx: info,
|
|
||||||
isAristo: true,
|
|
||||||
aErr: e))
|
|
||||||
|
|
||||||
func toError(
|
|
||||||
e: (VertexID,AristoError);
|
|
||||||
base: AristoBaseRef;
|
|
||||||
info: string;
|
|
||||||
error = Unspecified;
|
|
||||||
): CoreDbErrorRef =
|
|
||||||
base.parent.bless(error, AristoCoreDbError(
|
|
||||||
ctx: info,
|
|
||||||
isAristo: true,
|
|
||||||
vid: e[0],
|
|
||||||
aErr: e[1]))
|
|
||||||
|
|
||||||
func toRc[T](
|
|
||||||
rc: Result[T,AristoError];
|
|
||||||
base: AristoBaseRef;
|
|
||||||
info: string;
|
|
||||||
error = Unspecified;
|
|
||||||
): CoreDbRc[T] =
|
|
||||||
if rc.isOk:
|
|
||||||
when T is void:
|
|
||||||
return ok()
|
|
||||||
else:
|
|
||||||
return ok(rc.value)
|
|
||||||
err((VertexID(0),rc.error).toError(base, info, error))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private `MPT` call back functions
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc mptMethods(): CoreDbMptFns =
|
|
||||||
# These templates are a hack to remove a closure environment that was using
|
|
||||||
# hundreds of mb of memory to have this syntactic convenience
|
|
||||||
# TODO remove methods / abstraction entirely - it is no longer needed
|
|
||||||
template base: untyped = cMpt.base
|
|
||||||
template db: untyped = base.parent # Ditto
|
|
||||||
template api: untyped = base.api # Ditto
|
|
||||||
template mpt: untyped = base.ctx.mpt # Ditto
|
|
||||||
|
|
||||||
proc mptBackend(cMpt: AristoCoreDbMptRef): CoreDbMptBackendRef =
|
|
||||||
db.bless AristoCoreDbMptBE(adb: mpt)
|
|
||||||
|
|
||||||
proc mptFetch(cMpt: AristoCoreDbMptRef, key: openArray[byte]): CoreDbRc[Blob] =
|
|
||||||
const info = "fetchFn()"
|
|
||||||
let data = api.fetchGenericData(mpt, cMpt.mptRoot, key).valueOr:
|
|
||||||
if error == FetchPathNotFound:
|
|
||||||
return err(error.toError(base, info, MptNotFound))
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(data)
|
|
||||||
|
|
||||||
proc mptMerge(cMpt: AristoCoreDbMptRef, k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] =
|
|
||||||
const info = "mergeFn()"
|
|
||||||
api.mergeGenericData(mpt, cMpt.mptRoot, k, v).isOkOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc mptDelete(cMpt: AristoCoreDbMptRef, key: openArray[byte]): CoreDbRc[void] =
|
|
||||||
const info = "deleteFn()"
|
|
||||||
api.deleteGenericData(mpt, cMpt.mptRoot, key).isOkOr:
|
|
||||||
if error == DelPathNotFound:
|
|
||||||
return err(error.toError(base, info, MptNotFound))
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc mptHasPath(cMpt: AristoCoreDbMptRef, key: openArray[byte]): CoreDbRc[bool] =
|
|
||||||
const info = "hasPathFn()"
|
|
||||||
let yn = api.hasPathGeneric(mpt, cMpt.mptRoot, key).valueOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(yn)
|
|
||||||
|
|
||||||
proc mptState(cMpt: AristoCoreDbMptRef, updateOk: bool): CoreDbRc[Hash256] =
|
|
||||||
const info = "mptState()"
|
|
||||||
let state = api.fetchGenericState(mpt, cMpt.mptRoot, updateOk).valueOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(state)
|
|
||||||
|
|
||||||
## Generic columns database handlers
|
|
||||||
CoreDbMptFns(
|
|
||||||
backendFn: proc(cMpt: CoreDbMptRef): CoreDbMptBackendRef =
|
|
||||||
mptBackend(AristoCoreDbMptRef(cMpt)),
|
|
||||||
|
|
||||||
fetchFn: proc(cMpt: CoreDbMptRef, k: openArray[byte]): CoreDbRc[Blob] =
|
|
||||||
mptFetch(AristoCoreDbMptRef(cMpt), k),
|
|
||||||
|
|
||||||
deleteFn: proc(cMpt: CoreDbMptRef, k: openArray[byte]): CoreDbRc[void] =
|
|
||||||
mptDelete(AristoCoreDbMptRef(cMpt), k),
|
|
||||||
|
|
||||||
mergeFn: proc(cMpt: CoreDbMptRef, k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] =
|
|
||||||
mptMerge(AristoCoreDbMptRef(cMpt), k, v),
|
|
||||||
|
|
||||||
hasPathFn: proc(cMpt: CoreDbMptRef, k: openArray[byte]): CoreDbRc[bool] =
|
|
||||||
mptHasPath(AristoCoreDbMptRef(cMpt), k),
|
|
||||||
|
|
||||||
stateFn: proc(cMpt: CoreDbMptRef, updateOk: bool): CoreDbRc[Hash256] =
|
|
||||||
mptState(AristoCoreDbMptRef(cMpt), updateOk))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private account call back functions
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc accMethods(): CoreDbAccFns =
|
|
||||||
## Account columns database handlers
|
|
||||||
template base: untyped = cAcc.base
|
|
||||||
template db: untyped = base.parent
|
|
||||||
template api: untyped = base.api
|
|
||||||
template mpt: untyped = base.ctx.mpt
|
|
||||||
|
|
||||||
proc accBackend(cAcc: AristoCoreDbAccRef): CoreDbAccBackendRef =
|
|
||||||
db.bless AristoCoreDbAccBE(adb: mpt)
|
|
||||||
|
|
||||||
proc accFetch(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[CoreDbAccount] =
|
|
||||||
const info = "acc/fetchFn()"
|
|
||||||
|
|
||||||
let acc = api.fetchAccountRecord(mpt, accPath).valueOr:
|
|
||||||
if error != FetchPathNotFound:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
return err(error.toError(base, info, AccNotFound))
|
|
||||||
ok acc
|
|
||||||
|
|
||||||
proc accMerge(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
accRec: CoreDbAccount;
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
const info = "acc/mergeFn()"
|
|
||||||
|
|
||||||
let val = AristoAccount(
|
|
||||||
nonce: accRec.nonce,
|
|
||||||
balance: accRec.balance,
|
|
||||||
codeHash: accRec.codeHash)
|
|
||||||
api.mergeAccountRecord(mpt, accPath, val).isOkOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc accDelete(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
const info = "acc/deleteFn()"
|
|
||||||
|
|
||||||
api.deleteAccountRecord(mpt, accPath).isOkOr:
|
|
||||||
if error == DelPathNotFound:
|
|
||||||
# TODO: Would it be conseqient to just return `ok()` here?
|
|
||||||
return err(error.toError(base, info, AccNotFound))
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc accClearStorage(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
const info = "acc/clearStoFn()"
|
|
||||||
|
|
||||||
api.deleteStorageTree(mpt, accPath).isOkOr:
|
|
||||||
if error notin {DelStoRootMissing,DelStoAccMissing}:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc accHasPath(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[bool] =
|
|
||||||
const info = "hasPathFn()"
|
|
||||||
|
|
||||||
let yn = api.hasPathAccount(mpt, accPath).valueOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(yn)
|
|
||||||
|
|
||||||
proc accState(
|
|
||||||
cAcc: AristoCoreDbAccRef,
|
|
||||||
updateOk: bool;
|
|
||||||
): CoreDbRc[Hash256] =
|
|
||||||
const info = "accStateFn()"
|
|
||||||
let state = api.fetchAccountState(mpt, updateOk).valueOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(state)
|
|
||||||
|
|
||||||
|
|
||||||
proc slotFetch(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[Blob] =
|
|
||||||
const info = "slotFetchFn()"
|
|
||||||
|
|
||||||
let data = api.fetchStorageData(mpt, accPath, stoPath).valueOr:
|
|
||||||
if error != FetchPathNotFound:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
return err(error.toError(base, info, StoNotFound))
|
|
||||||
ok(data)
|
|
||||||
|
|
||||||
proc slotDelete(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
const info = "slotDeleteFn()"
|
|
||||||
|
|
||||||
api.deleteStorageData(mpt, accPath, stoPath).isOkOr:
|
|
||||||
if error == DelPathNotFound:
|
|
||||||
return err(error.toError(base, info, StoNotFound))
|
|
||||||
if error == DelStoRootMissing:
|
|
||||||
# This is insane but legit. A storage column was announced for an
|
|
||||||
# account but no data have been added, yet.
|
|
||||||
return ok()
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc slotHasPath(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[bool] =
|
|
||||||
const info = "slotHasPathFn()"
|
|
||||||
|
|
||||||
let yn = api.hasPathStorage(mpt, accPath, stoPath).valueOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(yn)
|
|
||||||
|
|
||||||
proc slotMerge(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
stoData: openArray[byte];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
const info = "slotMergeFn()"
|
|
||||||
|
|
||||||
api.mergeStorageData(mpt, accPath, stoPath, stoData).isOkOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc slotState(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
updateOk: bool;
|
|
||||||
): CoreDbRc[Hash256] =
|
|
||||||
const info = "slotStateFn()"
|
|
||||||
let state = api.fetchStorageState(mpt, accPath, updateOk).valueOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(state)
|
|
||||||
|
|
||||||
proc slotStateEmpty(
|
|
||||||
cAcc: AristoCoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[bool] =
|
|
||||||
const info = "slotStateEmptyFn()"
|
|
||||||
|
|
||||||
let yn = api.hasStorageData(mpt, accPath).valueOr:
|
|
||||||
return err(error.toError(base, info))
|
|
||||||
ok(not yn)
|
|
||||||
|
|
||||||
|
|
||||||
CoreDbAccFns(
|
|
||||||
backendFn: proc(cAcc: CoreDbAccRef): CoreDbAccBackendRef =
|
|
||||||
accBackend(AristoCoreDbAccRef(cAcc)),
|
|
||||||
|
|
||||||
fetchFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[CoreDbAccount] =
|
|
||||||
accFetch(AristoCoreDbAccRef(cAcc), accPath),
|
|
||||||
|
|
||||||
deleteFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
accDelete(AristoCoreDbAccRef(cAcc), accPath),
|
|
||||||
|
|
||||||
clearStorageFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
accClearStorage(AristoCoreDbAccRef(cAcc), accPath),
|
|
||||||
|
|
||||||
mergeFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
accRec: CoreDbAccount;
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
accMerge(AristoCoreDbAccRef(cAcc), accPath, accRec),
|
|
||||||
|
|
||||||
hasPathFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[bool] =
|
|
||||||
accHasPath(AristoCoreDbAccRef(cAcc), accPath),
|
|
||||||
|
|
||||||
stateFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
updateOk: bool;
|
|
||||||
): CoreDbRc[Hash256] =
|
|
||||||
accState(AristoCoreDbAccRef(cAcc), updateOk),
|
|
||||||
|
|
||||||
slotFetchFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[Blob] =
|
|
||||||
slotFetch(AristoCoreDbAccRef(cAcc), accPath, stoPath),
|
|
||||||
|
|
||||||
slotDeleteFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
slotDelete(AristoCoreDbAccRef(cAcc), accPath, stoPath),
|
|
||||||
|
|
||||||
slotHasPathFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[bool] =
|
|
||||||
slotHasPath(AristoCoreDbAccRef(cAcc), accPath, stoPath),
|
|
||||||
|
|
||||||
slotMergeFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
stoPath: openArray[byte];
|
|
||||||
stoData: openArray[byte];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
slotMerge(AristoCoreDbAccRef(cAcc), accPath, stoPath, stoData),
|
|
||||||
|
|
||||||
slotStateFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
updateOk: bool;
|
|
||||||
): CoreDbRc[Hash256] =
|
|
||||||
slotState(AristoCoreDbAccRef(cAcc), accPath, updateOk),
|
|
||||||
|
|
||||||
slotStateEmptyFn: proc(
|
|
||||||
cAcc: CoreDbAccRef;
|
|
||||||
accPath: Hash256;
|
|
||||||
): CoreDbRc[bool] =
|
|
||||||
slotStateEmpty(AristoCoreDbAccRef(cAcc), accPath))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private context call back functions
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc ctxMethods(): CoreDbCtxFns =
|
|
||||||
template base: untyped = cCtx.base
|
|
||||||
template db: untyped = base.parent
|
|
||||||
template api: untyped = base.api
|
|
||||||
template mpt: untyped = cCtx.mpt
|
|
||||||
|
|
||||||
proc ctxGetColumn(cCtx: AristoCoreDbCtxRef; colType: CoreDbColType; clearData: bool): CoreDbMptRef =
|
|
||||||
const info = "getColumnFn()"
|
|
||||||
if clearData:
|
|
||||||
api.deleteGenericTree(mpt, VertexID(colType)).isOkOr:
|
|
||||||
raiseAssert info & " clearing up failed: " & $error
|
|
||||||
db.bless AristoCoreDbMptRef(
|
|
||||||
methods: mptMethods(),
|
|
||||||
base: base,
|
|
||||||
mptRoot: VertexID(colType))
|
|
||||||
|
|
||||||
proc ctxGetAccounts(cCtx: AristoCoreDbCtxRef): CoreDbAccRef =
|
|
||||||
db.bless AristoCoreDbAccRef(
|
|
||||||
methods: accMethods(),
|
|
||||||
base: base)
|
|
||||||
|
|
||||||
proc ctxForget(cCtx: AristoCoreDbCtxRef) =
|
|
||||||
api.forget(mpt).isOkOr:
|
|
||||||
raiseAssert "forgetFn(): " & $error
|
|
||||||
|
|
||||||
|
|
||||||
CoreDbCtxFns(
|
|
||||||
getColumnFn: proc(cCtx: CoreDbCtxRef; colType: CoreDbColType; clearData: bool): CoreDbMptRef =
|
|
||||||
ctxGetColumn(AristoCoreDbCtxRef(cCtx), colType, clearData),
|
|
||||||
|
|
||||||
getAccountsFn: proc(cCtx: CoreDbCtxRef): CoreDbAccRef =
|
|
||||||
ctxGetAccounts(AristoCoreDbCtxRef(cCtx)),
|
|
||||||
|
|
||||||
forgetFn: proc(cCtx: CoreDbCtxRef) =
|
|
||||||
ctxForget(AristoCoreDbCtxRef(cCtx)))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public handlers and helpers
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc getSavedState*(base: AristoBaseRef): Result[SavedState,void] =
|
|
||||||
let be = base.ctx.mpt.backend
|
|
||||||
if not be.isNil:
|
|
||||||
let rc = base.api.fetchLastSavedState(base.ctx.mpt)
|
|
||||||
if rc.isOk:
|
|
||||||
return ok(rc.value)
|
|
||||||
err()
|
|
||||||
|
|
||||||
# ---------------------
|
|
||||||
|
|
||||||
func to*(dsc: CoreDbMptRef, T: type AristoDbRef): T =
|
|
||||||
AristoCoreDbMptRef(dsc).base.ctx.mpt
|
|
||||||
|
|
||||||
func to*(dsc: CoreDbAccRef, T: type AristoDbRef): T =
|
|
||||||
AristoCoreDbAccRef(dsc).base.ctx.mpt
|
|
||||||
|
|
||||||
func to*(dsc: CoreDbMptRef, T: type AristoApiRef): T =
|
|
||||||
AristoCoreDbMptRef(dsc).base.api
|
|
||||||
|
|
||||||
func to*(dsc: CoreDbAccRef, T: type AristoApiRef): T =
|
|
||||||
AristoCoreDbAccRef(dsc).base.api
|
|
||||||
|
|
||||||
func rootID*(dsc: CoreDbMptRef): VertexID =
|
|
||||||
AristoCoreDbMptRef(dsc).mptRoot
|
|
||||||
|
|
||||||
func txTop*(
|
|
||||||
base: AristoBaseRef;
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[AristoTxRef] =
|
|
||||||
base.api.txTop(base.adb).toRc(base, info)
|
|
||||||
|
|
||||||
proc txBegin*(
|
|
||||||
base: AristoBaseRef;
|
|
||||||
info: static[string];
|
|
||||||
): AristoTxRef =
|
|
||||||
let rc = base.api.txBegin(base.ctx.mpt)
|
|
||||||
if rc.isErr:
|
|
||||||
raiseAssert info & ": " & $rc.error
|
|
||||||
rc.value
|
|
||||||
|
|
||||||
proc getLevel*(base: AristoBaseRef): int =
|
|
||||||
base.api.level(base.ctx.mpt)
|
|
||||||
|
|
||||||
# ---------------------
|
|
||||||
|
|
||||||
proc swapCtx*(base: AristoBaseRef; ctx: CoreDbCtxRef): CoreDbCtxRef =
|
|
||||||
doAssert not ctx.isNil
|
|
||||||
result = base.ctx
|
|
||||||
|
|
||||||
# Set read-write access and install
|
|
||||||
base.ctx = AristoCoreDbCtxRef(ctx)
|
|
||||||
base.api.reCentre(base.ctx.mpt).isOkOr:
|
|
||||||
raiseAssert "swapCtx() failed: " & $error
|
|
||||||
|
|
||||||
|
|
||||||
proc persistent*(
|
|
||||||
base: AristoBaseRef;
|
|
||||||
fid: uint64;
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
let
|
|
||||||
api = base.api
|
|
||||||
mpt = base.ctx.mpt
|
|
||||||
rc = api.persist(mpt, fid)
|
|
||||||
if rc.isOk:
|
|
||||||
ok()
|
|
||||||
elif api.level(mpt) == 0:
|
|
||||||
err(rc.error.toError(base, info))
|
|
||||||
else:
|
|
||||||
err(rc.error.toError(base, info, TxPending))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public constructors and related
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc destroy*(base: AristoBaseRef; eradicate: bool) =
|
|
||||||
base.api.finish(base.ctx.mpt, eradicate)
|
|
||||||
|
|
||||||
|
|
||||||
func init*(T: type AristoBaseRef; db: CoreDbRef; adb: AristoDbRef): T =
|
|
||||||
result = T(
|
|
||||||
parent: db,
|
|
||||||
api: AristoApiRef.init())
|
|
||||||
|
|
||||||
# Create initial context
|
|
||||||
let ctx = AristoCoreDbCtxRef(
|
|
||||||
methods: ctxMethods(),
|
|
||||||
base: result,
|
|
||||||
mpt: adb)
|
|
||||||
result.ctx = db.bless ctx
|
|
||||||
|
|
||||||
when CoreDbEnableApiProfiling:
|
|
||||||
let profApi = AristoApiProfRef.init(result.api, adb.backend)
|
|
||||||
result.api = profApi
|
|
||||||
result.ctx.mpt.backend = profApi.be
|
|
||||||
|
|
||||||
|
|
||||||
proc init*(
|
|
||||||
T: type CoreDbCtxRef;
|
|
||||||
base: AristoBaseRef;
|
|
||||||
colState: Hash256;
|
|
||||||
colType: CoreDbColType;
|
|
||||||
): CoreDbRc[CoreDbCtxRef] =
|
|
||||||
const info = "fromTxFn()"
|
|
||||||
|
|
||||||
if colType.ord == 0:
|
|
||||||
return err(aristo.GenericError.toError(base, info, ColUnacceptable))
|
|
||||||
let
|
|
||||||
api = base.api
|
|
||||||
vid = VertexID(colType)
|
|
||||||
key = colState.to(HashKey)
|
|
||||||
|
|
||||||
# Find `(vid,key)` on transaction stack
|
|
||||||
inx = block:
|
|
||||||
let rc = api.findTx(base.ctx.mpt, vid, key)
|
|
||||||
if rc.isErr:
|
|
||||||
return err(rc.error.toError(base, info))
|
|
||||||
rc.value
|
|
||||||
|
|
||||||
# Fork MPT descriptor that provides `(vid,key)`
|
|
||||||
newMpt = block:
|
|
||||||
let rc = api.forkTx(base.ctx.mpt, inx)
|
|
||||||
if rc.isErr:
|
|
||||||
return err(rc.error.toError(base, info))
|
|
||||||
rc.value
|
|
||||||
|
|
||||||
# Create new context
|
|
||||||
let ctx = AristoCoreDbCtxRef(
|
|
||||||
methods: ctxMethods(),
|
|
||||||
base: base,
|
|
||||||
mpt: newMpt)
|
|
||||||
ok(base.parent.bless ctx)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# End
|
|
||||||
# ------------------------------------------------------------------------------
|
|
|
@ -1,266 +0,0 @@
|
||||||
# Nimbus
|
|
||||||
# Copyright (c) 2023-2024 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.
|
|
||||||
|
|
||||||
{.push raises: [].}
|
|
||||||
|
|
||||||
import
|
|
||||||
chronicles,
|
|
||||||
eth/common,
|
|
||||||
results,
|
|
||||||
../../../kvt as use_kvt,
|
|
||||||
../../base,
|
|
||||||
../../base/base_desc,
|
|
||||||
./common_desc
|
|
||||||
|
|
||||||
type
|
|
||||||
KvtBaseRef* = ref object
|
|
||||||
parent: CoreDbRef ## Opaque top level descriptor
|
|
||||||
kdb: KvtDbRef ## Shared key-value table
|
|
||||||
api*: KvtApiRef ## Api functions can be re-directed
|
|
||||||
cache: KvtCoreDbKvtRef ## Shared transaction table wrapper
|
|
||||||
|
|
||||||
KvtCoreDbKvtRef = ref object of CoreDbKvtRef
|
|
||||||
base: KvtBaseRef ## Local base descriptor
|
|
||||||
kvt: KvtDbRef ## In most cases different from `base.kdb`
|
|
||||||
|
|
||||||
AristoCoreDbKvtBE* = ref object of CoreDbKvtBackendRef
|
|
||||||
kdb*: KvtDbRef
|
|
||||||
|
|
||||||
logScope:
|
|
||||||
topics = "kvt-hdl"
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private helpers
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func toError(
|
|
||||||
e: KvtError;
|
|
||||||
base: KvtBaseRef;
|
|
||||||
info: string;
|
|
||||||
error = Unspecified;
|
|
||||||
): CoreDbErrorRef =
|
|
||||||
base.parent.bless(error, AristoCoreDbError(
|
|
||||||
ctx: info,
|
|
||||||
isAristo: false,
|
|
||||||
kErr: e))
|
|
||||||
|
|
||||||
func toRc[T](
|
|
||||||
rc: Result[T,KvtError];
|
|
||||||
base: KvtBaseRef;
|
|
||||||
info: string;
|
|
||||||
error = Unspecified;
|
|
||||||
): CoreDbRc[T] =
|
|
||||||
if rc.isOk:
|
|
||||||
when T is void:
|
|
||||||
return ok()
|
|
||||||
else:
|
|
||||||
return ok(rc.value)
|
|
||||||
err rc.error.toError(base, info, error)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private `kvt` call back functions
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc kvtMethods(cKvt: KvtCoreDbKvtRef): CoreDbKvtFns =
|
|
||||||
## Key-value database table handlers
|
|
||||||
|
|
||||||
proc kvtBackend(
|
|
||||||
cKvt:KvtCoreDbKvtRef;
|
|
||||||
): CoreDbKvtBackendRef =
|
|
||||||
cKvt.base.parent.bless AristoCoreDbKvtBE(kdb: cKvt.kvt)
|
|
||||||
|
|
||||||
proc kvtForget(
|
|
||||||
cKvt: KvtCoreDbKvtRef;
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
let
|
|
||||||
base = cKvt.base
|
|
||||||
kvt = cKvt.kvt
|
|
||||||
if kvt != base.kdb:
|
|
||||||
let rc = base.api.forget(kvt)
|
|
||||||
|
|
||||||
# There is not much that can be done in case of a `forget()` error.
|
|
||||||
# So unmark it anyway.
|
|
||||||
cKvt.kvt = KvtDbRef(nil)
|
|
||||||
|
|
||||||
if rc.isErr:
|
|
||||||
return err(rc.error.toError(base, info))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc kvtGet(
|
|
||||||
cKvt: KvtCoreDbKvtRef;
|
|
||||||
k: openArray[byte];
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[Blob] =
|
|
||||||
let rc = cKvt.base.api.get(cKvt.kvt, k)
|
|
||||||
if rc.isOk:
|
|
||||||
ok(rc.value)
|
|
||||||
elif rc.error == GetNotFound:
|
|
||||||
err(rc.error.toError(cKvt.base, info, KvtNotFound))
|
|
||||||
else:
|
|
||||||
rc.toRc(cKvt.base, info)
|
|
||||||
|
|
||||||
proc kvtLen(
|
|
||||||
cKvt: KvtCoreDbKvtRef;
|
|
||||||
k: openArray[byte];
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[int] =
|
|
||||||
let rc = cKvt.base.api.len(cKvt.kvt, k)
|
|
||||||
if rc.isOk:
|
|
||||||
ok(rc.value)
|
|
||||||
elif rc.error == GetNotFound:
|
|
||||||
err(rc.error.toError(cKvt.base, info, KvtNotFound))
|
|
||||||
else:
|
|
||||||
rc.toRc(cKvt.base, info)
|
|
||||||
|
|
||||||
proc kvtPut(
|
|
||||||
cKvt: KvtCoreDbKvtRef;
|
|
||||||
k: openArray[byte];
|
|
||||||
v: openArray[byte];
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
let rc = cKvt.base.api.put(cKvt.kvt, k, v)
|
|
||||||
if rc.isOk:
|
|
||||||
ok()
|
|
||||||
else:
|
|
||||||
err(rc.error.toError(cKvt.base, info))
|
|
||||||
|
|
||||||
proc kvtDel(
|
|
||||||
cKvt: KvtCoreDbKvtRef;
|
|
||||||
k: openArray[byte];
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
let rc = cKvt.base.api.del(cKvt.kvt, k)
|
|
||||||
if rc.isOk:
|
|
||||||
ok()
|
|
||||||
else:
|
|
||||||
err(rc.error.toError(cKvt.base, info))
|
|
||||||
|
|
||||||
proc kvtHasKey(
|
|
||||||
cKvt: KvtCoreDbKvtRef;
|
|
||||||
k: openArray[byte];
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[bool] =
|
|
||||||
let rc = cKvt.base.api.hasKey(cKvt.kvt, k)
|
|
||||||
if rc.isOk:
|
|
||||||
ok(rc.value)
|
|
||||||
else:
|
|
||||||
err(rc.error.toError(cKvt.base, info))
|
|
||||||
|
|
||||||
CoreDbKvtFns(
|
|
||||||
backendFn: proc(): CoreDbKvtBackendRef =
|
|
||||||
cKvt.kvtBackend(),
|
|
||||||
|
|
||||||
getFn: proc(k: openArray[byte]): CoreDbRc[Blob] =
|
|
||||||
cKvt.kvtGet(k, "getFn()"),
|
|
||||||
|
|
||||||
lenFn: proc(k: openArray[byte]): CoreDbRc[int] =
|
|
||||||
cKvt.kvtLen(k, "lenFn()"),
|
|
||||||
|
|
||||||
delFn: proc(k: openArray[byte]): CoreDbRc[void] =
|
|
||||||
cKvt.kvtDel(k, "delFn()"),
|
|
||||||
|
|
||||||
putFn: proc(k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] =
|
|
||||||
cKvt.kvtPut(k, v, "putFn()"),
|
|
||||||
|
|
||||||
hasKeyFn: proc(k: openArray[byte]): CoreDbRc[bool] =
|
|
||||||
cKvt.kvtHasKey(k, "hasKeyFn()"),
|
|
||||||
|
|
||||||
forgetFn: proc(): CoreDbRc[void] =
|
|
||||||
cKvt.kvtForget("forgetFn()"))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public handlers and helpers
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
func toVoidRc*[T](
|
|
||||||
rc: Result[T,KvtError];
|
|
||||||
base: KvtBaseRef;
|
|
||||||
info: string;
|
|
||||||
error = Unspecified;
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
if rc.isErr:
|
|
||||||
return err(rc.error.toError(base, info, error))
|
|
||||||
ok()
|
|
||||||
|
|
||||||
# ---------------------
|
|
||||||
|
|
||||||
func to*(dsc: CoreDbKvtRef; T: type KvtDbRef): T =
|
|
||||||
KvtCoreDbKvtRef(dsc).kvt
|
|
||||||
|
|
||||||
func txTop*(
|
|
||||||
base: KvtBaseRef;
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[KvtTxRef] =
|
|
||||||
base.api.txTop(base.kdb).toRc(base, info)
|
|
||||||
|
|
||||||
proc txBegin*(
|
|
||||||
base: KvtBaseRef;
|
|
||||||
info: static[string];
|
|
||||||
): KvtTxRef =
|
|
||||||
let rc = base.api.txBegin(base.kdb)
|
|
||||||
if rc.isErr:
|
|
||||||
raiseAssert info & ": " & $rc.error
|
|
||||||
rc.value
|
|
||||||
|
|
||||||
proc persistent*(
|
|
||||||
base: KvtBaseRef;
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[void] =
|
|
||||||
let
|
|
||||||
api = base.api
|
|
||||||
kvt = base.kdb
|
|
||||||
rc = api.persist(kvt)
|
|
||||||
if rc.isOk:
|
|
||||||
ok()
|
|
||||||
elif api.level(kvt) != 0:
|
|
||||||
err(rc.error.toError(base, info, TxPending))
|
|
||||||
elif rc.error == TxPersistDelayed:
|
|
||||||
# This is OK: Piggybacking on `Aristo` backend
|
|
||||||
ok()
|
|
||||||
else:
|
|
||||||
err(rc.error.toError(base, info))
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public constructors and related
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc newKvtHandler*(
|
|
||||||
base: KvtBaseRef;
|
|
||||||
info: static[string];
|
|
||||||
): CoreDbRc[CoreDbKvtRef] =
|
|
||||||
ok(base.cache)
|
|
||||||
|
|
||||||
|
|
||||||
proc destroy*(base: KvtBaseRef; eradicate: bool) =
|
|
||||||
base.api.finish(base.kdb, eradicate) # Close descriptor
|
|
||||||
|
|
||||||
|
|
||||||
func init*(T: type KvtBaseRef; db: CoreDbRef; kdb: KvtDbRef): T =
|
|
||||||
result = T(
|
|
||||||
parent: db,
|
|
||||||
api: KvtApiRef.init(),
|
|
||||||
kdb: kdb)
|
|
||||||
|
|
||||||
# Preallocated shared descriptor
|
|
||||||
let dsc = KvtCoreDbKvtRef(
|
|
||||||
base: result,
|
|
||||||
kvt: kdb)
|
|
||||||
dsc.methods = dsc.kvtMethods()
|
|
||||||
result.cache = db.bless dsc
|
|
||||||
|
|
||||||
when CoreDbEnableApiProfiling:
|
|
||||||
let profApi = KvtApiProfRef.init(result.api, kdb.backend)
|
|
||||||
result.api = profApi
|
|
||||||
result.kdb.backend = profApi.be
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# End
|
|
||||||
# ------------------------------------------------------------------------------
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Nimbus
|
||||||
|
# Copyright (c) 2023-2024 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.
|
||||||
|
|
||||||
|
## Generic iterator, prototype to be included (rather than imported). Using
|
||||||
|
## an include file avoids duplicating code because the `T` argument is not
|
||||||
|
## bound to any object type. Otherwise all object types would be required
|
||||||
|
## when providing this iterator for import.
|
||||||
|
##
|
||||||
|
## This is not wanted here, because the import of a **pesistent** object
|
||||||
|
## would always require extra linking.
|
||||||
|
|
||||||
|
template valueOrApiError[U,V](rc: Result[U,V]; info: static[string]): U =
|
||||||
|
rc.valueOr: raise (ref CoreDbApiError)(msg: info)
|
||||||
|
|
||||||
|
template dbType(dsc: CoreDbKvtRef | CoreDbMptRef | CoreDbAccRef): CoreDbType =
|
||||||
|
dsc.distinctBase.parent.dbType
|
||||||
|
|
||||||
|
# ---------------
|
||||||
|
|
||||||
|
template kvt(dsc: CoreDbKvtRef): KvtDbRef =
|
||||||
|
dsc.distinctBase.kvt
|
||||||
|
|
||||||
|
template call(api: KvtApiRef; fn: untyped; args: varArgs[untyped]): untyped =
|
||||||
|
when CoreDbEnableApiJumpTable:
|
||||||
|
api.fn(args)
|
||||||
|
else:
|
||||||
|
fn(args)
|
||||||
|
|
||||||
|
template call(kvt: CoreDbKvtRef; fn: untyped; args: varArgs[untyped]): untyped =
|
||||||
|
kvt.distinctBase.parent.kvtApi.call(fn, args)
|
||||||
|
|
||||||
|
# ---------------
|
||||||
|
|
||||||
|
template mpt(dsc: CoreDbAccRef | CoreDbMptRef): AristoDbRef =
|
||||||
|
dsc.distinctBase.mpt
|
||||||
|
|
||||||
|
template rootID(mpt: CoreDbMptRef): VertexID =
|
||||||
|
VertexID(CtGeneric)
|
||||||
|
|
||||||
|
template call(api: AristoApiRef; fn: untyped; args: varArgs[untyped]): untyped =
|
||||||
|
when CoreDbEnableApiJumpTable:
|
||||||
|
api.fn(args)
|
||||||
|
else:
|
||||||
|
fn(args)
|
||||||
|
|
||||||
|
template call(
|
||||||
|
acc: CoreDbAccRef | CoreDbMptRef;
|
||||||
|
fn: untyped;
|
||||||
|
args: varArgs[untyped];
|
||||||
|
): untyped =
|
||||||
|
acc.distinctBase.parent.ariApi.call(fn, args)
|
||||||
|
|
||||||
|
# ---------------
|
||||||
|
|
||||||
|
iterator aristoReplicate[T](
|
||||||
|
mpt: CoreDbMptRef;
|
||||||
|
): (Blob,Blob)
|
||||||
|
{.gcsafe, raises: [CoreDbApiError].} =
|
||||||
|
## Generic iterator used for building dedicated backend iterators.
|
||||||
|
##
|
||||||
|
let p = mpt.call(forkTx, mpt.mpt, 0).valueOrApiError "aristoReplicate()"
|
||||||
|
defer: discard mpt.call(forget, p)
|
||||||
|
for (vid,key,vtx,node) in T.replicate(p):
|
||||||
|
if key.len == 32:
|
||||||
|
yield (@(key.data), node.encode)
|
||||||
|
elif vid == mpt.rootID:
|
||||||
|
yield (@(key.to(Hash256).data), node.encode)
|
||||||
|
|
||||||
|
# End
|
|
@ -11,7 +11,6 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/sequtils,
|
|
||||||
eth/common,
|
eth/common,
|
||||||
rocksdb,
|
rocksdb,
|
||||||
results,
|
results,
|
||||||
|
@ -23,10 +22,9 @@ import
|
||||||
../../kvt/kvt_init/rocks_db/rdb_init,
|
../../kvt/kvt_init/rocks_db/rdb_init,
|
||||||
../base,
|
../base,
|
||||||
./aristo_db,
|
./aristo_db,
|
||||||
./aristo_db/[common_desc, handlers_aristo],
|
|
||||||
../../opts
|
../../opts
|
||||||
|
|
||||||
include ./aristo_db/aristo_replicate
|
include ./aristo_replicate
|
||||||
|
|
||||||
const
|
const
|
||||||
# Expectation messages
|
# Expectation messages
|
||||||
|
@ -34,7 +32,7 @@ const
|
||||||
kvtFail = "Kvt/RocksDB init() failed"
|
kvtFail = "Kvt/RocksDB init() failed"
|
||||||
|
|
||||||
# Annotation helper(s)
|
# Annotation helper(s)
|
||||||
{.pragma: rlpRaise, gcsafe, raises: [AristoApiRlpError].}
|
{.pragma: rlpRaise, gcsafe, raises: [CoreDbApiError].}
|
||||||
|
|
||||||
proc toRocksDb*(
|
proc toRocksDb*(
|
||||||
opts: DbOptions
|
opts: DbOptions
|
||||||
|
@ -172,15 +170,6 @@ proc newAristoDualRocksDbCoreDbRef*(path: string, opts: DbOptions): CoreDbRef =
|
||||||
raiseAssert kvtFail & ": " & $error
|
raiseAssert kvtFail & ": " & $error
|
||||||
AristoDbRocks.create(kdb, adb)
|
AristoDbRocks.create(kdb, adb)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Public aristo iterators
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
iterator aristoReplicateRdb*(dsc: CoreDbMptRef): (Blob, Blob) {.rlpRaise.} =
|
|
||||||
## Instantiation for `VoidBackendRef`
|
|
||||||
for k, v in aristoReplicate[use_ari.RdbBackendRef](dsc):
|
|
||||||
yield (k, v)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
# Nimbus
|
||||||
|
# Copyright (c) 2023-2024 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.
|
||||||
|
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
eth/common,
|
||||||
|
../../aristo as use_ari,
|
||||||
|
../../aristo/[aristo_walk],
|
||||||
|
../../kvt as use_kvt,
|
||||||
|
../../kvt/[kvt_init/memory_only, kvt_walk],
|
||||||
|
".."/[base, base/base_desc]
|
||||||
|
|
||||||
|
# Caveat:
|
||||||
|
# additional direct include(s) -- not import(s) -- is placed near
|
||||||
|
# the end of this source file
|
||||||
|
|
||||||
|
# Annotation helper(s)
|
||||||
|
{.pragma: noRaise, gcsafe, raises: [].}
|
||||||
|
{.pragma: rlpRaise, gcsafe, raises: [CoreDbApiError].}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Private functions, free parking
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
when false:
|
||||||
|
func toError(e: AristoError; s: string; error = Unspecified): CoreDbErrorRef =
|
||||||
|
CoreDbErrorRef(
|
||||||
|
error: error,
|
||||||
|
ctx: s,
|
||||||
|
isAristo: true,
|
||||||
|
aErr: e)
|
||||||
|
|
||||||
|
func toError(e: KvtError; s: string; error = Unspecified): CoreDbErrorRef =
|
||||||
|
CoreDbErrorRef(
|
||||||
|
error: error,
|
||||||
|
ctx: s,
|
||||||
|
isAristo: false,
|
||||||
|
kErr: e)
|
||||||
|
|
||||||
|
proc kvtForget(
|
||||||
|
cKvt: CoreDbKvtRef;
|
||||||
|
info: static[string];
|
||||||
|
): CoreDbRc[void] =
|
||||||
|
## Free parking here
|
||||||
|
let
|
||||||
|
base = cKvt.parent.kdbBase
|
||||||
|
kvt = cKvt.kvt
|
||||||
|
if kvt != base.kdb:
|
||||||
|
let rc = base.api.forget(kvt)
|
||||||
|
|
||||||
|
# There is not much that can be done in case of a `forget()` error.
|
||||||
|
# So unmark it anyway.
|
||||||
|
cKvt.kvt = KvtDbRef(nil)
|
||||||
|
|
||||||
|
if rc.isErr:
|
||||||
|
return err(rc.error.toError(base, info))
|
||||||
|
ok()
|
||||||
|
|
||||||
|
proc cptMethods(
|
||||||
|
tracer: AristoTracerRef;
|
||||||
|
): CoreDbCaptFns =
|
||||||
|
## Free parking here -- currently disabled
|
||||||
|
let
|
||||||
|
tr = tracer # So it can savely be captured
|
||||||
|
db = tr.parent # Will not change and can be captured
|
||||||
|
log = tr.topInst() # Ditto
|
||||||
|
|
||||||
|
CoreDbCaptFns(
|
||||||
|
recorderFn: proc(): CoreDbRef =
|
||||||
|
db,
|
||||||
|
|
||||||
|
logDbFn: proc(): TableRef[Blob,Blob] =
|
||||||
|
log.kLog,
|
||||||
|
|
||||||
|
getFlagsFn: proc(): set[CoreDbCaptFlags] =
|
||||||
|
log.flags,
|
||||||
|
|
||||||
|
forgetFn: proc() =
|
||||||
|
if not tracer.pop():
|
||||||
|
tr.parent.tracer = AristoTracerRef(nil)
|
||||||
|
tr.restore())
|
||||||
|
|
||||||
|
proc tracerSetup(flags: set[CoreDbCaptFlags]): CoreDbCaptRef =
|
||||||
|
## Free parking here -- currently disabled
|
||||||
|
if db.tracer.isNil:
|
||||||
|
db.tracer = AristoTracerRef(parent: db)
|
||||||
|
db.tracer.init(kBase, aBase, flags)
|
||||||
|
else:
|
||||||
|
db.tracer.push(flags)
|
||||||
|
CoreDbCaptRef(methods: db.tracer.cptMethods)
|
||||||
|
|
||||||
|
proc init(
|
||||||
|
T: type CoreDbCtxRef;
|
||||||
|
base: CoreDbAriBaseRef;
|
||||||
|
colState: Hash256;
|
||||||
|
colType: CoreDbColType;
|
||||||
|
): CoreDbRc[CoreDbCtxRef] =
|
||||||
|
const info = "fromTxFn()"
|
||||||
|
|
||||||
|
if colType.ord == 0:
|
||||||
|
return err(use_ari.GenericError.toError(base, info, ColUnacceptable))
|
||||||
|
let
|
||||||
|
api = base.api
|
||||||
|
vid = VertexID(colType)
|
||||||
|
key = colState.to(HashKey)
|
||||||
|
|
||||||
|
# Find `(vid,key)` on transaction stack
|
||||||
|
inx = block:
|
||||||
|
let rc = api.findTx(base.parent.ctx.CoreDbCtxRef.mpt, vid, key)
|
||||||
|
if rc.isErr:
|
||||||
|
return err(rc.error.toError(base, info))
|
||||||
|
rc.value
|
||||||
|
|
||||||
|
# Fork MPT descriptor that provides `(vid,key)`
|
||||||
|
newMpt = block:
|
||||||
|
let rc = api.forkTx(base.parent.ctx.CoreDbCtxRef.mpt, inx)
|
||||||
|
if rc.isErr:
|
||||||
|
return err(rc.error.toError(base, info))
|
||||||
|
rc.value
|
||||||
|
|
||||||
|
# Create new context
|
||||||
|
ok(base.parent.bless CoreDbCtxRef(mpt: newMpt))
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# End
|
||||||
|
# ------------------------------------------------------------------------------
|
File diff suppressed because it is too large
Load Diff
|
@ -20,21 +20,22 @@ import
|
||||||
|
|
||||||
type
|
type
|
||||||
CoreDbApiTrackRef* =
|
CoreDbApiTrackRef* =
|
||||||
CoreDbRef | CoreDbKvtRef |
|
# CoreDbCaptRef |
|
||||||
CoreDbCtxRef | CoreDbMptRef | CoreDbAccRef |
|
CoreDbRef | CoreDbKvtRef | CoreDbCtxRef | CoreDbMptRef | CoreDbAccRef |
|
||||||
CoreDbTxRef | CoreDbCaptRef | CoreDbErrorRef
|
CoreDbTxRef
|
||||||
|
|
||||||
CoreDbFnInx* = enum
|
CoreDbFnInx* = enum
|
||||||
## Profiling table index
|
## Profiling table index
|
||||||
SummaryItem = "total"
|
SummaryItem = "total"
|
||||||
|
|
||||||
|
AccClearStorageFn = "clearStorage"
|
||||||
AccDeleteFn = "acc/delete"
|
AccDeleteFn = "acc/delete"
|
||||||
AccFetchFn = "acc/fetch"
|
AccFetchFn = "acc/fetch"
|
||||||
AccForgetFn = "acc/forget"
|
AccForgetFn = "acc/forget"
|
||||||
AccHasPathFn = "acc/hasPath"
|
AccHasPathFn = "acc/hasPath"
|
||||||
AccMergeFn = "acc/merge"
|
AccMergeFn = "acc/merge"
|
||||||
|
AccRecastFn = "recast"
|
||||||
AccStateFn = "acc/state"
|
AccStateFn = "acc/state"
|
||||||
AccClearStorageFn = "acc/clearStorage"
|
|
||||||
|
|
||||||
AccSlotFetchFn = "slotFetch"
|
AccSlotFetchFn = "slotFetch"
|
||||||
AccSlotDeleteFn = "slotDelete"
|
AccSlotDeleteFn = "slotDelete"
|
||||||
|
@ -45,17 +46,13 @@ type
|
||||||
AccSlotStateEmptyOrVoidFn = "slotStateEmptyOrVoid"
|
AccSlotStateEmptyOrVoidFn = "slotStateEmptyOrVoid"
|
||||||
AccSlotPairsIt = "slotPairs"
|
AccSlotPairsIt = "slotPairs"
|
||||||
|
|
||||||
AnyBackendFn = "any/backend"
|
|
||||||
|
|
||||||
BaseDbTypeFn = "dbType"
|
|
||||||
BaseFinishFn = "finish"
|
BaseFinishFn = "finish"
|
||||||
BaseLevelFn = "level"
|
BaseLevelFn = "level"
|
||||||
BaseNewCaptureFn = "newCapture"
|
BaseNewCaptureFn = "newCapture"
|
||||||
BaseNewCtxFn = "ctx"
|
|
||||||
BaseNewCtxFromTxFn = "ctxFromTx"
|
BaseNewCtxFromTxFn = "ctxFromTx"
|
||||||
BaseNewKvtFn = "newKvt"
|
|
||||||
BaseNewTxFn = "newTransaction"
|
BaseNewTxFn = "newTransaction"
|
||||||
BasePersistentFn = "persistent"
|
BasePersistentFn = "persistent"
|
||||||
|
BaseStateBlockNumberFn = "stateBlockNumber"
|
||||||
BaseSwapCtxFn = "swapCtx"
|
BaseSwapCtxFn = "swapCtx"
|
||||||
|
|
||||||
CptFlagsFn = "cpt/flags"
|
CptFlagsFn = "cpt/flags"
|
||||||
|
@ -65,14 +62,9 @@ type
|
||||||
|
|
||||||
CtxForgetFn = "ctx/forget"
|
CtxForgetFn = "ctx/forget"
|
||||||
CtxGetAccountsFn = "getAccounts"
|
CtxGetAccountsFn = "getAccounts"
|
||||||
CtxGetColumnFn = "getColumn"
|
CtxGetGenericFn = "getGeneric"
|
||||||
CtxNewColFn = "ctx/newColumn"
|
|
||||||
|
|
||||||
ErrorPrintFn = "$$"
|
|
||||||
EthAccRecastFn = "recast"
|
|
||||||
|
|
||||||
KvtDelFn = "del"
|
KvtDelFn = "del"
|
||||||
KvtForgetFn = "forget"
|
|
||||||
KvtGetFn = "get"
|
KvtGetFn = "get"
|
||||||
KvtGetOrEmptyFn = "getOrEmpty"
|
KvtGetOrEmptyFn = "getOrEmpty"
|
||||||
KvtHasKeyFn = "hasKey"
|
KvtHasKeyFn = "hasKey"
|
||||||
|
@ -111,7 +103,11 @@ func toStr*(w: Hash256): string =
|
||||||
if w == EMPTY_ROOT_HASH: "EMPTY_ROOT_HASH" else: w.data.oaToStr
|
if w == EMPTY_ROOT_HASH: "EMPTY_ROOT_HASH" else: w.data.oaToStr
|
||||||
|
|
||||||
proc toStr*(e: CoreDbErrorRef): string =
|
proc toStr*(e: CoreDbErrorRef): string =
|
||||||
$e.error & "(" & e.parent.methods.errorPrintFn(e) & ")"
|
result = $e.error & "("
|
||||||
|
result &= (if e.isAristo: "Aristo" else: "Kvt")
|
||||||
|
result &= ", ctx=" & $e.ctx & ", error="
|
||||||
|
result &= (if e.isAristo: $e.aErr else: $e.kErr)
|
||||||
|
result &= ")"
|
||||||
|
|
||||||
func toLenStr*(w: openArray[byte]): string =
|
func toLenStr*(w: openArray[byte]): string =
|
||||||
if 0 < w.len and w.len < 5: "<" & w.oaToStr & ">"
|
if 0 < w.len and w.len < 5: "<" & w.oaToStr & ">"
|
||||||
|
@ -156,7 +152,7 @@ proc toStr*(rc: CoreDbRc[CoreDbRef]): string = rc.toStr "db"
|
||||||
proc toStr*(rc: CoreDbRc[CoreDbAccount]): string = rc.toStr "acc"
|
proc toStr*(rc: CoreDbRc[CoreDbAccount]): string = rc.toStr "acc"
|
||||||
proc toStr*(rc: CoreDbRc[CoreDbKvtRef]): string = rc.toStr "kvt"
|
proc toStr*(rc: CoreDbRc[CoreDbKvtRef]): string = rc.toStr "kvt"
|
||||||
proc toStr*(rc: CoreDbRc[CoreDbTxRef]): string = rc.toStr "tx"
|
proc toStr*(rc: CoreDbRc[CoreDbTxRef]): string = rc.toStr "tx"
|
||||||
proc toStr*(rc: CoreDbRc[CoreDbCaptRef]): string = rc.toStr "capt"
|
#proc toStr*(rc: CoreDbRc[CoreDbCaptRef]): string = rc.toStr "capt"
|
||||||
proc toStr*(rc: CoreDbRc[CoreDbCtxRef]): string = rc.toStr "ctx"
|
proc toStr*(rc: CoreDbRc[CoreDbCtxRef]): string = rc.toStr "ctx"
|
||||||
proc toStr*(rc: CoreDbRc[CoreDbMptRef]): string = rc.toStr "mpt"
|
proc toStr*(rc: CoreDbRc[CoreDbMptRef]): string = rc.toStr "mpt"
|
||||||
proc toStr*(rc: CoreDbRc[CoreDbAccRef]): string = rc.toStr "acc"
|
proc toStr*(rc: CoreDbRc[CoreDbAccRef]): string = rc.toStr "acc"
|
||||||
|
@ -177,9 +173,12 @@ template endNewApiIf*(w: CoreDbApiTrackRef; code: untyped) =
|
||||||
block body:
|
block body:
|
||||||
when typeof(w) is CoreDbRef:
|
when typeof(w) is CoreDbRef:
|
||||||
let db = w
|
let db = w
|
||||||
else:
|
elif typeof(w) is CoreDbTxRef:
|
||||||
|
let db = w.ctx.parent
|
||||||
if w.isNil: break body
|
if w.isNil: break body
|
||||||
let db = w.parent
|
else:
|
||||||
|
let db = w.distinctBase.parent
|
||||||
|
if w.distinctBase.isNil: break body
|
||||||
when CoreDbEnableApiProfiling:
|
when CoreDbEnableApiProfiling:
|
||||||
let elapsed {.inject,used.} = getTime() - bnaStart
|
let elapsed {.inject,used.} = getTime() - bnaStart
|
||||||
aristo_profile.update(db.profTab, bnaCtx.ord, elapsed)
|
aristo_profile.update(db.profTab, bnaCtx.ord, elapsed)
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/tables,
|
results,
|
||||||
eth/common,
|
|
||||||
../../aristo,
|
../../aristo,
|
||||||
|
../../kvt,
|
||||||
../../aristo/aristo_profile
|
../../aristo/aristo_profile
|
||||||
|
|
||||||
# Annotation helpers
|
# Annotation helpers
|
||||||
|
@ -59,261 +59,82 @@ type
|
||||||
StoNotFound
|
StoNotFound
|
||||||
TxPending
|
TxPending
|
||||||
|
|
||||||
CoreDbColType* = enum
|
CoreDbColType* = enum # Keep that legacy type for a while ..
|
||||||
CtGeneric = 2 # columns smaller than 2 are not provided
|
CtGeneric = 2 # Actually only this constant is needed
|
||||||
|
|
||||||
CoreDbCaptFlags* {.pure.} = enum
|
CoreDbCaptFlags* {.pure.} = enum
|
||||||
PersistPut
|
PersistPut
|
||||||
PersistDel
|
PersistDel
|
||||||
|
|
||||||
# --------------------------------------------------
|
|
||||||
# Sub-descriptor: Misc methods for main descriptor
|
|
||||||
# --------------------------------------------------
|
|
||||||
CoreDbBaseDestroyFn* = proc(eradicate = true) {.noRaise.}
|
|
||||||
CoreDbBaseErrorPrintFn* = proc(e: CoreDbErrorRef): string {.noRaise.}
|
|
||||||
CoreDbBaseLevelFn* = proc(): int {.noRaise.}
|
|
||||||
CoreDbBaseNewKvtFn* = proc(): CoreDbRc[CoreDbKvtRef] {.noRaise.}
|
|
||||||
CoreDbBaseNewCtxFn* = proc(): CoreDbCtxRef {.noRaise.}
|
|
||||||
CoreDbBaseNewCtxFromTxFn* = proc(
|
|
||||||
colState: Hash256; kind: CoreDbColType): CoreDbRc[CoreDbCtxRef] {.noRaise.}
|
|
||||||
CoreDbBaseSwapCtxFn* = proc(ctx: CoreDbCtxRef): CoreDbCtxRef {.noRaise.}
|
|
||||||
CoreDbBaseTxBeginFn* = proc(): CoreDbTxRef {.noRaise.}
|
|
||||||
CoreDbBaseNewCaptFn* =
|
|
||||||
proc(flgs: set[CoreDbCaptFlags]): CoreDbRc[CoreDbCaptRef] {.noRaise.}
|
|
||||||
CoreDbBaseGetCaptFn* = proc(): CoreDbRc[CoreDbCaptRef] {.noRaise.}
|
|
||||||
CoreDbBasePersistentFn* =
|
|
||||||
proc(bn: Opt[BlockNumber]): CoreDbRc[void] {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbBaseFns* = object
|
|
||||||
destroyFn*: CoreDbBaseDestroyFn
|
|
||||||
errorPrintFn*: CoreDbBaseErrorPrintFn
|
|
||||||
levelFn*: CoreDbBaseLevelFn
|
|
||||||
|
|
||||||
# Kvt constructor
|
|
||||||
newKvtFn*: CoreDbBaseNewKvtFn
|
|
||||||
|
|
||||||
# MPT context constructor
|
|
||||||
newCtxFn*: CoreDbBaseNewCtxFn
|
|
||||||
newCtxFromTxFn*: CoreDbBaseNewCtxFromTxFn
|
|
||||||
swapCtxFn*: CoreDbBaseSwapCtxFn
|
|
||||||
|
|
||||||
# Transactions constructors
|
|
||||||
beginFn*: CoreDbBaseTxBeginFn
|
|
||||||
|
|
||||||
# Capture/tracer constructors
|
|
||||||
newCaptureFn*: CoreDbBaseNewCaptFn
|
|
||||||
|
|
||||||
# Save to disk
|
|
||||||
persistentFn*: CoreDbBasePersistentFn
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------
|
|
||||||
# Sub-descriptor: KVT methods
|
|
||||||
# --------------------------------------------------
|
|
||||||
CoreDbKvtBackendFn* = proc(): CoreDbKvtBackendRef {.noRaise.}
|
|
||||||
CoreDbKvtGetFn* = proc(k: openArray[byte]): CoreDbRc[Blob] {.noRaise.}
|
|
||||||
CoreDbKvtLenFn* = proc(k: openArray[byte]): CoreDbRc[int] {.noRaise.}
|
|
||||||
CoreDbKvtDelFn* = proc(k: openArray[byte]): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbKvtPutFn* =
|
|
||||||
proc(k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbKvtForgetFn* = proc(): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbKvtHasKeyFn* = proc(k: openArray[byte]): CoreDbRc[bool] {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbKvtFns* = object
|
|
||||||
## Methods for key-value table
|
|
||||||
backendFn*: CoreDbKvtBackendFn
|
|
||||||
getFn*: CoreDbKvtGetFn
|
|
||||||
lenFn*: CoreDbKvtLenFn
|
|
||||||
delFn*: CoreDbKvtDelFn
|
|
||||||
putFn*: CoreDbKvtPutFn
|
|
||||||
hasKeyFn*: CoreDbKvtHasKeyFn
|
|
||||||
forgetFn*: CoreDbKvtForgetFn
|
|
||||||
|
|
||||||
# --------------------------------------------------
|
|
||||||
# Sub-descriptor: MPT context methods
|
|
||||||
# --------------------------------------------------
|
|
||||||
CoreDbCtxGetColumnFn* = proc(
|
|
||||||
cCtx: CoreDbCtxRef; colType: CoreDbColType; clearData: bool): CoreDbMptRef {.noRaise.}
|
|
||||||
CoreDbCtxGetAccountsFn* = proc(cCtx: CoreDbCtxRef): CoreDbAccRef {.noRaise.}
|
|
||||||
CoreDbCtxForgetFn* = proc(cCtx: CoreDbCtxRef) {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbCtxFns* = object
|
|
||||||
## Methods for context maniulation
|
|
||||||
getColumnFn*: CoreDbCtxGetColumnFn
|
|
||||||
getAccountsFn*: CoreDbCtxGetAccountsFn
|
|
||||||
forgetFn*: CoreDbCtxForgetFn
|
|
||||||
|
|
||||||
# --------------------------------------------------
|
|
||||||
# Sub-descriptor: generic Mpt methods
|
|
||||||
# --------------------------------------------------
|
|
||||||
CoreDbMptBackendFn* = proc(cMpt: CoreDbMptRef): CoreDbMptBackendRef {.noRaise.}
|
|
||||||
CoreDbMptFetchFn* =
|
|
||||||
proc(cMpt: CoreDbMptRef, k: openArray[byte]): CoreDbRc[Blob] {.noRaise.}
|
|
||||||
CoreDbMptFetchAccountFn* =
|
|
||||||
proc(cMpt: CoreDbMptRef, k: openArray[byte]): CoreDbRc[CoreDbAccount] {.noRaise.}
|
|
||||||
CoreDbMptDeleteFn* =
|
|
||||||
proc(cMpt: CoreDbMptRef, k: openArray[byte]): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbMptMergeFn* =
|
|
||||||
proc(cMpt: CoreDbMptRef, k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbMptHasPathFn* = proc(cMpt: CoreDbMptRef, k: openArray[byte]): CoreDbRc[bool] {.noRaise.}
|
|
||||||
CoreDbMptStateFn* = proc(cMpt: CoreDbMptRef, updateOk: bool): CoreDbRc[Hash256] {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbMptFns* = object
|
|
||||||
## Methods for trie objects
|
|
||||||
backendFn*: CoreDbMptBackendFn
|
|
||||||
fetchFn*: CoreDbMptFetchFn
|
|
||||||
deleteFn*: CoreDbMptDeleteFn
|
|
||||||
mergeFn*: CoreDbMptMergeFn
|
|
||||||
hasPathFn*: CoreDbMptHasPathFn
|
|
||||||
stateFn*: CoreDbMptStateFn
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------
|
|
||||||
# Sub-descriptor: Account column methods
|
|
||||||
# ------------------------------------------------------
|
|
||||||
CoreDbAccBackendFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef): CoreDbAccBackendRef {.noRaise.}
|
|
||||||
CoreDbAccFetchFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256;
|
|
||||||
): CoreDbRc[CoreDbAccount] {.noRaise.}
|
|
||||||
CoreDbAccDeleteFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef, accPath: Hash256): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbAccClearStorageFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbAccMergeFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256; accRec: CoreDbAccount;
|
|
||||||
): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbAccHasPathFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256): CoreDbRc[bool] {.noRaise.}
|
|
||||||
CoreDbAccStateFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; updateOk: bool): CoreDbRc[Hash256] {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbSlotFetchFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256, stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[Blob] {.noRaise.}
|
|
||||||
CoreDbSlotDeleteFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256, stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbSlotHasPathFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256, stoPath: openArray[byte];
|
|
||||||
): CoreDbRc[bool] {.noRaise.}
|
|
||||||
CoreDbSlotMergeFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256, stoPath, stoData: openArray[byte];
|
|
||||||
): CoreDbRc[void] {.noRaise.}
|
|
||||||
CoreDbSlotStateFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256; updateOk: bool;
|
|
||||||
): CoreDbRc[Hash256] {.noRaise.}
|
|
||||||
CoreDbSlotStateEmptyFn* = proc(
|
|
||||||
cAcc: CoreDbAccRef; accPath: Hash256;
|
|
||||||
): CoreDbRc[bool] {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbAccFns* = object
|
|
||||||
## Methods for trie objects
|
|
||||||
backendFn*: CoreDbAccBackendFn
|
|
||||||
fetchFn*: CoreDbAccFetchFn
|
|
||||||
clearStorageFn*: CoreDbAccClearStorageFn
|
|
||||||
deleteFn*: CoreDbAccDeleteFn
|
|
||||||
hasPathFn*: CoreDbAccHasPathFn
|
|
||||||
mergeFn*: CoreDbAccMergeFn
|
|
||||||
stateFn*: CoreDbAccStateFn
|
|
||||||
|
|
||||||
slotFetchFn*: CoreDbSlotFetchFn
|
|
||||||
slotDeleteFn*: CoreDbSlotDeleteFn
|
|
||||||
slotHasPathFn*: CoreDbSlotHasPathFn
|
|
||||||
slotMergeFn*: CoreDbSlotMergeFn
|
|
||||||
slotStateFn*: CoreDbSlotStateFn
|
|
||||||
slotStateEmptyFn*: CoreDbSlotStateEmptyFn
|
|
||||||
|
|
||||||
# --------------------------------------------------
|
|
||||||
# Sub-descriptor: Transaction frame management
|
|
||||||
# --------------------------------------------------
|
|
||||||
CoreDbTxLevelFn* = proc(): int {.noRaise.}
|
|
||||||
CoreDbTxCommitFn* = proc() {.noRaise.}
|
|
||||||
CoreDbTxRollbackFn* = proc() {.noRaise.}
|
|
||||||
CoreDbTxDisposeFn* = proc() {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbTxFns* = object
|
|
||||||
levelFn*: CoreDbTxLevelFn
|
|
||||||
commitFn*: CoreDbTxCommitFn
|
|
||||||
rollbackFn*: CoreDbTxRollbackFn
|
|
||||||
disposeFn*: CoreDbTxDisposeFn
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------
|
|
||||||
# Sub-descriptor: capture recorder methods
|
|
||||||
# --------------------------------------------------
|
|
||||||
CoreDbCaptRecorderFn* = proc(): CoreDbRef {.noRaise.}
|
|
||||||
CoreDbCaptLogDbFn* = proc(): TableRef[Blob,Blob] {.noRaise.}
|
|
||||||
CoreDbCaptFlagsFn* = proc(): set[CoreDbCaptFlags] {.noRaise.}
|
|
||||||
CoreDbCaptForgetFn* = proc() {.noRaise.}
|
|
||||||
|
|
||||||
CoreDbCaptFns* = object
|
|
||||||
recorderFn*: CoreDbCaptRecorderFn
|
|
||||||
logDbFn*: CoreDbCaptLogDbFn
|
|
||||||
getFlagsFn*: CoreDbCaptFlagsFn
|
|
||||||
forgetFn*: CoreDbCaptForgetFn
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# Production descriptors
|
# Production descriptors
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
CoreDbRef* = ref object of RootRef
|
CoreDbRef* = ref object
|
||||||
## Database descriptor
|
## Database descriptor
|
||||||
dbType*: CoreDbType ## Type of database backend
|
dbType*: CoreDbType ## Type of database backend
|
||||||
|
defCtx*: CoreDbCtxRef ## Default context
|
||||||
|
|
||||||
|
# Optional api interface (can be re-directed/intercepted)
|
||||||
|
ariApi*: AristoApiRef ## `Aristo` api
|
||||||
|
kvtApi*: KvtApiRef ## `KVT` api
|
||||||
|
|
||||||
|
# Optional profiling and debugging stuff
|
||||||
trackNewApi*: bool ## Debugging, support
|
trackNewApi*: bool ## Debugging, support
|
||||||
trackLedgerApi*: bool ## Debugging, suggestion for subsequent ledger
|
trackLedgerApi*: bool ## Debugging, suggestion for subsequent ledger
|
||||||
profTab*: CoreDbProfListRef ## Profiling data (if any)
|
profTab*: CoreDbProfListRef ## Profiling data (if any)
|
||||||
ledgerHook*: RootRef ## Debugging/profiling, to be used by ledger
|
ledgerHook*: RootRef ## Debugging/profiling, to be used by ledger
|
||||||
methods*: CoreDbBaseFns
|
|
||||||
|
|
||||||
CoreDbErrorRef* = ref object of RootRef
|
CoreDbCtxRef* = ref object
|
||||||
|
## Shared context for `CoreDbMptRef`, `CoreDbAccRef`, `CoreDbKvtRef`
|
||||||
|
parent*: CoreDbRef
|
||||||
|
mpt*: AristoDbRef ## `Aristo` database
|
||||||
|
kvt*: KvtDbRef ## `KVT` key-value table
|
||||||
|
|
||||||
|
CoreDbKvtRef* = distinct CoreDbCtxRef
|
||||||
|
## Statically initialised Key-Value pair table
|
||||||
|
|
||||||
|
CoreDbAccRef* = distinct CoreDbCtxRef
|
||||||
|
## Similar to `CoreDbKvtRef`, only dealing with `Aristo` accounts
|
||||||
|
|
||||||
|
CoreDbMptRef* = distinct CoreDbCtxRef
|
||||||
|
## Generic MPT
|
||||||
|
|
||||||
|
CoreDbTxRef* = ref object
|
||||||
|
## Transaction descriptor
|
||||||
|
ctx*: CoreDbCtxRef ## Context (also contains `Aristo` descriptor)
|
||||||
|
aTx*: AristoTxRef ## `Aristo` transaction (if any)
|
||||||
|
kTx*: KvtTxRef ## `KVT` transaction (if any)
|
||||||
|
|
||||||
|
CoreDbErrorRef* = ref object
|
||||||
## Generic error object
|
## Generic error object
|
||||||
error*: CoreDbErrorCode
|
error*: CoreDbErrorCode
|
||||||
parent*: CoreDbRef
|
ctx*: string ## Context where the exception or error occured
|
||||||
|
case isAristo*: bool
|
||||||
|
of true:
|
||||||
|
aErr*: AristoError
|
||||||
|
else:
|
||||||
|
kErr*: KvtError
|
||||||
|
|
||||||
CoreDbKvtBackendRef* = ref object of RootRef
|
when false: # TODO
|
||||||
## Backend wrapper for direct backend access
|
type
|
||||||
parent*: CoreDbRef
|
# --------------------------------------------------
|
||||||
|
# Sub-descriptor: capture recorder methods
|
||||||
|
# --------------------------------------------------
|
||||||
|
CoreDbCaptRecorderFn* = proc(): CoreDbRef {.noRaise.}
|
||||||
|
CoreDbCaptLogDbFn* = proc(): TableRef[Blob,Blob] {.noRaise.}
|
||||||
|
CoreDbCaptFlagsFn* = proc(): set[CoreDbCaptFlags] {.noRaise.}
|
||||||
|
CoreDbCaptForgetFn* = proc() {.noRaise.}
|
||||||
|
|
||||||
CoreDbMptBackendRef* = ref object of RootRef
|
CoreDbCaptFns* = object
|
||||||
## Backend wrapper for direct backend access
|
recorderFn*: CoreDbCaptRecorderFn
|
||||||
parent*: CoreDbRef
|
logDbFn*: CoreDbCaptLogDbFn
|
||||||
|
getFlagsFn*: CoreDbCaptFlagsFn
|
||||||
|
forgetFn*: CoreDbCaptForgetFn
|
||||||
|
|
||||||
CoreDbAccBackendRef* = ref object of RootRef
|
CoreDbCaptRef* = ref object
|
||||||
## Backend wrapper for direct backend access
|
## Db transaction tracer derived from `CoreDbRef`
|
||||||
parent*: CoreDbRef
|
parent*: CoreDbRef
|
||||||
|
methods*: CoreDbCaptFns
|
||||||
CoreDbKvtRef* = ref object of RootRef
|
|
||||||
## Statically initialised Key-Value pair table living in `CoreDbRef`
|
|
||||||
parent*: CoreDbRef
|
|
||||||
methods*: CoreDbKvtFns
|
|
||||||
|
|
||||||
CoreDbCtxRef* = ref object of RootRef
|
|
||||||
## Context for `CoreDbMptRef` and `CoreDbAccRef`
|
|
||||||
parent*: CoreDbRef
|
|
||||||
methods*: CoreDbCtxFns
|
|
||||||
|
|
||||||
CoreDbMptRef* = ref object of RootRef
|
|
||||||
## Hexary/Merkle-Patricia tree derived from `CoreDbRef`, will be
|
|
||||||
## initialised on-the-fly.
|
|
||||||
parent*: CoreDbRef
|
|
||||||
methods*: CoreDbMptFns
|
|
||||||
|
|
||||||
CoreDbAccRef* = ref object of RootRef
|
|
||||||
## Similar to `CoreDbKvtRef`, only dealing with `CoreDbAccount` data
|
|
||||||
## rather than `Blob` values.
|
|
||||||
parent*: CoreDbRef
|
|
||||||
methods*: CoreDbAccFns
|
|
||||||
|
|
||||||
CoreDbTxRef* = ref object of RootRef
|
|
||||||
## Transaction descriptor derived from `CoreDbRef`
|
|
||||||
parent*: CoreDbRef
|
|
||||||
methods*: CoreDbTxFns
|
|
||||||
|
|
||||||
CoreDbCaptRef* = ref object
|
|
||||||
## Db transaction tracer derived from `CoreDbRef`
|
|
||||||
parent*: CoreDbRef
|
|
||||||
methods*: CoreDbCaptFns
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
|
|
@ -10,135 +10,47 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
|
../../aristo,
|
||||||
./base_desc
|
./base_desc
|
||||||
|
|
||||||
type
|
type
|
||||||
EphemMethodsDesc =
|
ValidateSubDesc* = CoreDbCtxRef | CoreDbTxRef # | CoreDbCaptRef
|
||||||
CoreDbKvtBackendRef | CoreDbMptBackendRef | CoreDbAccBackendRef
|
|
||||||
|
|
||||||
MethodsDesc =
|
|
||||||
CoreDbKvtRef |
|
|
||||||
CoreDbCtxRef | CoreDbMptRef | CoreDbAccRef |
|
|
||||||
CoreDbTxRef |
|
|
||||||
CoreDbCaptRef
|
|
||||||
|
|
||||||
ValidateDesc* = MethodsDesc | EphemMethodsDesc | CoreDbErrorRef
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private helpers
|
# Private helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc validateMethodsDesc(base: CoreDbBaseFns) =
|
proc validateSubDescRef(ctx: CoreDbCtxRef) =
|
||||||
doAssert not base.destroyFn.isNil
|
|
||||||
doAssert not base.errorPrintFn.isNil
|
|
||||||
doAssert not base.levelFn.isNil
|
|
||||||
doAssert not base.newKvtFn.isNil
|
|
||||||
doAssert not base.newCtxFn.isNil
|
|
||||||
doAssert not base.newCtxFromTxFn.isNil
|
|
||||||
doAssert not base.swapCtxFn.isNil
|
|
||||||
doAssert not base.beginFn.isNil
|
|
||||||
# doAssert not base.newCaptureFn.isNil # currently disabled
|
|
||||||
doAssert not base.persistentFn.isNil
|
|
||||||
|
|
||||||
proc validateMethodsDesc(kvt: CoreDbKvtFns) =
|
|
||||||
doAssert not kvt.backendFn.isNil
|
|
||||||
doAssert not kvt.getFn.isNil
|
|
||||||
doAssert not kvt.lenFn.isNil
|
|
||||||
doAssert not kvt.delFn.isNil
|
|
||||||
doAssert not kvt.putFn.isNil
|
|
||||||
doAssert not kvt.hasKeyFn.isNil
|
|
||||||
doAssert not kvt.forgetFn.isNil
|
|
||||||
|
|
||||||
proc validateMethodsDesc(ctx: CoreDbCtxFns) =
|
|
||||||
doAssert not ctx.getAccountsFn.isNil
|
|
||||||
doAssert not ctx.getColumnFn.isNil
|
|
||||||
doAssert not ctx.forgetFn.isNil
|
|
||||||
|
|
||||||
proc validateMethodsDesc(fns: CoreDbMptFns) =
|
|
||||||
doAssert not fns.backendFn.isNil
|
|
||||||
doAssert not fns.fetchFn.isNil
|
|
||||||
doAssert not fns.deleteFn.isNil
|
|
||||||
doAssert not fns.mergeFn.isNil
|
|
||||||
doAssert not fns.hasPathFn.isNil
|
|
||||||
doAssert not fns.stateFn.isNil
|
|
||||||
|
|
||||||
proc validateMethodsDesc(fns: CoreDbAccFns) =
|
|
||||||
doAssert not fns.backendFn.isNil
|
|
||||||
doAssert not fns.fetchFn.isNil
|
|
||||||
doAssert not fns.clearStorageFn.isNil
|
|
||||||
doAssert not fns.deleteFn.isNil
|
|
||||||
doAssert not fns.hasPathFn.isNil
|
|
||||||
doAssert not fns.mergeFn.isNil
|
|
||||||
doAssert not fns.stateFn.isNil
|
|
||||||
|
|
||||||
doAssert not fns.slotFetchFn.isNil
|
|
||||||
doAssert not fns.slotDeleteFn.isNil
|
|
||||||
doAssert not fns.slotHasPathFn.isNil
|
|
||||||
doAssert not fns.slotMergeFn.isNil
|
|
||||||
doAssert not fns.slotStateFn.isNil
|
|
||||||
doAssert not fns.slotStateEmptyFn.isNil
|
|
||||||
|
|
||||||
# ------------
|
|
||||||
|
|
||||||
proc validateMethodsDesc(e: CoreDbErrorRef) =
|
|
||||||
doAssert e.error != CoreDbErrorCode(0)
|
|
||||||
doAssert not e.isNil
|
|
||||||
doAssert not e.parent.isNil
|
|
||||||
|
|
||||||
proc validateMethodsDesc(eph: EphemMethodsDesc) =
|
|
||||||
doAssert not eph.isNil
|
|
||||||
doAssert not eph.parent.isNil
|
|
||||||
|
|
||||||
proc validateMethodsDesc(kvt: CoreDbKvtRef) =
|
|
||||||
doAssert not kvt.isNil
|
|
||||||
doAssert not kvt.parent.isNil
|
|
||||||
kvt.methods.validateMethodsDesc
|
|
||||||
|
|
||||||
proc validateMethodsDesc(ctx: CoreDbCtxRef) =
|
|
||||||
doAssert not ctx.isNil
|
doAssert not ctx.isNil
|
||||||
doAssert not ctx.parent.isNil
|
doAssert not ctx.parent.isNil
|
||||||
ctx.methods.validateMethodsDesc
|
doAssert not ctx.mpt.isNil
|
||||||
|
doAssert not ctx.kvt.isNil
|
||||||
|
|
||||||
proc validateMethodsDesc(mpt: CoreDbMptRef) =
|
proc validateSubDescRef(tx: CoreDbTxRef) =
|
||||||
doAssert not mpt.isNil
|
doAssert not tx.isNil
|
||||||
doAssert not mpt.parent.isNil
|
doAssert not tx.ctx.isNil
|
||||||
mpt.methods.validateMethodsDesc
|
doAssert not tx.aTx.isNil
|
||||||
|
doAssert not tx.kTx.isNil
|
||||||
proc validateMethodsDesc(acc: CoreDbAccRef) =
|
|
||||||
doAssert not acc.isNil
|
|
||||||
doAssert not acc.parent.isNil
|
|
||||||
acc.methods.validateMethodsDesc
|
|
||||||
|
|
||||||
when false: # currently disabled
|
when false: # currently disabled
|
||||||
proc validateMethodsDesc(cpt: CoreDbCaptRef) =
|
proc validateSubDescRef(cpt: CoreDbCaptRef) =
|
||||||
doAssert not cpt.isNil
|
doAssert not cpt.isNil
|
||||||
doAssert not cpt.parent.isNil
|
doAssert not cpt.parent.isNil
|
||||||
doAssert not cpt.methods.recorderFn.isNil
|
doAssert not cpt.methods.recorderFn.isNil
|
||||||
doAssert not cpt.methods.getFlagsFn.isNil
|
doAssert not cpt.methods.getFlagsFn.isNil
|
||||||
doAssert not cpt.methods.forgetFn.isNil
|
doAssert not cpt.methods.forgetFn.isNil
|
||||||
|
|
||||||
proc validateMethodsDesc(tx: CoreDbTxRef) =
|
|
||||||
doAssert not tx.isNil
|
|
||||||
doAssert not tx.parent.isNil
|
|
||||||
doAssert not tx.methods.levelFn.isNil
|
|
||||||
doAssert not tx.methods.commitFn.isNil
|
|
||||||
doAssert not tx.methods.rollbackFn.isNil
|
|
||||||
doAssert not tx.methods.disposeFn.isNil
|
|
||||||
|
|
||||||
proc validateMethodsDesc(db: CoreDbRef) =
|
|
||||||
doAssert not db.isNil
|
|
||||||
doAssert db.dbType != CoreDbType(0)
|
|
||||||
db.methods.validateMethodsDesc
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public debugging helpers
|
# Public debugging helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc validate*(dsc: ValidateDesc) =
|
proc validate*(dsc: ValidateSubDesc) =
|
||||||
dsc.validateMethodsDesc
|
dsc.validateSubDescRef
|
||||||
|
|
||||||
proc validate*(db: CoreDbRef) =
|
proc validate*(db: CoreDbRef) =
|
||||||
db.validateMethodsDesc
|
doAssert not db.isNil
|
||||||
|
doAssert db.dbType != CoreDbType(0)
|
||||||
|
db.defCtx.validate
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
|
|
@ -13,10 +13,23 @@
|
||||||
import
|
import
|
||||||
std/typetraits,
|
std/typetraits,
|
||||||
eth/common,
|
eth/common,
|
||||||
./backend/aristo_db,
|
../aristo as use_ari,
|
||||||
|
../aristo/[aristo_walk, aristo_serialise],
|
||||||
|
../kvt as use_kvt,
|
||||||
|
../kvt/[kvt_init/memory_only, kvt_walk],
|
||||||
./base/[api_tracking, base_desc],
|
./base/[api_tracking, base_desc],
|
||||||
./base
|
./base
|
||||||
|
|
||||||
|
when CoreDbEnableApiJumpTable:
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
import
|
||||||
|
../aristo/[aristo_desc, aristo_path, aristo_tx],
|
||||||
|
../kvt/[kvt_desc, kvt_tx]
|
||||||
|
|
||||||
|
include
|
||||||
|
./backend/aristo_replicate
|
||||||
|
|
||||||
when CoreDbEnableApiTracking:
|
when CoreDbEnableApiTracking:
|
||||||
import chronicles
|
import chronicles
|
||||||
|
|
||||||
|
@ -35,39 +48,43 @@ iterator pairs*(kvt: CoreDbKvtRef): (Blob, Blob) {.apiRaise.} =
|
||||||
## Iterator supported on memory DB (otherwise implementation dependent)
|
## Iterator supported on memory DB (otherwise implementation dependent)
|
||||||
##
|
##
|
||||||
kvt.setTrackNewApi KvtPairsIt
|
kvt.setTrackNewApi KvtPairsIt
|
||||||
case kvt.parent.dbType:
|
case kvt.dbType:
|
||||||
of AristoDbMemory:
|
of AristoDbMemory:
|
||||||
for k,v in kvt.aristoKvtPairsMem():
|
let p = kvt.call(forkTx, kvt.kvt, 0).valueOrApiError "kvt/pairs()"
|
||||||
|
defer: discard kvt.call(forget, p)
|
||||||
|
for (k,v) in use_kvt.MemBackendRef.walkPairs p:
|
||||||
yield (k,v)
|
yield (k,v)
|
||||||
of AristoDbVoid:
|
of AristoDbVoid:
|
||||||
for k,v in kvt.aristoKvtPairsVoid():
|
let p = kvt.call(forkTx, kvt.kvt, 0).valueOrApiError "kvt/pairs()"
|
||||||
|
defer: discard kvt.call(forget, p)
|
||||||
|
for (k,v) in use_kvt.VoidBackendRef.walkPairs p:
|
||||||
yield (k,v)
|
yield (k,v)
|
||||||
of Ooops, AristoDbRocks:
|
of Ooops, AristoDbRocks:
|
||||||
raiseAssert: "Unsupported database type: " & $kvt.parent.dbType
|
raiseAssert: "Unsupported database type: " & $kvt.dbType
|
||||||
kvt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
kvt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
||||||
|
|
||||||
iterator pairs*(mpt: CoreDbMptRef): (Blob, Blob) =
|
iterator pairs*(mpt: CoreDbMptRef): (Blob, Blob) =
|
||||||
## Trie traversal, only supported for `CoreDbMptRef`
|
## Trie traversal, only supported for `CoreDbMptRef`
|
||||||
##
|
##
|
||||||
mpt.setTrackNewApi MptPairsIt
|
mpt.setTrackNewApi MptPairsIt
|
||||||
case mpt.parent.dbType:
|
case mpt.dbType:
|
||||||
of AristoDbMemory, AristoDbRocks, AristoDbVoid:
|
of AristoDbMemory, AristoDbRocks, AristoDbVoid:
|
||||||
for k,v in mpt.aristoMptPairs():
|
for (path,data) in mpt.mpt.rightPairsGeneric mpt.rootID:
|
||||||
yield (k,v)
|
yield (mpt.call(pathAsBlob, path), data)
|
||||||
of Ooops:
|
of Ooops:
|
||||||
raiseAssert: "Unsupported database type: " & $mpt.parent.dbType
|
raiseAssert: "Unsupported database type: " & $mpt.dbType
|
||||||
mpt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
mpt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
||||||
|
|
||||||
iterator slotPairs*(acc: CoreDbAccRef; accPath: Hash256): (Blob, Blob) =
|
iterator slotPairs*(acc: CoreDbAccRef; accPath: Hash256): (Blob, Blob) =
|
||||||
## Trie traversal, only supported for `CoreDbMptRef`
|
## Trie traversal, only supported for `CoreDbMptRef`
|
||||||
##
|
##
|
||||||
acc.setTrackNewApi AccSlotPairsIt
|
acc.setTrackNewApi AccSlotPairsIt
|
||||||
case acc.parent.dbType:
|
case acc.dbType:
|
||||||
of AristoDbMemory, AristoDbRocks, AristoDbVoid:
|
of AristoDbMemory, AristoDbRocks, AristoDbVoid:
|
||||||
for k,v in acc.aristoSlotPairs accPath:
|
for (path,data) in acc.mpt.rightPairsStorage accPath:
|
||||||
yield (k,v)
|
yield (acc.call(pathAsBlob, path), data)
|
||||||
of Ooops:
|
of Ooops:
|
||||||
raiseAssert: "Unsupported database type: " & $acc.parent.dbType
|
raiseAssert: "Unsupported database type: " & $acc.dbType
|
||||||
acc.ifTrackNewApi:
|
acc.ifTrackNewApi:
|
||||||
doAssert accPath.len == 32
|
doAssert accPath.len == 32
|
||||||
debug newApiTxt, api, elapsed
|
debug newApiTxt, api, elapsed
|
||||||
|
@ -76,15 +93,15 @@ iterator replicate*(mpt: CoreDbMptRef): (Blob, Blob) {.apiRaise.} =
|
||||||
## Low level trie dump, only supported for non persistent `CoreDbMptRef`
|
## Low level trie dump, only supported for non persistent `CoreDbMptRef`
|
||||||
##
|
##
|
||||||
mpt.setTrackNewApi MptReplicateIt
|
mpt.setTrackNewApi MptReplicateIt
|
||||||
case mpt.parent.dbType:
|
case mpt.dbType:
|
||||||
of AristoDbMemory:
|
of AristoDbMemory:
|
||||||
for k,v in aristoReplicateMem(mpt):
|
for k,v in aristoReplicate[use_ari.MemBackendRef](mpt):
|
||||||
yield (k,v)
|
yield (k,v)
|
||||||
of AristoDbVoid:
|
of AristoDbVoid:
|
||||||
for k,v in aristoReplicateVoid(mpt):
|
for k,v in aristoReplicate[use_ari.VoidBackendRef](mpt):
|
||||||
yield (k,v)
|
yield (k,v)
|
||||||
of Ooops, AristoDbRocks:
|
of Ooops, AristoDbRocks:
|
||||||
raiseAssert: "Unsupported database type: " & $mpt.parent.dbType
|
raiseAssert: "Unsupported database type: " & $mpt.dbType
|
||||||
mpt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
mpt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -13,10 +13,16 @@
|
||||||
import
|
import
|
||||||
std/typetraits,
|
std/typetraits,
|
||||||
eth/common,
|
eth/common,
|
||||||
./backend/[aristo_db, aristo_rocksdb],
|
../aristo as use_ari,
|
||||||
|
../aristo/aristo_init/rocks_db,
|
||||||
|
../aristo/[aristo_desc, aristo_walk/persistent, aristo_tx],
|
||||||
|
../kvt, # needed for `aristo_replicate`
|
||||||
./base/[api_tracking, base_desc],
|
./base/[api_tracking, base_desc],
|
||||||
./base
|
./base
|
||||||
|
|
||||||
|
include
|
||||||
|
./backend/aristo_replicate
|
||||||
|
|
||||||
when CoreDbEnableApiTracking:
|
when CoreDbEnableApiTracking:
|
||||||
import chronicles
|
import chronicles
|
||||||
|
|
||||||
|
@ -25,7 +31,7 @@ when CoreDbEnableApiTracking:
|
||||||
newApiTxt = logTxt & "API"
|
newApiTxt = logTxt & "API"
|
||||||
|
|
||||||
# Annotation helper(s)
|
# Annotation helper(s)
|
||||||
{.pragma: rlpRaise, gcsafe, raises: [AristoApiRlpError].}
|
{.pragma: rlpRaise, gcsafe, raises: [CoreDbApiError].}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public iterators
|
# Public iterators
|
||||||
|
@ -35,18 +41,18 @@ iterator replicatePersistent*(mpt: CoreDbMptRef): (Blob, Blob) {.rlpRaise.} =
|
||||||
## Extended version of `replicate()` for `Aristo` persistent backend.
|
## Extended version of `replicate()` for `Aristo` persistent backend.
|
||||||
##
|
##
|
||||||
mpt.setTrackNewApi MptReplicateIt
|
mpt.setTrackNewApi MptReplicateIt
|
||||||
case mpt.parent.dbType:
|
case mpt.dbType:
|
||||||
of AristoDbMemory:
|
of AristoDbMemory:
|
||||||
for k,v in aristoReplicateMem(mpt):
|
for k,v in aristoReplicate[use_ari.MemBackendRef](mpt):
|
||||||
yield (k,v)
|
yield (k,v)
|
||||||
of AristoDbVoid:
|
of AristoDbVoid:
|
||||||
for k,v in aristoReplicateVoid(mpt):
|
for k,v in aristoReplicate[use_ari.VoidBackendRef](mpt):
|
||||||
yield (k,v)
|
yield (k,v)
|
||||||
of AristoDbRocks:
|
of AristoDbRocks:
|
||||||
for k,v in aristoReplicateRdb(mpt):
|
for k, v in aristoReplicate[rocks_db.RdbBackendRef](mpt):
|
||||||
yield (k,v)
|
yield (k, v)
|
||||||
else:
|
else:
|
||||||
raiseAssert: "Unsupported database type: " & $mpt.parent.dbType
|
raiseAssert: "Unsupported database type: " & $mpt.dbType
|
||||||
mpt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
mpt.ifTrackNewApi: debug newApiTxt, api, elapsed
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -310,15 +310,7 @@ proc getSavedStateBlockNumber*(
|
||||||
## Returns the block number registered when the database was last time
|
## Returns the block number registered when the database was last time
|
||||||
## updated, or `BlockNumber(0)` if there was no updata found.
|
## updated, or `BlockNumber(0)` if there was no updata found.
|
||||||
##
|
##
|
||||||
## This function verifies the state consistency of the database and throws
|
db.stateBlockNumber()
|
||||||
## an assert exception if that fails. So the function will only apply to a
|
|
||||||
## saved database state. For an an opportunistic use, the `relax` argument
|
|
||||||
## can be set `true` so this function also returns the block number if the
|
|
||||||
## state consistency check fails.
|
|
||||||
##
|
|
||||||
# FIXME: This construct following will be replaced by a proper
|
|
||||||
# `CoreDb` method.
|
|
||||||
db.ctx.getColumn(CtGeneric).backend.toAristoSavedStateBlockNumber()
|
|
||||||
|
|
||||||
proc getBlockHeader*(
|
proc getBlockHeader*(
|
||||||
db: CoreDbRef;
|
db: CoreDbRef;
|
||||||
|
|
|
@ -24,20 +24,7 @@ export
|
||||||
base,
|
base,
|
||||||
base_iterators,
|
base_iterators,
|
||||||
common,
|
common,
|
||||||
core_apps,
|
core_apps
|
||||||
|
|
||||||
# see `aristo_db`
|
|
||||||
isAristo,
|
|
||||||
toAristo,
|
|
||||||
toAristoProfData,
|
|
||||||
toAristoSavedStateBlockNumber,
|
|
||||||
|
|
||||||
# Standard interface for calculating merkle hash signatures (see `aristo`)
|
|
||||||
MerkleSignRef,
|
|
||||||
merkleSignBegin,
|
|
||||||
merkleSignAdd,
|
|
||||||
merkleSignCommit,
|
|
||||||
to
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public constructors
|
# Public constructors
|
||||||
|
|
|
@ -23,6 +23,7 @@ import
|
||||||
export
|
export
|
||||||
MemBackendRef,
|
MemBackendRef,
|
||||||
VoidBackendRef,
|
VoidBackendRef,
|
||||||
|
finish,
|
||||||
init
|
init
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
|
@ -32,7 +32,7 @@ func isTop*(tx: KvtTxRef): bool =
|
||||||
## level transaction.
|
## level transaction.
|
||||||
tx.txFrameIsTop()
|
tx.txFrameIsTop()
|
||||||
|
|
||||||
func level*(tx: KvtTxRef): int =
|
func txLevel*(tx: KvtTxRef): int =
|
||||||
## Getter, positive nesting level of transaction argument `tx`
|
## Getter, positive nesting level of transaction argument `tx`
|
||||||
tx.txFrameLevel()
|
tx.txFrameLevel()
|
||||||
|
|
||||||
|
|
|
@ -97,9 +97,6 @@ func toStr*(w: EthAddress): string =
|
||||||
func toStr*(w: Hash256): string =
|
func toStr*(w: Hash256): string =
|
||||||
w.data.oaToStr
|
w.data.oaToStr
|
||||||
|
|
||||||
func toStr*(w: CoreDbMptRef): string =
|
|
||||||
if w.CoreDbMptRef.isNil: "nil" else: "MptRef"
|
|
||||||
|
|
||||||
func toStr*(w: CodeBytesRef): string =
|
func toStr*(w: CodeBytesRef): string =
|
||||||
if w.CodeBytesRef.isNil: "nil"
|
if w.CodeBytesRef.isNil: "nil"
|
||||||
else: "[" & $w.bytes.len & "]"
|
else: "[" & $w.bytes.len & "]"
|
||||||
|
|
|
@ -357,7 +357,7 @@ when isMainModule:
|
||||||
#dbType = CdbAristoDualRocks,
|
#dbType = CdbAristoDualRocks,
|
||||||
capture = capture,
|
capture = capture,
|
||||||
pruneHistory = true,
|
pruneHistory = true,
|
||||||
#profilingOk = true,
|
profilingOk = true,
|
||||||
#finalDiskCleanUpOk = false,
|
#finalDiskCleanUpOk = false,
|
||||||
oldLogAlign = true
|
oldLogAlign = true
|
||||||
)
|
)
|
||||||
|
|
|
@ -184,9 +184,9 @@ proc test_chainSync*(
|
||||||
# API data need to be captured so it will be available after the services
|
# API data need to be captured so it will be available after the services
|
||||||
# have terminated.
|
# have terminated.
|
||||||
when CoreDbEnableApiProfiling:
|
when CoreDbEnableApiProfiling:
|
||||||
# terminated.
|
aristoProfData = com.db.ariApi.AristoApiProfRef.data
|
||||||
(aristoProfData, kvtProfData) = com.db.toAristoProfData()
|
kvtProfData = com.db.kvtApi.KvtApiProfRef.data
|
||||||
cdbProfData = com.db.dbProfData()
|
cdbProfData = com.db.profTab
|
||||||
when LedgerEnableApiProfiling:
|
when LedgerEnableApiProfiling:
|
||||||
ldgProfData = com.db.ldgProfData()
|
ldgProfData = com.db.ldgProfData()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue