166 lines
4.8 KiB
Nim
166 lines
4.8 KiB
Nim
# nimbus-eth1
|
|
# 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.
|
|
|
|
## Aristo DB -- Obects Retrival Via Traversal Path
|
|
## ===============================================
|
|
##
|
|
{.push raises: [].}
|
|
|
|
import
|
|
std/typetraits,
|
|
eth/[common, trie/nibbles],
|
|
results,
|
|
"."/[aristo_desc, aristo_get, aristo_hike, aristo_utils]
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Private functions
|
|
# ------------------------------------------------------------------------------
|
|
|
|
func mustBeGeneric(
|
|
root: VertexID;
|
|
): Result[void,AristoError] =
|
|
## Verify that `root` is neither from an accounts tree nor a strorage tree.
|
|
if not root.isValid:
|
|
return err(FetchRootVidMissing)
|
|
elif root == VertexID(1):
|
|
return err(FetchAccRootNotAccepted)
|
|
elif LEAST_FREE_VID <= root.distinctBase:
|
|
return err(FetchStoRootNotAccepted)
|
|
ok()
|
|
|
|
|
|
proc retrievePayload(
|
|
db: AristoDbRef;
|
|
root: VertexID;
|
|
path: openArray[byte];
|
|
): Result[PayloadRef,AristoError] =
|
|
if path.len == 0:
|
|
return err(FetchPathInvalid)
|
|
|
|
let hike = path.initNibbleRange.hikeUp(root, db).valueOr:
|
|
if error[1] in HikeAcceptableStopsNotFound:
|
|
return err(FetchPathNotFound)
|
|
return err(error[1])
|
|
|
|
ok hike.legs[^1].wp.vtx.lData
|
|
|
|
|
|
proc retrieveStoID(
|
|
db: AristoDbRef;
|
|
accPath: PathID;
|
|
): Result[VertexID,AristoError] =
|
|
let
|
|
accHike = ? db.retrieveStoAccHike accPath # checks for `AccountData`
|
|
stoID = accHike.legs[^1].wp.vtx.lData.account.storageID
|
|
|
|
if not stoID.isValid:
|
|
return err(FetchPathNotFound)
|
|
|
|
ok stoID
|
|
|
|
|
|
proc hasPayload(
|
|
db: AristoDbRef;
|
|
root: VertexID;
|
|
path: openArray[byte];
|
|
): Result[bool,AristoError] =
|
|
if path.len == 0:
|
|
return err(FetchPathInvalid)
|
|
|
|
let hike = path.initNibbleRange.hikeUp(VertexID(1), db).valueOr:
|
|
if error[1] in HikeAcceptableStopsNotFound:
|
|
return ok(false)
|
|
return err(error[1])
|
|
ok(true)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc fetchLastSavedState*(
|
|
db: AristoDbRef;
|
|
): Result[SavedState,AristoError] =
|
|
## Wrapper around `getLstUbe()`. The function returns the state of the last
|
|
## saved state. This is a Merkle hash tag for vertex with ID 1 and a bespoke
|
|
## `uint64` identifier (may be interpreted as block number.)
|
|
db.getLstUbe()
|
|
|
|
|
|
proc fetchAccountPayload*(
|
|
db: AristoDbRef;
|
|
path: openArray[byte];
|
|
): Result[AristoAccount,AristoError] =
|
|
## Fetch an account record from the database indexed by `path`.
|
|
##
|
|
let pyl = ? db.retrievePayload(VertexID(1), path)
|
|
assert pyl.pType == AccountData # debugging only
|
|
ok pyl.account
|
|
|
|
proc hasPathAccount*(
|
|
db: AristoDbRef;
|
|
path: openArray[byte];
|
|
): Result[bool,AristoError] =
|
|
## For an account record indexed by `path` query whether this record exists
|
|
## on the database.
|
|
##
|
|
db.hasPayload(VertexID(1), path)
|
|
|
|
|
|
proc fetchGenericData*(
|
|
db: AristoDbRef;
|
|
root: VertexID;
|
|
path: openArray[byte];
|
|
): Result[Blob,AristoError] =
|
|
## For a generic sub-tree starting at `root`, fetch the data record
|
|
## indexed by `path`.
|
|
##
|
|
? root.mustBeGeneric()
|
|
let pyl = ? db.retrievePayload(root, path)
|
|
assert pyl.pType == RawData # debugging only
|
|
ok pyl.rawBlob
|
|
|
|
proc hasPathGeneric*(
|
|
db: AristoDbRef;
|
|
root: VertexID;
|
|
path: openArray[byte];
|
|
): Result[bool,AristoError] =
|
|
## For a generic sub-tree starting at `root` and indexed by `path`, query
|
|
## whether this record exists on the database.
|
|
##
|
|
? root.mustBeGeneric()
|
|
db.hasPayload(root, path)
|
|
|
|
|
|
proc fetchStorageData*(
|
|
db: AristoDbRef;
|
|
path: openArray[byte];
|
|
accPath: PathID;
|
|
): Result[Blob,AristoError] =
|
|
## For a storage tree related to account `accPath`, fetch the data record
|
|
## from the database indexed by `path`.
|
|
##
|
|
let pyl = ? db.retrievePayload(? db.retrieveStoID accPath, path)
|
|
assert pyl.pType == RawData # debugging only
|
|
ok pyl.rawBlob
|
|
|
|
proc hasPathStorage*(
|
|
db: AristoDbRef;
|
|
path: openArray[byte];
|
|
accPath: PathID;
|
|
): Result[bool,AristoError] =
|
|
## For a storage tree related to account `accPath`, query whether the data
|
|
## record indexed by `path` exists on the database.
|
|
##
|
|
db.hasPayload(? db.retrieveStoID accPath, path)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# End
|
|
# ------------------------------------------------------------------------------
|