Aristo uses pre classified tree types cont2 (#2397)

* Provide dedicated functions for fetching accounts and storage trees

why:
  Different prototypes for each class `account`, `generic` and
  `storage`.

* Remove `fetchPayload()` and other cruft from API, `aristo_fetch`, etc.

* Fix typos, debugging left overs, comments
This commit is contained in:
Jordan Hrycaj 2024-06-19 12:40:00 +00:00 committed by GitHub
parent 035ef696a6
commit e7be0d185c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 408 additions and 257 deletions

View File

@ -108,15 +108,30 @@ type
## Merkle hash tag for vertex with ID 1 and a bespoke `uint64` identifier ## Merkle hash tag for vertex with ID 1 and a bespoke `uint64` identifier
## (may be interpreted as block number.) ## (may be interpreted as block number.)
AristoApiFetchPayloadFn* = AristoApiFetchAccountPayloadFn* =
proc(db: AristoDbRef;
path: openArray[byte];
): Result[AristoAccount,AristoError]
{.noRaise.}
## Fetch an account record from the database indexed by `path`.
AristoApiFetchGenericDataFn* =
proc(db: AristoDbRef; proc(db: AristoDbRef;
root: VertexID; root: VertexID;
path: openArray[byte]; path: openArray[byte];
): Result[PayloadRef,(VertexID,AristoError)] ): Result[Blob,AristoError]
{.noRaise.} {.noRaise.}
## Cascaded attempt to traverse the `Aristo Trie` and fetch the value ## For a generic sub-tree starting at `root`, fetch the data record
## of a leaf vertex. This function is complementary to some `mergeXXX()` ## indexed by `path`.
## function.
AristoApiFetchStorageDataFn* =
proc(db: AristoDbRef;
path: openArray[byte];
accPath: PathID;
): Result[Blob,AristoError]
{.noRaise.}
## For a storage tree related to account `accPath`, fetch the data
## record from the database indexed by `path`.
AristoApiFindTxFn* = AristoApiFindTxFn* =
proc(db: AristoDbRef; proc(db: AristoDbRef;
@ -205,15 +220,31 @@ type
## Add keys to the `Patricia Trie` so that it becomes a `Merkle ## Add keys to the `Patricia Trie` so that it becomes a `Merkle
## Patricia Tree`. ## Patricia Tree`.
AristoApiHasPathFn* = AristoApiHasPathAccountFn* =
proc(db: AristoDbRef;
path: openArray[byte];
): Result[bool,AristoError]
{.noRaise.}
## For an account record indexed by `path` query whether this record
## exists on the database.
AristoApiHasPathGenericFn* =
proc(db: AristoDbRef; proc(db: AristoDbRef;
root: VertexID; root: VertexID;
path: openArray[byte]; path: openArray[byte];
): Result[bool,(VertexID,AristoError)] ): Result[bool,AristoError]
{.noRaise.} {.noRaise.}
## Variant of `fetchPayload()` without returning data. It returns ## For a generic sub-tree starting at `root` and indexed by `path`,
## `true` iff the database `db` contains a leaf item with the argument ## mquery whether this record exists on the database.
## path.
AristoApiHasPathStorageFn* =
proc(db: AristoDbRef;
path: openArray[byte];
accPath: PathID;
): Result[bool,AristoError]
{.noRaise.}
## For a storage tree related to account `accPath`, query whether the
## data record indexed by `path` exists on the database.
AristoApiHikeUpFn* = AristoApiHikeUpFn* =
proc(path: NibblesSeq; proc(path: NibblesSeq;
@ -384,14 +415,18 @@ type
deleteStorageData*: AristoApiDeleteStorageDataFn deleteStorageData*: AristoApiDeleteStorageDataFn
deleteStorageTree*: AristoApiDeleteStorageTreeFn deleteStorageTree*: AristoApiDeleteStorageTreeFn
fetchLastSavedState*: AristoApiFetchLastSavedStateFn fetchLastSavedState*: AristoApiFetchLastSavedStateFn
fetchPayload*: AristoApiFetchPayloadFn fetchAccountPayload*: AristoApiFetchAccountPayloadFn
fetchGenericData*: AristoApiFetchGenericDataFn
fetchStorageData*: AristoApiFetchStorageDataFn
findTx*: AristoApiFindTxFn findTx*: AristoApiFindTxFn
finish*: AristoApiFinishFn finish*: AristoApiFinishFn
forget*: AristoApiForgetFn forget*: AristoApiForgetFn
forkTx*: AristoApiForkTxFn forkTx*: AristoApiForkTxFn
getKeyRc*: AristoApiGetKeyRcFn getKeyRc*: AristoApiGetKeyRcFn
hashify*: AristoApiHashifyFn hashify*: AristoApiHashifyFn
hasPath*: AristoApiHasPathFn hasPathAccount*: AristoApiHasPathAccountFn
hasPathGeneric*: AristoApiHasPathGenericFn
hasPathStorage*: AristoApiHasPathStorageFn
hikeUp*: AristoApiHikeUpFn hikeUp*: AristoApiHikeUpFn
isTop*: AristoApiIsTopFn isTop*: AristoApiIsTopFn
level*: AristoApiLevelFn level*: AristoApiLevelFn
@ -419,14 +454,18 @@ type
AristoApiProfDeleteStorageDataFn = "deleteStorageData" AristoApiProfDeleteStorageDataFn = "deleteStorageData"
AristoApiProfDeleteStorageTreeFn = "deleteStorageTree" AristoApiProfDeleteStorageTreeFn = "deleteStorageTree"
AristoApiProfFetchLastSavedStateFn = "fetchPayload" AristoApiProfFetchLastSavedStateFn = "fetchPayload"
AristoApiProfFetchPayloadFn = "fetchPayload" AristoApiProfFetchAccountPayloadFn = "fetchAccountPayload"
AristoApiProfFetchGenericDataFn = "fetchGenericData"
AristoApiProfFetchStorageDataFn = "fetchStorageData"
AristoApiProfFindTxFn = "findTx" AristoApiProfFindTxFn = "findTx"
AristoApiProfFinishFn = "finish" AristoApiProfFinishFn = "finish"
AristoApiProfForgetFn = "forget" AristoApiProfForgetFn = "forget"
AristoApiProfForkTxFn = "forkTx" AristoApiProfForkTxFn = "forkTx"
AristoApiProfGetKeyRcFn = "getKeyRc" AristoApiProfGetKeyRcFn = "getKeyRc"
AristoApiProfHashifyFn = "hashify" AristoApiProfHashifyFn = "hashify"
AristoApiProfHasPathFn = "hasPath" AristoApiProfHasPathAccountFn = "hasPathAccount"
AristoApiProfHasPathGenericFn = "hasPathGeneric"
AristoApiProfHasPathStorageFn = "hasPathStorage"
AristoApiProfHikeUpFn = "hikeUp" AristoApiProfHikeUpFn = "hikeUp"
AristoApiProfIsTopFn = "isTop" AristoApiProfIsTopFn = "isTop"
AristoApiProfLevelFn = "level" AristoApiProfLevelFn = "level"
@ -470,14 +509,18 @@ when AutoValidateApiHooks:
doAssert not api.deleteStorageData.isNil doAssert not api.deleteStorageData.isNil
doAssert not api.deleteStorageTree.isNil doAssert not api.deleteStorageTree.isNil
doAssert not api.fetchLastSavedState.isNil doAssert not api.fetchLastSavedState.isNil
doAssert not api.fetchPayload.isNil doAssert not api.fetchAccountPayload.isNil
doAssert not api.fetchGenericData.isNil
doAssert not api.fetchStorageData.isNil
doAssert not api.findTx.isNil doAssert not api.findTx.isNil
doAssert not api.finish.isNil doAssert not api.finish.isNil
doAssert not api.forget.isNil doAssert not api.forget.isNil
doAssert not api.forkTx.isNil doAssert not api.forkTx.isNil
doAssert not api.getKeyRc.isNil doAssert not api.getKeyRc.isNil
doAssert not api.hashify.isNil doAssert not api.hashify.isNil
doAssert not api.hasPath.isNil doAssert not api.hasPathAccount.isNil
doAssert not api.hasPathGeneric.isNil
doAssert not api.hasPathStorage.isNil
doAssert not api.hikeUp.isNil doAssert not api.hikeUp.isNil
doAssert not api.isTop.isNil doAssert not api.isTop.isNil
doAssert not api.level.isNil doAssert not api.level.isNil
@ -525,14 +568,18 @@ func init*(api: var AristoApiObj) =
api.deleteStorageData = deleteStorageData api.deleteStorageData = deleteStorageData
api.deleteStorageTree = deleteStorageTree api.deleteStorageTree = deleteStorageTree
api.fetchLastSavedState = fetchLastSavedState api.fetchLastSavedState = fetchLastSavedState
api.fetchPayload = fetchPayload api.fetchAccountPayload = fetchAccountPayload
api.fetchGenericData = fetchGenericData
api.fetchStorageData = fetchStorageData
api.findTx = findTx api.findTx = findTx
api.finish = finish api.finish = finish
api.forget = forget api.forget = forget
api.forkTx = forkTx api.forkTx = forkTx
api.getKeyRc = getKeyRc api.getKeyRc = getKeyRc
api.hashify = hashify api.hashify = hashify
api.hasPath = hasPath api.hasPathAccount = hasPathAccount
api.hasPathGeneric = hasPathGeneric
api.hasPathStorage = hasPathStorage
api.hikeUp = hikeUp api.hikeUp = hikeUp
api.isTop = isTop api.isTop = isTop
api.level = level api.level = level
@ -563,14 +610,18 @@ func dup*(api: AristoApiRef): AristoApiRef =
deleteStorageData: api.deleteStorageData, deleteStorageData: api.deleteStorageData,
deleteStorageTree: api.deleteStorageTree, deleteStorageTree: api.deleteStorageTree,
fetchLastSavedState: api.fetchLastSavedState, fetchLastSavedState: api.fetchLastSavedState,
fetchPayload: api.fetchPayload, fetchAccountPayload: api.fetchAccountPayload,
fetchGenericData: api.fetchGenericData,
fetchStorageData: api.fetchStorageData,
findTx: api.findTx, findTx: api.findTx,
finish: api.finish, finish: api.finish,
forget: api.forget, forget: api.forget,
forkTx: api.forkTx, forkTx: api.forkTx,
getKeyRc: api.getKeyRc, getKeyRc: api.getKeyRc,
hashify: api.hashify, hashify: api.hashify,
hasPath: api.hasPath, hasPathAccount: api.hasPathAccount,
hasPathGeneric: api.hasPathGeneric,
hasPathStorage: api.hasPathStorage,
hikeUp: api.hikeUp, hikeUp: api.hikeUp,
isTop: api.isTop, isTop: api.isTop,
level: api.level, level: api.level,
@ -650,10 +701,20 @@ func init*(
AristoApiProfFetchLastSavedStateFn.profileRunner: AristoApiProfFetchLastSavedStateFn.profileRunner:
result = api.fetchLastSavedState(a) result = api.fetchLastSavedState(a)
profApi.fetchPayload = profApi.fetchAccountPayload =
proc(a: AristoDbRef; b: openArray[byte]): auto =
AristoApiProfFetchAccountPayloadFn.profileRunner:
result = api.fetchAccountPayload(a, b)
profApi.fetchGenericData =
proc(a: AristoDbRef; b: VertexID; c: openArray[byte]): auto = proc(a: AristoDbRef; b: VertexID; c: openArray[byte]): auto =
AristoApiProfFetchPayloadFn.profileRunner: AristoApiProfFetchGenericDataFn.profileRunner:
result = api.fetchPayload(a, b, c) result = api.fetchGenericData(a, b, c)
profApi.fetchStorageData =
proc(a: AristoDbRef; b: openArray[byte]; c: PathID;): auto =
AristoApiProfFetchStorageDataFn.profileRunner:
result = api.fetchStorageData(a, b, c)
profApi.findTx = profApi.findTx =
proc(a: AristoDbRef; b: VertexID; c: HashKey): auto = proc(a: AristoDbRef; b: VertexID; c: HashKey): auto =
@ -685,10 +746,20 @@ func init*(
AristoApiProfHashifyFn.profileRunner: AristoApiProfHashifyFn.profileRunner:
result = api.hashify(a) result = api.hashify(a)
profApi.hasPath = profApi.hasPathAccount =
proc(a: AristoDbRef; b: openArray[byte]): auto =
AristoApiProfHasPathAccountFn.profileRunner:
result = api.hasPathAccount(a, b)
profApi.hasPathGeneric =
proc(a: AristoDbRef; b: VertexID; c: openArray[byte]): auto = proc(a: AristoDbRef; b: VertexID; c: openArray[byte]): auto =
AristoApiProfHasPathFn.profileRunner: AristoApiProfHasPathGenericFn.profileRunner:
result = api.hasPath(a, b, c) result = api.hasPathGeneric(a, b, c)
profApi.hasPathStorage =
proc(a: AristoDbRef; b: openArray[byte]; c: PathID;): auto =
AristoApiProfHasPathStorageFn.profileRunner:
result = api.hasPathStorage(a, b, c)
profApi.hikeUp = profApi.hikeUp =
proc(a: NibblesSeq; b: VertexID; c: AristoDbRef): auto = proc(a: NibblesSeq; b: VertexID; c: AristoDbRef): auto =

View File

@ -19,7 +19,7 @@ import
std/[sets, typetraits], std/[sets, typetraits],
eth/[common, trie/nibbles], eth/[common, trie/nibbles],
results, results,
"."/[aristo_desc, aristo_get, aristo_hike, aristo_layers, aristo_path, "."/[aristo_desc, aristo_get, aristo_hike, aristo_layers,
aristo_utils, aristo_vid] aristo_utils, aristo_vid]
type type

View File

@ -239,9 +239,9 @@ proc forget*(db: AristoDbRef): Result[void,AristoError] =
## comments on `fork()`.) ## comments on `fork()`.)
## ##
if db.isCentre: if db.isCentre:
err(NotAllowedOnCentre) err(DescNotAllowedOnCentre)
elif db notin db.dudes.peers: elif db notin db.dudes.peers:
err(StaleDescriptor) err(DescStaleDescriptor)
else: else:
db.dudes.peers.excl db # Unlink argument `db` from peers list db.dudes.peers.excl db # Unlink argument `db` from peers list
ok() ok()
@ -252,7 +252,7 @@ proc forgetOthers*(db: AristoDbRef): Result[void,AristoError] =
## ##
if not db.dudes.isNil: if not db.dudes.isNil:
if db.dudes.centre != db: if db.dudes.centre != db:
return err(MustBeOnCentre) return err(DescMustBeOnCentre)
db.dudes = DudesRef(nil) db.dudes = DudesRef(nil)
ok() ok()

View File

@ -11,21 +11,16 @@
type type
AristoError* = enum AristoError* = enum
NothingSerious = 0 NothingSerious = 0
# Miscelaneous/unclassified handy helpers
GenericError GenericError
# Rlp decoder, `read()` AccRootUnacceptable
Rlp2Or17ListEntries MptRootUnacceptable
RlpBlobExpected MptRootMissing
RlpBranchHashKeyExpected NotImplemented
RlpEmptyBlobExpected TrieInvalid
RlpExtHashKeyExpected
RlpHashKeyExpected
RlpNonEmptyBlobExpected
RlpOtherException
RlpRlpException
# Serialise decoder
SerCantResolveStorageRoot
# Data record transcoders, `deblobify()` and `blobify()` # Data record transcoders, `deblobify()` and `blobify()`
BlobifyBranchMissingRefs BlobifyBranchMissingRefs
@ -37,6 +32,51 @@ type
BlobifyStateSrcLenGarbled BlobifyStateSrcLenGarbled
BlobifyStateTrgLenGarbled BlobifyStateTrgLenGarbled
# Cache checker `checkCache()`
CheckAnyVidDeadStorageRoot
CheckAnyVidSharedStorageRoot
CheckAnyVtxEmptyKeyMissing
CheckAnyVtxEmptyKeyExpected
CheckAnyVtxEmptyKeyMismatch
CheckAnyVtxBranchLinksMissing
CheckAnyVtxExtPfxMissing
CheckAnyVtxLockWithoutKey
CheckAnyVTopUnset
CheckBeCacheGarbledVTop
CheckBeCacheIsDirty
CheckBeCacheKeyCantCompile
CheckBeCacheKeyDangling
CheckBeCacheKeyMismatch
CheckBeCacheKeyMissing
CheckBeCacheKeyNonEmpty
CheckBeCacheVidUnsynced
CheckBeCacheVtxDangling
CheckBeFifoSrcTrgMismatch
CheckBeFifoTrgNotStateRoot
CheckBeGarbledVTop
CheckBeKeyCantCompile
CheckBeKeyInvalid
CheckBeKeyMismatch
CheckBeKeyMissing
CheckBeVtxBranchLinksMissing
CheckBeVtxExtPfxMissing
CheckBeVtxInvalid
CheckBeVtxMissing
CheckStkKeyStrayZeroEntry
CheckStkVtxIncomplete
CheckStkVtxKeyMismatch
CheckStkVtxKeyMissing
CheckRlxVidVtxMismatch
CheckRlxVtxIncomplete
CheckRlxVtxKeyMissing
CheckRlxVtxKeyMismatch
# De-serialiser from `blobify.nim`
DeblobNilArgument DeblobNilArgument
DeblobUnknown DeblobUnknown
DeblobVtxTooShort DeblobVtxTooShort
@ -64,8 +104,68 @@ type
DeblobFilterTrpVtxSizeGarbled DeblobFilterTrpVtxSizeGarbled
DeblobFilterSizeGarbled DeblobFilterSizeGarbled
# Converter `asNode()`, currenly for unit tests only
CacheMissingNodekeys # Deletion of vertex paths, `deleteXxx()`
DelAccRootNotAccepted
DelBranchExpexted
DelBranchLocked
DelBranchWithoutRefs
DelDanglingStoTrie
DelExtLocked
DelLeafExpexted
DelLeafLocked
DelLeafUnexpected
DelPathNotFound
DelPathTagError
DelRootVidMissing
DelStoAccMissing
DelStoRootMissing
DelStoRootNotAccepted
DelSubTreeAccRoot
DelSubTreeVoidRoot
DelVidStaleVtx
# Functions from `aristo_desc.nim`
DescMustBeOnCentre
DescNotAllowedOnCentre
DescStaleDescriptor
# Functions from `aristo_filter.nim`
FilBackendMissing
FilBackendRoMode
FilNilFilterRejected
FilSiblingsCommitUnfinshed
FilSrcTrgInconsistent
FilStateRootMismatch
FilTrgSrcMismatch
# Fetch functions from `aristo_fetch.nim`
FetchPathNotFound
FetchLeafKeyInvalid
FetchPathInvalid
FetchRootVidMissing
FetchAccRootNotAccepted
FetchStoRootNotAccepted
# Get functions from `aristo_get.nim`
GetFilNotFound
GetFqsNotFound
GetKeyNotFound
GetKeyUpdateNeeded
GetLstNotFound
GetTuvNotFound
GetVtxNotFound
# Update `Merkle` hashes `hashify()`
HashifyVtxUnresolved
HashifyRootVtxUnresolved
HashifyProofHashMismatch
# Path function `hikeUp()` # Path function `hikeUp()`
HikeBranchMissingEdge HikeBranchMissingEdge
@ -79,10 +179,6 @@ type
HikeNoLegs HikeNoLegs
HikeRootMissing HikeRootMissing
# Path/nibble/key conversions in `aisto_path.nim`
PathExpected64Nibbles
PathAtMost64Nibbles
PathExpectedLeaf
# Merge leaf `merge()` # Merge leaf `merge()`
MergeAssemblyFailed # Ooops, internal error MergeAssemblyFailed # Ooops, internal error
@ -119,61 +215,6 @@ type
MergeRootKeysOverflow MergeRootKeysOverflow
MergeRootVidMissing MergeRootVidMissing
# Update `Merkle` hashes `hashify()`
HashifyVtxUnresolved
HashifyRootVtxUnresolved
HashifyProofHashMismatch
# Cache checker `checkCache()`
CheckStkKeyStrayZeroEntry
CheckStkVtxIncomplete
CheckStkVtxKeyMismatch
CheckStkVtxKeyMissing
CheckRlxVidVtxMismatch
CheckRlxVtxIncomplete
CheckRlxVtxKeyMissing
CheckRlxVtxKeyMismatch
CheckAnyVidDeadStorageRoot
CheckAnyVidSharedStorageRoot
CheckAnyVtxEmptyKeyMissing
CheckAnyVtxEmptyKeyExpected
CheckAnyVtxEmptyKeyMismatch
CheckAnyVtxBranchLinksMissing
CheckAnyVtxExtPfxMissing
CheckAnyVtxLockWithoutKey
CheckAnyVTopUnset
# Backend structural check `checkBE()`
CheckBeVtxInvalid
CheckBeVtxMissing
CheckBeVtxBranchLinksMissing
CheckBeVtxExtPfxMissing
CheckBeKeyInvalid
CheckBeKeyMissing
CheckBeKeyCantCompile
CheckBeKeyMismatch
CheckBeGarbledVTop
CheckBeCacheIsDirty
CheckBeCacheKeyMissing
CheckBeCacheKeyNonEmpty
CheckBeCacheVidUnsynced
CheckBeCacheKeyDangling
CheckBeCacheVtxDangling
CheckBeCacheKeyCantCompile
CheckBeCacheKeyMismatch
CheckBeCacheGarbledVTop
CheckBeFifoSrcTrgMismatch
CheckBeFifoTrgNotStateRoot
# Jornal check `checkJournal()`
CheckJrnCachedQidOverlap
CheckJrnSavedQidMissing
CheckJrnSavedQidStale
CheckJrnLinkingGap
# Neighbour vertex, tree traversal `nearbyRight()` and `nearbyLeft()` # Neighbour vertex, tree traversal `nearbyRight()` and `nearbyLeft()`
NearbyBeyondRange NearbyBeyondRange
@ -189,50 +230,12 @@ type
NearbyUnexpectedVtx NearbyUnexpectedVtx
NearbyVidInvalid NearbyVidInvalid
# Deletion of vertices, `delete()`
DelAccRootNotAccepted
DelBranchExpexted
DelBranchLocked
DelBranchWithoutRefs
DelDanglingStoTrie
DelExtLocked
DelLeafExpexted
DelLeafLocked
DelLeafUnexpected
DelPathNotFound
DelPathTagError
DelRootVidMissing
DelStoAccMissing
DelStoRootMissing
DelStoRootNotAccepted
DelSubTreeAccRoot
DelSubTreeVoidRoot
DelVidStaleVtx
# Functions from `aristo_filter.nim` # Path/nibble/key conversions in `aisto_path.nim`
FilBackendMissing PathExpected64Nibbles
FilBackendRoMode PathAtMost64Nibbles
FilNilFilterRejected PathExpectedLeaf
FilSiblingsCommitUnfinshed
FilSrcTrgInconsistent
FilStateRootMismatch
FilTrgSrcMismatch
# Get functions from `aristo_get.nim`
GetLeafMissing
GetKeyUpdateNeeded
GetLeafNotFound
GetVtxNotFound
GetKeyNotFound
GetFilNotFound
GetTuvNotFound
GetLstNotFound
GetFqsNotFound
# Fetch functions from `aristo_fetch.nim`
FetchPathNotFound
LeafKeyInvalid
# RocksDB backend # RocksDB backend
RdbBeCantCreateDataDir RdbBeCantCreateDataDir
@ -256,6 +259,23 @@ type
RdbGuestInstanceUnsupported RdbGuestInstanceUnsupported
RdbHashKeyExpected RdbHashKeyExpected
# Rlp decoder, `read()`
Rlp2Or17ListEntries
RlpBlobExpected
RlpBranchHashKeyExpected
RlpEmptyBlobExpected
RlpExtHashKeyExpected
RlpHashKeyExpected
RlpNonEmptyBlobExpected
RlpOtherException
RlpRlpException
# Serialise decoder
SerCantResolveStorageRoot
# Transaction wrappers # Transaction wrappers
TxAccRootMissing TxAccRootMissing
TxArgStaleTx TxArgStaleTx
@ -267,38 +287,23 @@ type
TxNotFound TxNotFound
TxNotTopTx TxNotTopTx
TxPendingTx TxPendingTx
TxPrettyPointlessLayer
TxStackGarbled TxStackGarbled
TxStackUnderflow TxStackUnderflow
TxPrettyPointlessLayer
TxStateRootMismatch TxStateRootMismatch
# Functions from `aristo_desc.nim`
MustBeOnCentre
NotAllowedOnCentre
StaleDescriptor
# Functions from `aristo_utils.nim` # Functions from `aristo_utils.nim`
AccRlpDecodingError UtilsAccInaccessible
AccStorageKeyMissing UtilsAccLeafPayloadExpected
AccVtxUnsupported UtilsAccNodeUnsupported
AccNodeUnsupported
PayloadTypeUnsupported
UtilsAccPathMissing UtilsAccPathMissing
UtilsAccPathWithoutLeaf UtilsAccPathWithoutLeaf
UtilsAccInaccessible UtilsAccStorageKeyMissing
UtilsAccVtxUnsupported
UtilsAccWrongStorageRoot UtilsAccWrongStorageRoot
UtilsPayloadTypeUnsupported
UtilsStoRootInaccessible UtilsStoRootInaccessible
UtilsStoRootMissing UtilsStoRootMissing
UtilsAccLeafPayloadExpected
# Miscelaneous handy helpers
AccRootUnacceptable
MptRootUnacceptable
MptRootMissing
NotImplemented
TrieInvalid
VidContextLocked
# End # End

View File

@ -14,70 +14,76 @@
{.push raises: [].} {.push raises: [].}
import import
eth/trie/nibbles, std/typetraits,
eth/[common, trie/nibbles],
results, results,
"."/[aristo_desc, aristo_get, aristo_hike] "."/[aristo_desc, aristo_get, aristo_hike, aristo_utils]
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Private functions # Private functions
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
proc fetchPayloadImpl( func mustBeGeneric(
rc: Result[Hike,(VertexID,AristoError,Hike)]; root: VertexID;
): Result[PayloadRef,(VertexID,AristoError)] = ): Result[void,AristoError] =
if rc.isErr: ## Verify that `root` is neither from an accounts tree nor a strorage tree.
if rc.error[1] in HikeAcceptableStopsNotFound: if not root.isValid:
return err((rc.error[0], FetchPathNotFound)) return err(FetchRootVidMissing)
return err((rc.error[0], rc.error[1])) elif root == VertexID(1):
ok rc.value.legs[^1].wp.vtx.lData return err(FetchAccRootNotAccepted)
elif LEAST_FREE_VID <= root.distinctBase:
return err(FetchStoRootNotAccepted)
ok()
proc fetchPayloadImpl(
proc retrievePayload(
db: AristoDbRef; db: AristoDbRef;
root: VertexID; root: VertexID;
path: openArray[byte]; path: openArray[byte];
): Result[PayloadRef,(VertexID,AristoError)] = ): Result[PayloadRef,AristoError] =
path.initNibbleRange.hikeUp(root, db).fetchPayloadImpl 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 # Public functions
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
proc fetchPayload*(
db: AristoDbRef;
key: LeafTie;
): Result[PayloadRef,(VertexID,AristoError)] =
## Cascaded attempt to traverse the `Aristo Trie` and fetch the value of a
## leaf vertex. This function is complementary to `mergePayload()`.
##
key.hikeUp(db).fetchPayloadImpl
proc fetchPayload*(
db: AristoDbRef;
root: VertexID;
path: openArray[byte];
): Result[PayloadRef,(VertexID,AristoError)] =
## Variant of `fetchPayload()`
##
if path.len == 0:
return err((VertexID(0),LeafKeyInvalid))
db.fetchPayloadImpl(root, path)
proc hasPath*(
db: AristoDbRef; # Database
root: VertexID;
path: openArray[byte]; # Key of database record
): Result[bool,(VertexID,AristoError)] =
## Variant of `fetchPayload()`
##
if path.len == 0:
return err((VertexID(0),LeafKeyInvalid))
let rc = db.fetchPayloadImpl(root, path)
if rc.isOk:
return ok(true)
if rc.error[1] == FetchPathNotFound:
return ok(false)
err(rc.error)
proc fetchLastSavedState*( proc fetchLastSavedState*(
db: AristoDbRef; db: AristoDbRef;
): Result[SavedState,AristoError] = ): Result[SavedState,AristoError] =
@ -86,6 +92,74 @@ proc fetchLastSavedState*(
## `uint64` identifier (may be interpreted as block number.) ## `uint64` identifier (may be interpreted as block number.)
db.getLstUbe() 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 # End
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -97,7 +97,7 @@ func layersGetKey*(db: AristoDbRef; vid: VertexID): Opt[HashKey] =
Opt.none(HashKey) Opt.none(HashKey)
func layersGetKeyOrVoid*(db: AristoDbRef; vid: VertexID): HashKey = func layersGetKeyOrVoid*(db: AristoDbRef; vid: VertexID): HashKey =
## Simplified version of `layersGetkey()` ## Simplified version of `layersGetKey()`
db.layersGetKey(vid).valueOr: VOID_HASH_KEY db.layersGetKey(vid).valueOr: VOID_HASH_KEY

View File

@ -120,7 +120,7 @@ proc mergeStorageData*(
## otherwise `VertexID(0)`. ## otherwise `VertexID(0)`.
## ##
let let
accHike = ?db.retrieveStoAccHike accPath accHike = ? db.retrieveStoAccHike accPath # checks for `AccountData`
wpAcc = accHike.legs[^1].wp wpAcc = accHike.legs[^1].wp
stoID = wpAcc.vtx.lData.account.storageID stoID = wpAcc.vtx.lData.account.storageID

View File

@ -40,7 +40,7 @@ proc toAccount*(
acc.storageRoot = (? db.getKeyRc payload.account.storageID).to(Hash256) acc.storageRoot = (? db.getKeyRc payload.account.storageID).to(Hash256)
return ok(acc) return ok(acc)
err PayloadTypeUnsupported err UtilsPayloadTypeUnsupported
proc toAccount*( proc toAccount*(
vtx: VertexRef; vtx: VertexRef;
@ -49,7 +49,7 @@ proc toAccount*(
## Variant of `toAccount()` for a `Leaf` vertex. ## Variant of `toAccount()` for a `Leaf` vertex.
if vtx.isValid and vtx.vType == Leaf: if vtx.isValid and vtx.vType == Leaf:
return vtx.lData.toAccount db return vtx.lData.toAccount db
err AccVtxUnsupported err UtilsAccVtxUnsupported
proc toAccount*( proc toAccount*(
node: NodeRef; node: NodeRef;
@ -65,13 +65,13 @@ proc toAccount*(
storageRoot: EMPTY_ROOT_HASH) storageRoot: EMPTY_ROOT_HASH)
if node.lData.account.storageID.isValid: if node.lData.account.storageID.isValid:
if not node.key[0].isValid: if not node.key[0].isValid:
return err(AccStorageKeyMissing) return err(UtilsAccStorageKeyMissing)
acc.storageRoot = node.key[0].to(Hash256) acc.storageRoot = node.key[0].to(Hash256)
return ok(acc) return ok(acc)
else: else:
return err(PayloadTypeUnsupported) return err(UtilsPayloadTypeUnsupported)
err AccNodeUnsupported err UtilsAccNodeUnsupported
# --------------------- # ---------------------

View File

@ -155,6 +155,7 @@ func toRc[T](
return ok(rc.value) return ok(rc.value)
err rc.error.toError(base, info, error) err rc.error.toError(base, info, error)
func toRc[T]( func toRc[T](
rc: Result[T,AristoError]; rc: Result[T,AristoError];
base: AristoBaseRef; base: AristoBaseRef;
@ -206,12 +207,11 @@ proc mptMethods(cMpt: AristoCoreDxMptRef): CoreDbMptFns =
# The mpt might have become empty # The mpt might have become empty
let let
key = cMpt.address.keccakHash.data key = cMpt.address.keccakHash.data
pyl = api.fetchPayload(mpt, AccountsVID, key).valueOr: acc = api.fetchAccountPayload(mpt, key).valueOr:
raiseAssert "mptColFn(): " & $error[1] & " at " & $error[0] raiseAssert "mptColFn(): " & $error
# Update by accounts data # Update by accounts data
doAssert pyl.pType == AccountData cMpt.mptRoot = acc.storageID
cMpt.mptRoot = pyl.account.storageID
db.bless AristoColRef( db.bless AristoColRef(
base: base, base: base,
@ -222,20 +222,24 @@ proc mptMethods(cMpt: AristoCoreDxMptRef): CoreDbMptFns =
proc mptFetch(key: openArray[byte]): CoreDbRc[Blob] = proc mptFetch(key: openArray[byte]): CoreDbRc[Blob] =
const info = "fetchFn()" const info = "fetchFn()"
# Some pathological behaviour observed with storage column due to lazy let rc = block:
# update. The `fetchPayload()` does not now about this and would complain if cMpt.accPath.isValid:
# an error different from `FetchPathNotFound`. api.fetchStorageData(mpt, key, cMpt.accPath)
let rootVID = cMpt.mptRoot elif cMpt.mptRoot.isValid:
if not rootVID.isValid: api.fetchGenericData(mpt, cMpt.mptRoot, key)
return err((VoidVID,MptRootMissing).toError(base, info, MptNotFound)) else:
# Some pathological behaviour observed with storage column due to lazy
# update. The `fetchXxxPayload()` does not now about this and would
# complain an error different from `FetchPathNotFound`.
return err(MptRootMissing.toError(base, info, MptNotFound))
let rc = api.fetchPayload(mpt, rootVID, key) # let rc = api.fetchPayload(mpt, rootVID, key)
if rc.isOk: if rc.isOk:
api.serialise(mpt, rc.value).toRc(base, info) ok rc.value
elif rc.error[1] != FetchPathNotFound: elif rc.error != FetchPathNotFound:
err(rc.error.toError(base, info)) err(rc.error.toError(base, info))
else: else:
err rc.error.toError(base, info, MptNotFound) err(rc.error.toError(base, info, MptNotFound))
proc mptMerge(k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] = proc mptMerge(k: openArray[byte]; v: openArray[byte]): CoreDbRc[void] =
const info = "mergeFn()" const info = "mergeFn()"
@ -280,7 +284,13 @@ proc mptMethods(cMpt: AristoCoreDxMptRef): CoreDbMptFns =
proc mptHasPath(key: openArray[byte]): CoreDbRc[bool] = proc mptHasPath(key: openArray[byte]): CoreDbRc[bool] =
const info = "hasPathFn()" const info = "hasPathFn()"
let rc = api.hasPath(mpt, cMpt.mptRoot, key) let rc = block:
if cMpt.accPath.isValid:
api.hasPathStorage(mpt, key, cMpt.accPath)
else:
api.hasPathGeneric(mpt, cMpt.mptRoot, key)
#let rc = api.hasPath(mpt, cMpt.mptRoot, key)
if rc.isErr: if rc.isErr:
return err(rc.error.toError(base, info)) return err(rc.error.toError(base, info))
ok(rc.value) ok(rc.value)
@ -333,21 +343,14 @@ proc accMethods(cAcc: AristoCoreDxAccRef): CoreDbAccFns =
proc accFetch(address: EthAddress): CoreDbRc[CoreDbAccount] = proc accFetch(address: EthAddress): CoreDbRc[CoreDbAccount] =
const info = "acc/fetchFn()" const info = "acc/fetchFn()"
let pyl = block: let
let key = address.keccakHash.data
key = address.keccakHash.data acc = api.fetchAccountPayload(mpt, key).valueOr:
rc = api.fetchPayload(mpt, AccountsVID, key) if error != FetchPathNotFound:
if rc.isOk: return err(error.toError(base, info))
rc.value return err(error.toError(base, info, AccNotFound))
elif rc.error[1] != FetchPathNotFound:
return err(rc.error.toError(base, info))
else:
return err(rc.error.toError(base, info, AccNotFound))
if pyl.pType != AccountData: ok cAcc.toCoreDbAccount(acc, address)
let vidErrPair = (pyl.account.storageID, PayloadTypeUnsupported)
return err(vidErrPair.toError(base, info & "/" & $pyl.pType))
ok cAcc.toCoreDbAccount(pyl.account, address)
proc accMerge(account: CoreDbAccount): CoreDbRc[void] = proc accMerge(account: CoreDbAccount): CoreDbRc[void] =
const info = "acc/mergeFn()" const info = "acc/mergeFn()"
@ -385,10 +388,9 @@ proc accMethods(cAcc: AristoCoreDxAccRef): CoreDbAccFns =
let let
key = address.keccakHash.data key = address.keccakHash.data
rc = api.hasPath(mpt, AccountsVID, key) yn = api.hasPathAccount(mpt, key).valueOr:
if rc.isErr: return err(error.toError(base, info))
return err(rc.error.toError(base, info)) ok(yn)
ok(rc.value)
CoreDbAccFns( CoreDbAccFns(
@ -499,7 +501,6 @@ proc ctxMethods(cCtx: AristoCoreDbCtxRef): CoreDbCtxFns =
if reset: if reset:
let rc = api.deleteGenericTree(mpt, newMpt.mptRoot) let rc = api.deleteGenericTree(mpt, newMpt.mptRoot)
if rc.isErr: if rc.isErr:
raiseAssert "find me"
return err(rc.error.toError(base, info, AutoFlushFailed)) return err(rc.error.toError(base, info, AutoFlushFailed))
col.reset = false col.reset = false