2023-05-30 11:47:47 +00:00
|
|
|
# nimbus-eth1
|
Core db update storage root management for sub tries (#1964)
* Aristo: Re-phrase `LayerDelta` and `LayerFinal` as object references
why:
Avoids copying in some cases
* Fix copyright header
* Aristo: Verify `leafTie.root` function argument for `merge()` proc
why:
Zero root will lead to inconsistent DB entry
* Aristo: Update failure condition for hash labels compiler `hashify()`
why:
Node need not be rejected as long as links are on the schedule. In
that case, `redo[]` is to become `wff.base[]` at a later stage.
This amends an earlier fix, part of #1952 by also testing against
the target nodes of the `wff.base[]` sets.
* Aristo: Add storage root glue record to `hashify()` schedule
why:
An account leaf node might refer to a non-resolvable storage root ID.
Storage root node chains will end up at the storage root. So the link
`storage-root->account-leaf` needs an extra item in the schedule.
* Aristo: fix error code returned by `fetchPayload()`
details:
Final error code is implied by the error code form the `hikeUp()`
function.
* CoreDb: Discard `createOk` argument in API `getRoot()` function
why:
Not needed for the legacy DB. For the `Arsto` DB, a lazy approach is
implemented where a stprage root node is created on-the-fly.
* CoreDb: Prevent `$$` logging in some cases
why:
Logging the function `$$` is not useful when it is used for internal
use, i.e. retrieving an an error text for logging.
* CoreDb: Add `tryHashFn()` to API for pretty printing
why:
Pretty printing must not change the hashification status for the
`Aristo` DB. So there is an independent API wrapper for getting the
node hash which never updated the hashes.
* CoreDb: Discard `update` argument in API `hash()` function
why:
When calling the API function `hash()`, the latest state is always
wanted. For a version that uses the current state as-is without checking,
the function `tryHash()` was added to the backend.
* CoreDb: Update opaque vertex ID objects for the `Aristo` backend
why:
For `Aristo`, vID objects encapsulate a numeric `VertexID`
referencing a vertex (rather than a node hash as used on the
legacy backend.) For storage sub-tries, there might be no initial
vertex known when the descriptor is created. So opaque vertex ID
objects are supported without a valid `VertexID` which will be
initalised on-the-fly when the first item is merged.
* CoreDb: Add pretty printer for opaque vertex ID objects
* Cosmetics, printing profiling data
* CoreDb: Fix segfault in `Aristo` backend when creating MPT descriptor
why:
Missing initialisation error
* CoreDb: Allow MPT to inherit shared context on `Aristo` backend
why:
Creates descriptors with different storage roots for the same
shared `Aristo` DB descriptor.
* Cosmetics, update diagnostic message items for `Aristo` backend
* Fix Copyright year
2024-01-11 19:11:38 +00:00
|
|
|
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
2023-05-30 11:47:47 +00:00
|
|
|
# Licensed under either of
|
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
|
|
# http://opensource.org/licenses/MIT)
|
|
|
|
# at your option. This file may not be copied, modified, or distributed
|
|
|
|
# except according to those terms.
|
|
|
|
|
2023-05-30 21:21:15 +00:00
|
|
|
## Aristo DB -- Patricia Trie builder, raw node insertion
|
|
|
|
## ======================================================
|
|
|
|
##
|
2023-10-27 21:36:51 +00:00
|
|
|
## This module merges `PathID` values as hexary lookup paths into the
|
2023-05-30 21:21:15 +00:00
|
|
|
## `Patricia Trie`. When changing vertices (aka nodes without Merkle hashes),
|
|
|
|
## associated (but separated) Merkle hashes will be deleted unless locked.
|
|
|
|
## Instead of deleting locked hashes error handling is applied.
|
|
|
|
##
|
|
|
|
## Also, nodes (vertices plus merkle hashes) can be added which is needed for
|
|
|
|
## boundary proofing after `snap/1` download. The vertices are split from the
|
|
|
|
## nodes and stored as-is on the table holding `Patricia Trie` entries. The
|
|
|
|
## hashes are stored iin a separate table and the vertices are labelled
|
|
|
|
## `locked`.
|
|
|
|
|
2023-05-30 11:47:47 +00:00
|
|
|
{.push raises: [].}
|
|
|
|
|
|
|
|
import
|
2024-06-07 10:56:31 +00:00
|
|
|
std/[strutils, sets, tables, typetraits],
|
2023-05-30 11:47:47 +00:00
|
|
|
eth/[common, trie/nibbles],
|
2023-09-12 18:45:12 +00:00
|
|
|
results,
|
2024-02-22 08:24:58 +00:00
|
|
|
"."/[aristo_desc, aristo_get, aristo_hike, aristo_layers,
|
2024-06-07 10:56:31 +00:00
|
|
|
aristo_path, aristo_utils],
|
|
|
|
./aristo_merge/[merge_payload_helper, merge_proof]
|
2023-05-30 11:47:47 +00:00
|
|
|
|
2024-06-07 10:56:31 +00:00
|
|
|
export
|
|
|
|
merge_proof
|
2023-05-30 11:47:47 +00:00
|
|
|
|
2023-06-02 19:21:46 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Private helpers
|
|
|
|
# ------------------------------------------------------------------------------
|
2023-05-30 21:21:15 +00:00
|
|
|
|
2023-09-15 15:23:53 +00:00
|
|
|
proc to(
|
|
|
|
rc: Result[Hike,AristoError];
|
|
|
|
T: type Result[bool,AristoError];
|
|
|
|
): T =
|
|
|
|
## Return code converter
|
|
|
|
if rc.isOk:
|
|
|
|
ok true
|
2023-12-04 20:39:26 +00:00
|
|
|
elif rc.error in {MergeLeafPathCachedAlready,
|
|
|
|
MergeLeafPathOnBackendAlready}:
|
2023-09-15 15:23:53 +00:00
|
|
|
ok false
|
|
|
|
else:
|
|
|
|
err(rc.error)
|
|
|
|
|
2023-05-30 11:47:47 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Public functions
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
2024-02-29 21:10:24 +00:00
|
|
|
proc mergePayload*(
|
2023-07-04 18:24:03 +00:00
|
|
|
db: AristoDbRef; # Database, top layer
|
2023-08-07 17:45:23 +00:00
|
|
|
leafTie: LeafTie; # Leaf item to add to the database
|
|
|
|
payload: PayloadRef; # Payload value
|
2024-02-01 21:27:48 +00:00
|
|
|
accPath: PathID; # Needed for accounts payload
|
2023-09-15 15:23:53 +00:00
|
|
|
): Result[Hike,AristoError] =
|
|
|
|
## Merge the argument `leafTie` key-value-pair into the top level vertex
|
|
|
|
## table of the database `db`. The field `path` of the `leafTie` argument is
|
2024-05-30 17:48:38 +00:00
|
|
|
## used to address the leaf vertex with the payload. It is stored or updated
|
|
|
|
## on the database accordingly.
|
|
|
|
##
|
|
|
|
## If the `leafTie` argument referes to aa account entrie (i.e. the
|
|
|
|
## `leafTie.root` equals `VertexID(1)`) and the leaf entry has already an
|
|
|
|
## `AccountData` payload, its `storageID` field must be the same as the one
|
|
|
|
## on the database. The `accPath` argument will be ignored.
|
|
|
|
##
|
|
|
|
## Otherwise, if the `root` argument belongs to a well known sub trie (i.e.
|
|
|
|
## it does not exceed `LEAST_FREE_VID`) the `accPath` argument is ignored
|
|
|
|
## and the entry will just be merged.
|
|
|
|
##
|
|
|
|
## Otherwise, a valid `accPath` (i.e. different from `VOID_PATH_ID`.) is
|
|
|
|
## required relating to an account leaf entry (starting at `VertexID(`)`).
|
|
|
|
## If the payload of that leaf entry is not of type `AccountData` it is
|
|
|
|
## ignored.
|
2023-05-30 21:21:15 +00:00
|
|
|
##
|
2024-05-30 17:48:38 +00:00
|
|
|
## Otherwise, if the sub-trie where the `leafTie` is to be merged into does
|
|
|
|
## not exist yes, the `storageID` field of the `accPath` leaf must have been
|
|
|
|
## reset to `storageID(0)` and will be updated accordingly on the database.
|
2024-02-01 21:27:48 +00:00
|
|
|
##
|
2024-05-30 17:48:38 +00:00
|
|
|
## Otherwise its `storageID` field must be equal to the `leafTie.root` vertex
|
|
|
|
## ID. So vertices can be marked for Merkle hash update.
|
|
|
|
##
|
|
|
|
let wp = block:
|
|
|
|
if leafTie.root.distinctBase < LEAST_FREE_VID:
|
|
|
|
if not leafTie.root.isValid:
|
|
|
|
return err(MergeRootMissing)
|
|
|
|
VidVtxPair()
|
|
|
|
else:
|
|
|
|
let rc = db.registerAccount(leafTie.root, accPath)
|
|
|
|
if rc.isErr:
|
|
|
|
return err(rc.error)
|
|
|
|
else:
|
|
|
|
rc.value
|
Core db update storage root management for sub tries (#1964)
* Aristo: Re-phrase `LayerDelta` and `LayerFinal` as object references
why:
Avoids copying in some cases
* Fix copyright header
* Aristo: Verify `leafTie.root` function argument for `merge()` proc
why:
Zero root will lead to inconsistent DB entry
* Aristo: Update failure condition for hash labels compiler `hashify()`
why:
Node need not be rejected as long as links are on the schedule. In
that case, `redo[]` is to become `wff.base[]` at a later stage.
This amends an earlier fix, part of #1952 by also testing against
the target nodes of the `wff.base[]` sets.
* Aristo: Add storage root glue record to `hashify()` schedule
why:
An account leaf node might refer to a non-resolvable storage root ID.
Storage root node chains will end up at the storage root. So the link
`storage-root->account-leaf` needs an extra item in the schedule.
* Aristo: fix error code returned by `fetchPayload()`
details:
Final error code is implied by the error code form the `hikeUp()`
function.
* CoreDb: Discard `createOk` argument in API `getRoot()` function
why:
Not needed for the legacy DB. For the `Arsto` DB, a lazy approach is
implemented where a stprage root node is created on-the-fly.
* CoreDb: Prevent `$$` logging in some cases
why:
Logging the function `$$` is not useful when it is used for internal
use, i.e. retrieving an an error text for logging.
* CoreDb: Add `tryHashFn()` to API for pretty printing
why:
Pretty printing must not change the hashification status for the
`Aristo` DB. So there is an independent API wrapper for getting the
node hash which never updated the hashes.
* CoreDb: Discard `update` argument in API `hash()` function
why:
When calling the API function `hash()`, the latest state is always
wanted. For a version that uses the current state as-is without checking,
the function `tryHash()` was added to the backend.
* CoreDb: Update opaque vertex ID objects for the `Aristo` backend
why:
For `Aristo`, vID objects encapsulate a numeric `VertexID`
referencing a vertex (rather than a node hash as used on the
legacy backend.) For storage sub-tries, there might be no initial
vertex known when the descriptor is created. So opaque vertex ID
objects are supported without a valid `VertexID` which will be
initalised on-the-fly when the first item is merged.
* CoreDb: Add pretty printer for opaque vertex ID objects
* Cosmetics, printing profiling data
* CoreDb: Fix segfault in `Aristo` backend when creating MPT descriptor
why:
Missing initialisation error
* CoreDb: Allow MPT to inherit shared context on `Aristo` backend
why:
Creates descriptors with different storage roots for the same
shared `Aristo` DB descriptor.
* Cosmetics, update diagnostic message items for `Aristo` backend
* Fix Copyright year
2024-01-11 19:11:38 +00:00
|
|
|
|
2023-09-15 15:23:53 +00:00
|
|
|
let hike = leafTie.hikeUp(db).to(Hike)
|
|
|
|
var okHike: Hike
|
|
|
|
if 0 < hike.legs.len:
|
|
|
|
case hike.legs[^1].wp.vtx.vType:
|
|
|
|
of Branch:
|
2024-06-07 10:56:31 +00:00
|
|
|
okHike = ? db.mergePayloadTopIsBranchAddLeaf(hike, payload)
|
2023-09-15 15:23:53 +00:00
|
|
|
of Leaf:
|
|
|
|
if 0 < hike.tail.len: # `Leaf` vertex problem?
|
|
|
|
return err(MergeLeafGarbledHike)
|
2024-06-07 10:56:31 +00:00
|
|
|
okHike = ? db.mergePayloadUpdate(hike, leafTie, payload)
|
2023-09-15 15:23:53 +00:00
|
|
|
of Extension:
|
2024-06-07 10:56:31 +00:00
|
|
|
okHike = ? db.mergePayloadTopIsExtAddLeaf(hike, payload)
|
2023-05-30 11:47:47 +00:00
|
|
|
|
|
|
|
else:
|
2023-09-15 15:23:53 +00:00
|
|
|
# Empty hike
|
|
|
|
let rootVtx = db.getVtx hike.root
|
|
|
|
if rootVtx.isValid:
|
2024-06-07 10:56:31 +00:00
|
|
|
okHike = ? db.mergePayloadTopIsEmptyAddLeaf(hike,rootVtx, payload)
|
2023-05-30 11:47:47 +00:00
|
|
|
|
|
|
|
else:
|
2023-09-15 15:23:53 +00:00
|
|
|
# Bootstrap for existing root ID
|
|
|
|
let wp = VidVtxPair(
|
|
|
|
vid: hike.root,
|
|
|
|
vtx: VertexRef(
|
|
|
|
vType: Leaf,
|
|
|
|
lPfx: leafTie.path.to(NibblesSeq),
|
|
|
|
lData: payload))
|
2024-02-22 08:24:58 +00:00
|
|
|
db.setVtxAndKey(hike.root, wp.vid, wp.vtx)
|
2023-09-15 15:23:53 +00:00
|
|
|
okHike = Hike(root: wp.vid, legs: @[Leg(wp: wp, nibble: -1)])
|
2023-06-20 13:26:25 +00:00
|
|
|
|
2023-09-15 15:23:53 +00:00
|
|
|
# Double check the result until the code is more reliable
|
|
|
|
block:
|
2023-10-27 21:36:51 +00:00
|
|
|
let rc = okHike.to(NibblesSeq).pathToTag
|
|
|
|
if rc.isErr or rc.value != leafTie.path:
|
2023-09-15 15:23:53 +00:00
|
|
|
return err(MergeAssemblyFailed) # Ooops
|
|
|
|
|
2024-05-30 17:48:38 +00:00
|
|
|
# Make sure that there is an accounts that refers to that storage trie
|
|
|
|
if wp.vid.isValid and not wp.vtx.lData.account.storageID.isValid:
|
|
|
|
let leaf = wp.vtx.dup # Dup on modify
|
|
|
|
leaf.lData.account.storageID = leafTie.root
|
|
|
|
db.layersPutVtx(VertexID(1), wp.vid, leaf)
|
|
|
|
db.layersResKey(VertexID(1), wp.vid)
|
|
|
|
|
2023-09-15 15:23:53 +00:00
|
|
|
ok okHike
|
|
|
|
|
|
|
|
|
2024-02-29 21:10:24 +00:00
|
|
|
proc mergePayload*(
|
2023-09-15 15:23:53 +00:00
|
|
|
db: AristoDbRef; # Database, top layer
|
|
|
|
root: VertexID; # MPT state root
|
2023-10-27 21:36:51 +00:00
|
|
|
path: openArray[byte]; # Even nibbled byte path
|
2023-09-15 15:23:53 +00:00
|
|
|
payload: PayloadRef; # Payload value
|
2024-02-29 21:10:24 +00:00
|
|
|
accPath = VOID_PATH_ID; # Needed for accounts payload
|
2023-09-15 15:23:53 +00:00
|
|
|
): Result[bool,AristoError] =
|
|
|
|
## Variant of `merge()` for `(root,path)` arguments instead of a `LeafTie`
|
|
|
|
## object.
|
2023-11-08 12:18:32 +00:00
|
|
|
let lty = LeafTie(root: root, path: ? path.pathToTag)
|
2024-02-29 21:10:24 +00:00
|
|
|
db.mergePayload(lty, payload, accPath).to(typeof result)
|
2024-02-01 21:27:48 +00:00
|
|
|
|
2023-09-15 15:23:53 +00:00
|
|
|
|
|
|
|
proc merge*(
|
|
|
|
db: AristoDbRef; # Database, top layer
|
|
|
|
root: VertexID; # MPT state root
|
|
|
|
path: openArray[byte]; # Leaf item to add to the database
|
2023-11-08 12:18:32 +00:00
|
|
|
data: openArray[byte]; # Raw data payload value
|
2024-02-01 21:27:48 +00:00
|
|
|
accPath: PathID; # Needed for accounts payload
|
2023-09-15 15:23:53 +00:00
|
|
|
): Result[bool,AristoError] =
|
2023-11-08 12:18:32 +00:00
|
|
|
## Variant of `merge()` for `(root,path)` arguments instead of a `LeafTie`.
|
2024-02-01 21:27:48 +00:00
|
|
|
## The argument `data` is stored as-is as a `RawData` payload value.
|
|
|
|
let pyl = PayloadRef(pType: RawData, rawBlob: @data)
|
2024-02-29 21:10:24 +00:00
|
|
|
db.mergePayload(root, path, pyl, accPath)
|
2024-02-01 21:27:48 +00:00
|
|
|
|
2024-02-29 21:10:24 +00:00
|
|
|
proc mergeAccount*(
|
2024-02-01 21:27:48 +00:00
|
|
|
db: AristoDbRef; # Database, top layer
|
|
|
|
path: openArray[byte]; # Leaf item to add to the database
|
|
|
|
data: openArray[byte]; # Raw data payload value
|
|
|
|
): Result[bool,AristoError] =
|
|
|
|
## Variant of `merge()` for `(VertexID(1),path)` arguments instead of a
|
|
|
|
## `LeafTie`. The argument `data` is stored as-is as a `RawData` payload
|
|
|
|
## value.
|
|
|
|
let pyl = PayloadRef(pType: RawData, rawBlob: @data)
|
2024-02-29 21:10:24 +00:00
|
|
|
db.mergePayload(VertexID(1), path, pyl, VOID_PATH_ID)
|
2024-02-01 21:27:48 +00:00
|
|
|
|
2023-08-11 17:23:57 +00:00
|
|
|
|
2024-02-29 21:10:24 +00:00
|
|
|
proc mergeLeaf*(
|
2023-08-07 17:45:23 +00:00
|
|
|
db: AristoDbRef; # Database, top layer
|
2023-11-08 12:18:32 +00:00
|
|
|
leaf: LeafTiePayload; # Leaf item to add to the database
|
2024-02-29 21:10:24 +00:00
|
|
|
accPath = VOID_PATH_ID; # Needed for accounts payload
|
2023-08-07 17:45:23 +00:00
|
|
|
): Result[bool,AristoError] =
|
|
|
|
## Variant of `merge()`. This function will not indicate if the leaf
|
|
|
|
## was cached, already.
|
2024-06-07 10:56:31 +00:00
|
|
|
db.mergePayload(leaf.leafTie,leaf.payload, accPath).to(typeof result)
|
2023-06-09 11:17:37 +00:00
|
|
|
|
2023-05-30 11:47:47 +00:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# End
|
|
|
|
# ------------------------------------------------------------------------------
|