nimbus-eth1/execution_chain/db/aristo/aristo_tx_frame.nim
Jacek Sieka 3732b3f95e
fix level reporting (#3085)
Oops, level 0 was always used which needlessly increases mem usage -
comes with an assortment of simplifications
2025-02-18 08:01:44 +07:00

114 lines
3.3 KiB
Nim

# nimbus-eth1
# Copyright (c) 2023-2025 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.
## Aristo DB -- Transaction frames helper
## ======================================
##
{.push raises: [].}
import
results,
./[aristo_desc, aristo_layers]
# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
proc txFrameBegin*(db: AristoDbRef, parent: AristoTxRef): AristoTxRef =
let parent = if parent == nil:
db.txRef
else:
parent
AristoTxRef(
db: db,
parent: parent,
vTop: parent.vTop)
proc baseTxFrame*(db: AristoDbRef): AristoTxRef=
db.txRef
proc dispose*(
tx: AristoTxRef;
) =
tx[].reset()
proc checkpoint*(
tx: AristoTxRef;
blockNumber: uint64;
) =
tx.blockNumber = Opt.some(blockNumber)
proc txFramePersist*(
db: AristoDbRef; # Database
batch: PutHdlRef;
txFrame: AristoTxRef;
) =
if txFrame == db.txRef and txFrame.sTab.len == 0:
# No changes in frame - no `checkpoint` requirement - nothing to do here
return
let be = db.backend
doAssert not be.isNil, "Persisting to backend requires ... a backend!"
let lSst = SavedState(
key: emptyRoot, # placeholder for more
serial: txFrame.blockNumber.expect("`checkpoint` before persisting frame"))
# Squash all changes up to the base
if txFrame != db.txRef:
# Consolidate the changes from the old to the new base going from the
# bottom of the stack to avoid having to cascade each change through
# the full stack
assert txFrame.parent != nil
for frame in txFrame.stack():
if frame == db.txRef:
continue
mergeAndReset(db.txRef, frame)
frame.dispose() # This will also dispose `txFrame` itself!
# Put the now-merged contents in txFrame and make it the new base
swap(db.txRef[], txFrame[])
db.txRef = txFrame
# Store structural single trie entries
for rvid, vtx in txFrame.sTab:
txFrame.kMap.withValue(rvid, key) do:
be.putVtxFn(batch, rvid, vtx, key[])
do:
be.putVtxFn(batch, rvid, vtx, default(HashKey))
be.putTuvFn(batch, txFrame.vTop)
be.putLstFn(batch, lSst)
# TODO above, we only prepare the changes to the database but don't actually
# write them to disk - the code below that updates the frame should
# really run after things have been written (to maintain sync betweeen
# in-memory and on-disk state)
# Copy back updated payloads
for accPath, vtx in txFrame.accLeaves:
db.accLeaves.put(accPath, vtx)
for mixPath, vtx in txFrame.stoLeaves:
db.stoLeaves.put(mixPath, vtx)
txFrame.sTab.clear()
txFrame.kMap.clear()
txFrame.accLeaves.clear()
txFrame.stoLeaves.clear()
txFrame.blockNumber.reset()
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------