mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-10 11:06:49 +00:00
Smaller leaf types
This commit is contained in:
parent
fa09c54a37
commit
a984d54c2d
@ -48,7 +48,8 @@ proc branchStillNeeded(vtx: VertexRef, removed: int8): Result[int8,void] =
|
||||
proc deleteImpl(
|
||||
db: AristoDbRef; # Database, top layer
|
||||
hike: Hike; # Fully expanded path
|
||||
): Result[VertexRef,AristoError] =
|
||||
T: type
|
||||
): Result[Opt[T],AristoError] =
|
||||
## Removes the last node in the hike and returns the updated leaf in case
|
||||
## a branch collapsed
|
||||
|
||||
@ -62,7 +63,7 @@ proc deleteImpl(
|
||||
if hike.legs.len == 1:
|
||||
# This was the last node in the trie, meaning we don't have any branches or
|
||||
# leaves to update
|
||||
return ok(default(VertexRef))
|
||||
return ok(default(Opt[T]))
|
||||
|
||||
if hike.legs[^2].wp.vtx.vType != Branch:
|
||||
return err(DelBranchExpexted)
|
||||
@ -111,16 +112,16 @@ proc deleteImpl(
|
||||
db.layersPutVtx((hike.root, br.vid), vtx)
|
||||
|
||||
if vtx.vType == Leaf:
|
||||
ok(vtx)
|
||||
ok(Opt.some(vtx.to(T)))
|
||||
else:
|
||||
ok(default(VertexRef))
|
||||
ok(Opt.none(T))
|
||||
else:
|
||||
# Clear the removed leaf from the branch (that still contains other children)
|
||||
var brDup = br.vtx.dup
|
||||
discard brDup.setUsed(uint8 hike.legs[^2].nibble, false)
|
||||
db.layersPutVtx((hike.root, br.vid), brDup)
|
||||
|
||||
ok(default(VertexRef))
|
||||
ok(Opt.none(T))
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions
|
||||
@ -145,64 +146,17 @@ proc deleteAccountRecord*(
|
||||
if stoID.isValid:
|
||||
? db.delStoTreeImpl((stoID.vid, stoID.vid), accPath)
|
||||
|
||||
let otherLeaf = ?db.deleteImpl(accHike)
|
||||
let otherLeaf = ?db.deleteImpl(accHike, AccountLeaf)
|
||||
|
||||
db.layersPutAccLeaf(accPath, default(VertexRef))
|
||||
db.layersPutAccLeaf(accPath, default(Opt[AccountLeaf]))
|
||||
|
||||
if otherLeaf.isValid:
|
||||
if otherLeaf.isSome:
|
||||
db.layersPutAccLeaf(
|
||||
Hash32(getBytes(NibblesBuf.fromBytes(accPath.data).replaceSuffix(otherLeaf.pfx))),
|
||||
Hash32(getBytes(NibblesBuf.fromBytes(accPath.data).replaceSuffix(otherLeaf[].pfx))),
|
||||
otherLeaf)
|
||||
|
||||
ok()
|
||||
|
||||
proc deleteGenericData*(
|
||||
db: AristoDbRef;
|
||||
root: VertexID;
|
||||
path: openArray[byte];
|
||||
): Result[bool,AristoError] =
|
||||
## Delete the leaf data entry addressed by the argument `path`. The MPT
|
||||
## sub-tree the leaf data entry is subsumed under is passed as argument
|
||||
## `root` which must be greater than `VertexID(1)` and smaller than
|
||||
## `LEAST_FREE_VID`.
|
||||
##
|
||||
## The return value is `true` if the argument `path` deleted was the last
|
||||
## one and the tree does not exist anymore.
|
||||
##
|
||||
# Verify that `root` is neither an accounts tree nor a strorage tree.
|
||||
if not root.isValid:
|
||||
return err(DelRootVidMissing)
|
||||
elif root == VertexID(1):
|
||||
return err(DelAccRootNotAccepted)
|
||||
elif LEAST_FREE_VID <= root.distinctBase:
|
||||
return err(DelStoRootNotAccepted)
|
||||
|
||||
var hike: Hike
|
||||
path.hikeUp(root, db, Opt.none(VertexRef), hike).isOkOr:
|
||||
if error[1] in HikeAcceptableStopsNotFound:
|
||||
return err(DelPathNotFound)
|
||||
return err(error[1])
|
||||
|
||||
discard ?db.deleteImpl(hike)
|
||||
|
||||
ok(not db.getVtx((root, root)).isValid)
|
||||
|
||||
proc deleteGenericTree*(
|
||||
db: AristoDbRef; # Database, top layer
|
||||
root: VertexID; # Root vertex
|
||||
): Result[void,AristoError] =
|
||||
## Variant of `deleteGenericData()` for purging the whole MPT sub-tree.
|
||||
##
|
||||
# Verify that `root` is neither an accounts tree nor a strorage tree.
|
||||
if not root.isValid:
|
||||
return err(DelRootVidMissing)
|
||||
elif root == VertexID(1):
|
||||
return err(DelAccRootNotAccepted)
|
||||
elif LEAST_FREE_VID <= root.distinctBase:
|
||||
return err(DelStoRootNotAccepted)
|
||||
|
||||
db.delSubTreeImpl root
|
||||
|
||||
proc deleteStorageData*(
|
||||
db: AristoDbRef;
|
||||
accPath: Hash32; # Implies storage data tree
|
||||
@ -220,7 +174,7 @@ proc deleteStorageData*(
|
||||
mixPath = mixUp(accPath, stoPath)
|
||||
stoLeaf = db.cachedStoLeaf(mixPath)
|
||||
|
||||
if stoLeaf == Opt.some(default(VertexRef)):
|
||||
if stoLeaf == Opt.some(default(Opt[StoLeaf])):
|
||||
return err(DelPathNotFound)
|
||||
|
||||
var accHike: Hike
|
||||
@ -246,13 +200,13 @@ proc deleteStorageData*(
|
||||
# Mark account path Merkle keys for update
|
||||
db.layersResKeys accHike
|
||||
|
||||
let otherLeaf = ?db.deleteImpl(stoHike)
|
||||
db.layersPutStoLeaf(mixPath, default(VertexRef))
|
||||
let otherLeaf = ?db.deleteImpl(stoHike, StoLeaf)
|
||||
db.layersPutStoLeaf(mixPath, default(Opt[StoLeaf]))
|
||||
|
||||
if otherLeaf.isValid:
|
||||
if otherLeaf.isSome:
|
||||
let leafMixPath = mixUp(
|
||||
accPath,
|
||||
Hash32(getBytes(stoNibbles.replaceSuffix(otherLeaf.pfx))))
|
||||
Hash32(getBytes(stoNibbles.replaceSuffix(otherLeaf[].pfx))))
|
||||
db.layersPutStoLeaf(leafMixPath, otherLeaf)
|
||||
|
||||
# If there was only one item (that got deleted), update the account as well
|
||||
@ -262,7 +216,7 @@ proc deleteStorageData*(
|
||||
# De-register the deleted storage tree from the account record
|
||||
var leaf = wpAcc.vtx.dup # Dup on modify
|
||||
leaf.lData.stoID.isValid = false
|
||||
db.layersPutAccLeaf(accPath, leaf)
|
||||
db.layersPutAccLeaf(accPath, Opt.some(leaf.to(AccountLeaf)))
|
||||
db.layersPutVtx((accHike.root, wpAcc.vid), leaf)
|
||||
ok(true)
|
||||
|
||||
@ -294,7 +248,7 @@ proc deleteStorageTree*(
|
||||
# De-register the deleted storage tree from the accounts record
|
||||
var leaf = wpAcc.vtx.dup # Dup on modify
|
||||
leaf.lData.stoID.isValid = false
|
||||
db.layersPutAccLeaf(accPath, leaf)
|
||||
db.layersPutAccLeaf(accPath, Opt.some(leaf.to(AccountLeaf)))
|
||||
db.layersPutVtx((accHike.root, wpAcc.vid), leaf)
|
||||
ok()
|
||||
|
||||
|
@ -61,7 +61,7 @@ proc delStoTreeNow(
|
||||
|
||||
of Leaf:
|
||||
let stoPath = Hash32((stoPath & vtx.pfx).getBytes())
|
||||
db.layersPutStoLeaf(mixUp(accPath, stoPath), default(VertexRef))
|
||||
db.layersPutStoLeaf(mixUp(accPath, stoPath), default(Opt[StoLeaf]))
|
||||
|
||||
db.layersResVtx(rvid)
|
||||
|
||||
|
@ -64,7 +64,7 @@ type
|
||||
txUidGen*: uint ## Tx-relative unique number generator
|
||||
dudes: DudesRef ## Related DB descriptors
|
||||
|
||||
accLeaves*: LruCache[Hash32, VertexRef]
|
||||
accLeaves*: LruCache[Hash32, Opt[AccountLeaf]]
|
||||
## Account path to payload cache - accounts are frequently accessed by
|
||||
## account path when contracts interact with them - this cache ensures
|
||||
## that we don't have to re-traverse the storage trie for every such
|
||||
@ -72,7 +72,7 @@ type
|
||||
## TODO a better solution would probably be to cache this in a type
|
||||
## exposed to the high-level API
|
||||
|
||||
stoLeaves*: LruCache[Hash32, VertexRef]
|
||||
stoLeaves*: LruCache[Hash32, Opt[StoLeaf]]
|
||||
## Mixed account/storage path to payload cache - same as above but caches
|
||||
## the full lookup of storage slots
|
||||
|
||||
|
@ -79,6 +79,15 @@ type
|
||||
startVid*: VertexID
|
||||
used*: uint16
|
||||
|
||||
AccountLeaf* = object
|
||||
pfx*: NibblesBuf
|
||||
account*: AristoAccount
|
||||
stoID*: StorageID
|
||||
|
||||
StoLeaf* = object
|
||||
pfx*: NibblesBuf
|
||||
stoData*: UInt256
|
||||
|
||||
NodeRef* = ref object of RootRef
|
||||
## Combined record for a *traditional* ``Merkle Patricia Tree` node merged
|
||||
## with a structural `VertexRef` type object.
|
||||
@ -125,8 +134,8 @@ type
|
||||
kMap*: Table[RootedVertexID,HashKey] ## Merkle hash key mapping
|
||||
vTop*: VertexID ## Last used vertex ID
|
||||
|
||||
accLeaves*: Table[Hash32, VertexRef] ## Account path -> VertexRef
|
||||
stoLeaves*: Table[Hash32, VertexRef] ## Storage path -> VertexRef
|
||||
accLeaves*: Table[Hash32, Opt[AccountLeaf]] ## Account path -> VertexRef
|
||||
stoLeaves*: Table[Hash32, Opt[StoLeaf]] ## Storage path -> VertexRef
|
||||
|
||||
txUid*: uint ## Transaction identifier if positive
|
||||
|
||||
@ -196,6 +205,18 @@ proc `==`*(a, b: VertexRef): bool =
|
||||
return false
|
||||
true
|
||||
|
||||
func to*(v: VertexRef, _: type AccountLeaf): AccountLeaf =
|
||||
AccountLeaf(pfx: v.pfx, account: v.lData.account, stoID: v.lData.stoID)
|
||||
|
||||
func to*(v: VertexRef, _: type StoLeaf): StoLeaf =
|
||||
StoLeaf(pfx: v.pfx, stoData: v.lData.stoData)
|
||||
|
||||
func to*(v: AccountLeaf, _: type VertexRef): VertexRef =
|
||||
VertexRef(pfx: v.pfx, vType: Leaf, lData: LeafPayload(pType: AccountData, account: v.account, stoID: v.stoID))
|
||||
|
||||
func to*(v: StoLeaf, _: type VertexRef): VertexRef =
|
||||
VertexRef(pfx: v.pfx, vType: Leaf, lData: LeafPayload(pType: StoData, stoData: v.stoData))
|
||||
|
||||
iterator pairs*(vtx: VertexRef): tuple[nibble: uint8, vid: VertexID] =
|
||||
## Iterates over the sub-vids of a branch (does nothing for leaves)
|
||||
case vtx.vType:
|
||||
|
@ -27,7 +27,8 @@ proc retrieveLeaf(
|
||||
db: AristoDbRef;
|
||||
root: VertexID;
|
||||
path: Hash32;
|
||||
): Result[VertexRef,AristoError] =
|
||||
T: type
|
||||
): Result[T,AristoError] =
|
||||
for step in stepUp(NibblesBuf.fromBytes(path.data), root, db):
|
||||
let vtx = step.valueOr:
|
||||
if error in HikeAcceptableStopsNotFound:
|
||||
@ -35,42 +36,42 @@ proc retrieveLeaf(
|
||||
return err(error)
|
||||
|
||||
if vtx.vType == Leaf:
|
||||
return ok vtx
|
||||
return ok vtx.to(T)
|
||||
|
||||
return err(FetchPathNotFound)
|
||||
|
||||
proc cachedAccLeaf*(db: AristoDbRef; accPath: Hash32): Opt[VertexRef] =
|
||||
proc cachedAccLeaf*(db: AristoDbRef; accPath: Hash32): Opt[Opt[AccountLeaf]] =
|
||||
# Return vertex from layers or cache, `nil` if it's known to not exist and
|
||||
# none otherwise
|
||||
db.layersGetAccLeaf(accPath) or
|
||||
db.accLeaves.get(accPath) or
|
||||
Opt.none(VertexRef)
|
||||
Opt.none(Opt[AccountLeaf])
|
||||
|
||||
proc cachedStoLeaf*(db: AristoDbRef; mixPath: Hash32): Opt[VertexRef] =
|
||||
proc cachedStoLeaf*(db: AristoDbRef; mixPath: Hash32): Opt[Opt[StoLeaf]] =
|
||||
# Return vertex from layers or cache, `nil` if it's known to not exist and
|
||||
# none otherwise
|
||||
db.layersGetStoLeaf(mixPath) or
|
||||
db.stoLeaves.get(mixPath) or
|
||||
Opt.none(VertexRef)
|
||||
Opt.none(Opt[StoLeaf])
|
||||
|
||||
proc retrieveAccountLeaf(
|
||||
db: AristoDbRef;
|
||||
accPath: Hash32;
|
||||
): Result[VertexRef,AristoError] =
|
||||
): Result[AccountLeaf,AristoError] =
|
||||
if (let leafVtx = db.cachedAccLeaf(accPath); leafVtx.isSome()):
|
||||
if not leafVtx[].isValid():
|
||||
if not leafVtx[].isSome():
|
||||
return err(FetchPathNotFound)
|
||||
return ok leafVtx[]
|
||||
return ok leafVtx[][]
|
||||
|
||||
# Updated payloads are stored in the layers so if we didn't find them there,
|
||||
# it must have been in the database
|
||||
let
|
||||
leafVtx = db.retrieveLeaf(VertexID(1), accPath).valueOr:
|
||||
leafVtx = db.retrieveLeaf(VertexID(1), accPath, AccountLeaf).valueOr:
|
||||
if error == FetchPathNotFound:
|
||||
db.accLeaves.put(accPath, default(VertexRef))
|
||||
db.accLeaves.put(accPath, default(Opt[AccountLeaf]))
|
||||
return err(error)
|
||||
|
||||
db.accLeaves.put(accPath, leafVtx)
|
||||
db.accLeaves.put(accPath, Opt.some(leafVtx))
|
||||
|
||||
ok leafVtx
|
||||
|
||||
@ -105,7 +106,7 @@ proc fetchStorageIdImpl(
|
||||
## Helper function for retrieving a storage (vertex) ID for a given account.
|
||||
let
|
||||
leafVtx = ?db.retrieveAccountLeaf(accPath)
|
||||
stoID = leafVtx.lData.stoID
|
||||
stoID = leafVtx.stoID
|
||||
|
||||
if stoID.isValid:
|
||||
ok stoID.vid
|
||||
@ -126,11 +127,11 @@ proc fetchAccountHike*(
|
||||
## Expand account path to account leaf or return failure
|
||||
|
||||
# Prefer the leaf cache so as not to burden the lower layers
|
||||
let leaf = db.cachedAccLeaf(accPath)
|
||||
if leaf == Opt.some(default(VertexRef)):
|
||||
let accLeaf = db.cachedAccLeaf(accPath)
|
||||
if accLeaf == Opt.some(Opt.none(AccountLeaf)):
|
||||
return err(FetchAccInaccessible)
|
||||
|
||||
accPath.hikeUp(VertexID(1), db, leaf, accHike).isOkOr:
|
||||
accPath.hikeUp(VertexID(1), db, accLeaf, accHike).isOkOr:
|
||||
return err(FetchAccInaccessible)
|
||||
|
||||
# Extract the account payload from the leaf
|
||||
@ -159,20 +160,20 @@ proc retrieveStoragePayload(
|
||||
let mixPath = mixUp(accPath, stoPath)
|
||||
|
||||
if (let leafVtx = db.cachedStoLeaf(mixPath); leafVtx.isSome()):
|
||||
if not leafVtx[].isValid():
|
||||
if not leafVtx[].isSome():
|
||||
return err(FetchPathNotFound)
|
||||
return ok leafVtx[].lData.stoData
|
||||
return ok leafVtx[][].stoData
|
||||
|
||||
# Updated payloads are stored in the layers so if we didn't find them there,
|
||||
# it must have been in the database
|
||||
let leafVtx = db.retrieveLeaf(? db.fetchStorageIdImpl(accPath), stoPath).valueOr:
|
||||
let leafVtx = db.retrieveLeaf(? db.fetchStorageIdImpl(accPath), stoPath, StoLeaf).valueOr:
|
||||
if error == FetchPathNotFound:
|
||||
db.stoLeaves.put(mixPath, default(VertexRef))
|
||||
db.stoLeaves.put(mixPath, default(Opt[StoLeaf]))
|
||||
return err(error)
|
||||
|
||||
db.stoLeaves.put(mixPath, leafVtx)
|
||||
db.stoLeaves.put(mixPath, Opt.some(leafVtx))
|
||||
|
||||
ok leafVtx.lData.stoData
|
||||
ok leafVtx.stoData
|
||||
|
||||
proc hasStoragePayload(
|
||||
db: AristoDbRef;
|
||||
@ -205,9 +206,8 @@ proc fetchAccountRecord*(
|
||||
## Fetch an account record from the database indexed by `accPath`.
|
||||
##
|
||||
let leafVtx = ? db.retrieveAccountLeaf(accPath)
|
||||
assert leafVtx.lData.pType == AccountData # debugging only
|
||||
|
||||
ok leafVtx.lData.account
|
||||
ok leafVtx.account
|
||||
|
||||
proc fetchStateRoot*(
|
||||
db: AristoDbRef;
|
||||
|
@ -124,11 +124,11 @@ iterator stepUp*(
|
||||
if path.len == 0:
|
||||
break
|
||||
|
||||
proc hikeUp*(
|
||||
proc hikeUp*[T](
|
||||
path: NibblesBuf; # Partial path
|
||||
root: VertexID; # Start vertex
|
||||
db: AristoDbRef; # Database
|
||||
leaf: Opt[VertexRef];
|
||||
leaf: Opt[T];
|
||||
hike: var Hike;
|
||||
): Result[void,(VertexID,AristoError)] =
|
||||
## For the argument `path`, find and return the logest possible path in the
|
||||
@ -147,10 +147,11 @@ proc hikeUp*(
|
||||
|
||||
var vid = root
|
||||
while true:
|
||||
if leaf.isSome() and leaf[].isValid and path == leaf[].pfx:
|
||||
hike.legs.add Leg(wp: VidVtxPair(vid: vid, vtx: leaf[]), nibble: -1)
|
||||
reset(hike.tail)
|
||||
break
|
||||
when T is Opt[AccountLeaf] or T is Opt[StoLeaf]:
|
||||
if leaf.isSome() and leaf[].isSome and path == leaf[][].pfx:
|
||||
hike.legs.add Leg(wp: VidVtxPair(vid: vid, vtx: leaf[][].to(VertexRef)), nibble: -1)
|
||||
reset(hike.tail)
|
||||
break
|
||||
|
||||
let (vtx, path, next) = step(hike.tail, (root, vid), db).valueOr:
|
||||
return err((vid,error))
|
||||
@ -173,30 +174,30 @@ proc hikeUp*(
|
||||
|
||||
ok()
|
||||
|
||||
proc hikeUp*(
|
||||
proc hikeUp*[T](
|
||||
lty: LeafTie;
|
||||
db: AristoDbRef;
|
||||
leaf: Opt[VertexRef];
|
||||
leaf: Opt[T];
|
||||
hike: var Hike
|
||||
): Result[void,(VertexID,AristoError)] =
|
||||
## Variant of `hike()`
|
||||
lty.path.to(NibblesBuf).hikeUp(lty.root, db, leaf, hike)
|
||||
|
||||
proc hikeUp*(
|
||||
proc hikeUp*[T](
|
||||
path: openArray[byte];
|
||||
root: VertexID;
|
||||
db: AristoDbRef;
|
||||
leaf: Opt[VertexRef];
|
||||
leaf: Opt[T];
|
||||
hike: var Hike
|
||||
): Result[void,(VertexID,AristoError)] =
|
||||
## Variant of `hike()`
|
||||
NibblesBuf.fromBytes(path).hikeUp(root, db, leaf, hike)
|
||||
|
||||
proc hikeUp*(
|
||||
proc hikeUp*[T](
|
||||
path: Hash32;
|
||||
root: VertexID;
|
||||
db: AristoDbRef;
|
||||
leaf: Opt[VertexRef];
|
||||
leaf: Opt[T];
|
||||
hike: var Hike
|
||||
): Result[void,(VertexID,AristoError)] =
|
||||
## Variant of `hike()`
|
||||
|
@ -54,8 +54,8 @@ proc newAristoRdbDbRef(
|
||||
ok((AristoDbRef(
|
||||
top: LayerRef(vTop: vTop),
|
||||
backend: be,
|
||||
accLeaves: LruCache[Hash32, VertexRef].init(ACC_LRU_SIZE),
|
||||
stoLeaves: LruCache[Hash32, VertexRef].init(ACC_LRU_SIZE),
|
||||
accLeaves: LruCache[Hash32, Opt[AccountLeaf]].init(ACC_LRU_SIZE),
|
||||
stoLeaves: LruCache[Hash32, Opt[StoLeaf]].init(ACC_LRU_SIZE),
|
||||
), oCfs))
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -91,7 +91,7 @@ func layersGetKeyOrVoid*(db: AristoDbRef; rvid: RootedVertexID): HashKey =
|
||||
## Simplified version of `layersGetKey()`
|
||||
(db.layersGetKey(rvid).valueOr (VOID_HASH_KEY, 0))[0]
|
||||
|
||||
func layersGetAccLeaf*(db: AristoDbRef; accPath: Hash32): Opt[VertexRef] =
|
||||
func layersGetAccLeaf*(db: AristoDbRef; accPath: Hash32): Opt[Opt[AccountLeaf]] =
|
||||
db.top.accLeaves.withValue(accPath, item):
|
||||
return Opt.some(item[])
|
||||
|
||||
@ -99,9 +99,9 @@ func layersGetAccLeaf*(db: AristoDbRef; accPath: Hash32): Opt[VertexRef] =
|
||||
w.accLeaves.withValue(accPath, item):
|
||||
return Opt.some(item[])
|
||||
|
||||
Opt.none(VertexRef)
|
||||
Opt.none(Opt[AccountLeaf])
|
||||
|
||||
func layersGetStoLeaf*(db: AristoDbRef; mixPath: Hash32): Opt[VertexRef] =
|
||||
func layersGetStoLeaf*(db: AristoDbRef; mixPath: Hash32): Opt[Opt[StoLeaf]] =
|
||||
db.top.stoLeaves.withValue(mixPath, item):
|
||||
return Opt.some(item[])
|
||||
|
||||
@ -109,7 +109,7 @@ func layersGetStoLeaf*(db: AristoDbRef; mixPath: Hash32): Opt[VertexRef] =
|
||||
w.stoLeaves.withValue(mixPath, item):
|
||||
return Opt.some(item[])
|
||||
|
||||
Opt.none(VertexRef)
|
||||
Opt.none(Opt[StoLeaf])
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions: setter variants
|
||||
@ -153,10 +153,10 @@ func layersResKeys*(db: AristoDbRef; hike: Hike) =
|
||||
for i in 1..hike.legs.len:
|
||||
db.layersResKey((hike.root, hike.legs[^i].wp.vid), hike.legs[^i].wp.vtx)
|
||||
|
||||
func layersPutAccLeaf*(db: AristoDbRef; accPath: Hash32; leafVtx: VertexRef) =
|
||||
func layersPutAccLeaf*(db: AristoDbRef; accPath: Hash32; leafVtx: Opt[AccountLeaf]) =
|
||||
db.top.accLeaves[accPath] = leafVtx
|
||||
|
||||
func layersPutStoLeaf*(db: AristoDbRef; mixPath: Hash32; leafVtx: VertexRef) =
|
||||
func layersPutStoLeaf*(db: AristoDbRef; mixPath: Hash32; leafVtx: Opt[StoLeaf]) =
|
||||
db.top.stoLeaves[mixPath] = leafVtx
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -38,13 +38,13 @@ proc layersPutLeaf(
|
||||
db.layersPutVtx(rvid, vtx)
|
||||
vtx
|
||||
|
||||
proc mergePayloadImpl(
|
||||
proc mergePayloadImpl[T](
|
||||
db: AristoDbRef, # Database, top layer
|
||||
root: VertexID, # MPT state root
|
||||
path: Hash32, # Leaf item to add to the database
|
||||
leaf: Opt[VertexRef],
|
||||
leaf: Opt[Opt[T]],
|
||||
payload: LeafPayload, # Payload value
|
||||
): Result[(VertexRef, VertexRef, VertexRef), AristoError] =
|
||||
): Result[(T, Opt[NibblesBuf], Opt[T]), AristoError] =
|
||||
## Merge the argument `(root,path)` key-value-pair into the top level vertex
|
||||
## table of the database `db`. The `path` argument is used to address the
|
||||
## leaf vertex with the payload. It is stored or updated on the database
|
||||
@ -59,7 +59,7 @@ proc mergePayloadImpl(
|
||||
|
||||
# We're at the root vertex and there is no data - this must be a fresh
|
||||
# VertexID!
|
||||
return ok (db.layersPutLeaf((root, cur), path, payload), default(VertexRef), default(VertexRef))
|
||||
return ok (db.layersPutLeaf((root, cur), path, payload).to(T), Opt.none(NibblesBuf), Opt.none(T))
|
||||
vids: ArrayBuf[NibblesBuf.high + 1, VertexID]
|
||||
vtxs: ArrayBuf[NibblesBuf.high + 1, VertexRef]
|
||||
|
||||
@ -93,7 +93,7 @@ proc mergePayloadImpl(
|
||||
db.layersPutLeaf((root, cur), path, payload)
|
||||
else:
|
||||
db.layersPutLeaf((root, cur), path, payload)
|
||||
(leafVtx, default(VertexRef), default(VertexRef))
|
||||
(leafVtx.to(T), Opt.none(NibblesBuf), Opt.none(T))
|
||||
else:
|
||||
# Turn leaf into a branch (or extension) then insert the two leaves
|
||||
# into the branch
|
||||
@ -111,7 +111,7 @@ proc mergePayloadImpl(
|
||||
|
||||
# We need to return vtx here because its pfx member hasn't yet been
|
||||
# sliced off and is therefore shared with the hike
|
||||
(leafVtx, vtx, other)
|
||||
(leafVtx.to(T), Opt.some(vtx.pfx), Opt.some(other.to(T)))
|
||||
|
||||
resetKeys()
|
||||
return ok(res)
|
||||
@ -126,8 +126,8 @@ proc mergePayloadImpl(
|
||||
cur = next
|
||||
path = path.slice(n + 1)
|
||||
vtx =
|
||||
if leaf.isSome and leaf[].isValid and leaf[].pfx == path:
|
||||
leaf[]
|
||||
if leaf.isSome and leaf[].isSome and leaf[][].pfx == path:
|
||||
leaf[][].to(VertexRef)
|
||||
else:
|
||||
(?db.getVtxRc((root, next)))[0]
|
||||
|
||||
@ -143,7 +143,7 @@ proc mergePayloadImpl(
|
||||
leafVtx = db.layersPutLeaf((root, local), path.slice(n + 1), payload)
|
||||
|
||||
resetKeys()
|
||||
return ok((leafVtx, default(VertexRef), default(VertexRef)))
|
||||
return ok((leafVtx.to(T), Opt.none(NibblesBuf), Opt.none(T)))
|
||||
else:
|
||||
# Partial path match - we need to split the existing branch at
|
||||
# the point of divergence, inserting a new branch
|
||||
@ -163,7 +163,7 @@ proc mergePayloadImpl(
|
||||
db.layersPutVtx((root, cur), branch)
|
||||
|
||||
resetKeys()
|
||||
return ok((leafVtx, default(VertexRef), default(VertexRef)))
|
||||
return ok((leafVtx.to(T), Opt.none(NibblesBuf), Opt.none(T)))
|
||||
|
||||
err(MergeHikeFailed)
|
||||
|
||||
@ -193,10 +193,10 @@ proc mergeAccountRecord*(
|
||||
|
||||
# Update leaf cache both of the merged value and potentially the displaced
|
||||
# leaf resulting from splitting a leaf into a branch with two leaves
|
||||
db.layersPutAccLeaf(accPath, updated[0])
|
||||
if updated[1].isValid:
|
||||
db.layersPutAccLeaf(accPath, Opt.some(updated[0]))
|
||||
if updated[1].isSome:
|
||||
let otherPath = Hash32(getBytes(
|
||||
NibblesBuf.fromBytes(accPath.data).replaceSuffix(updated[1].pfx)))
|
||||
NibblesBuf.fromBytes(accPath.data).replaceSuffix(updated[1][])))
|
||||
db.layersPutAccLeaf(otherPath, updated[2])
|
||||
|
||||
ok true
|
||||
@ -239,18 +239,18 @@ proc mergeStorageData*(
|
||||
|
||||
# Update leaf cache both of the merged value and potentially the displaced
|
||||
# leaf resulting from splitting a leaf into a branch with two leaves
|
||||
db.layersPutStoLeaf(mixPath, updated[0])
|
||||
db.layersPutStoLeaf(mixPath, Opt.some(updated[0]))
|
||||
|
||||
if updated[1].isValid:
|
||||
if updated[1].isSome:
|
||||
let otherPath = Hash32(getBytes(
|
||||
NibblesBuf.fromBytes(stoPath.data).replaceSuffix(updated[1].pfx)))
|
||||
NibblesBuf.fromBytes(stoPath.data).replaceSuffix(updated[1][])))
|
||||
db.layersPutStoLeaf(mixUp(accPath, otherPath), updated[2])
|
||||
|
||||
if not stoID.isValid:
|
||||
# Make sure that there is an account that refers to that storage trie
|
||||
var leaf = accHike.legs[^1].wp.vtx.dup # Dup on modify
|
||||
leaf.lData.stoID = useID
|
||||
db.layersPutAccLeaf(accPath, leaf)
|
||||
db.layersPutAccLeaf(accPath, Opt.some(leaf.to(AccountLeaf)))
|
||||
db.layersPutVtx((VertexID(1), accHike.legs[^1].wp.vid), leaf)
|
||||
|
||||
ok()
|
||||
|
@ -145,9 +145,9 @@ proc zeroAdjust(
|
||||
|
||||
proc toHike(pfx: NibblesBuf, root: VertexID, db: AristoDbRef): Hike =
|
||||
when doLeast:
|
||||
discard pfx.pathPfxPad(0).hikeUp(root, db, Opt.none(VertexRef), result)
|
||||
discard pfx.pathPfxPad(0).hikeUp(root, db, Opt.none(void), result)
|
||||
else:
|
||||
discard pfx.pathPfxPad(255).hikeUp(root, db, Opt.none(VertexRef), result)
|
||||
discard pfx.pathPfxPad(255).hikeUp(root, db, Opt.none(void), result)
|
||||
|
||||
if 0 < hike.legs.len:
|
||||
return ok(hike)
|
||||
@ -354,7 +354,7 @@ proc nearbyNextLeafTie(
|
||||
): Result[PathID,(VertexID,AristoError)] =
|
||||
## Variant of `nearbyNext()`, convenience wrapper
|
||||
var hike: Hike
|
||||
discard lty.hikeUp(db, Opt.none(VertexRef), hike)
|
||||
discard lty.hikeUp(db, Opt.none(void), hike)
|
||||
hike = ?hike.nearbyNext(db, hikeLenMax, moveRight)
|
||||
|
||||
if 0 < hike.legs.len:
|
||||
@ -403,7 +403,7 @@ iterator rightPairs*(
|
||||
## Traverse the sub-trie implied by the argument `start` with increasing
|
||||
## order.
|
||||
var hike: Hike
|
||||
discard start.hikeUp(db, Opt.none(VertexRef), hike)
|
||||
discard start.hikeUp(db, Opt.none(void), hike)
|
||||
var rc = hike.right db
|
||||
while rc.isOk:
|
||||
hike = rc.value
|
||||
@ -431,7 +431,7 @@ iterator rightPairs*(
|
||||
hike.legs.setLen(hike.legs.len - 1)
|
||||
break reuseHike
|
||||
# Fall back to default method
|
||||
discard key.next.hikeUp(db, Opt.none(VertexRef), hike)
|
||||
discard key.next.hikeUp(db, Opt.none(void), hike)
|
||||
|
||||
rc = hike.right db
|
||||
# End while
|
||||
@ -488,7 +488,7 @@ iterator leftPairs*(
|
||||
## the `path` field decremented by `1`.
|
||||
var
|
||||
hike: Hike
|
||||
discard start.hikeUp(db, Opt.none(VertexRef), hike)
|
||||
discard start.hikeUp(db, Opt.none(void), hike)
|
||||
|
||||
var rc = hike.left db
|
||||
while rc.isOk:
|
||||
@ -517,7 +517,7 @@ iterator leftPairs*(
|
||||
hike.legs.setLen(hike.legs.len - 1)
|
||||
break reuseHike
|
||||
# Fall back to default method
|
||||
discard key.prev.hikeUp(db, Opt.none(VertexRef), hike)
|
||||
discard key.prev.hikeUp(db, Opt.none(void), hike)
|
||||
|
||||
rc = hike.left db
|
||||
# End while
|
||||
|
@ -125,27 +125,17 @@ proc ctxAcceptChange(psc: PartStateCtx): Result[bool,AristoError] =
|
||||
|
||||
proc ctxMergeBegin*(
|
||||
ps: PartStateRef;
|
||||
root: VertexID;
|
||||
path: openArray[byte];
|
||||
accPath: Hash32;
|
||||
): Result[PartStateCtx,AristoError] =
|
||||
## This function clears the way for mering some payload at the argument
|
||||
## path `(root,path)`.
|
||||
## Variant of `partMergeBegin()` for different path representation
|
||||
var hike: Hike
|
||||
path.hikeUp(root,ps.db, Opt.none(VertexRef), hike).isOkOr:
|
||||
accPath.hikeUp(VertexID(1),ps.db, Opt.none(Opt[AccountLeaf]), hike).isOkOr:
|
||||
if error[1] != HikeDanglingEdge:
|
||||
return err error[1] # Cannot help here
|
||||
return ps.newCtx hike
|
||||
|
||||
ok PartStateCtx(nil) # Nothing to do
|
||||
|
||||
proc ctxMergeBegin*(
|
||||
ps: PartStateRef;
|
||||
accPath: Hash32;
|
||||
): Result[PartStateCtx,AristoError] =
|
||||
## Variant of `partMergeBegin()` for different path representation
|
||||
ps.ctxMergeBegin(VertexID(1), accPath.data)
|
||||
|
||||
|
||||
proc ctxMergeCommit*(psc: PartStateCtx): Result[bool,AristoError] =
|
||||
##
|
||||
if psc.isNil:
|
||||
|
@ -153,7 +153,7 @@ proc testCreatePortalProof(node: JsonNode, testStatusIMPL: var TestStatus) {.dep
|
||||
let
|
||||
path = a.data.keccak256
|
||||
var hike: Hike
|
||||
let rc = path.hikeUp(VertexID(1), ps.db, Opt.none(VertexRef), hike)
|
||||
let rc = path.hikeUp(VertexID(1), ps.db, Opt.none(void), hike)
|
||||
sample[path] = ProofData(
|
||||
error: (if rc.isErr: rc.error[1] else: AristoError(0)),
|
||||
hike: hike) # keep `hike` for potential debugging
|
||||
|
@ -95,7 +95,7 @@ proc randomisedLeafs(
|
||||
var lvp: seq[(LeafTie,RootedVertexID)]
|
||||
for lty in ltys:
|
||||
var hike: Hike
|
||||
?lty.hikeUp(db, Opt.none(VertexRef), hike)
|
||||
?lty.hikeUp(db, Opt.none(void), hike)
|
||||
lvp.add (lty,(hike.root, hike.legs[^1].wp.vid))
|
||||
|
||||
var lvp2 = lvp.sorted(
|
||||
|
Loading…
x
Reference in New Issue
Block a user