Skip to content

Commit

Permalink
Added delete fuctionality (status-im#1596)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjfh authored Jun 2, 2023
1 parent 099444a commit 11bb33d
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 19 deletions.
135 changes: 135 additions & 0 deletions nimbus/db/aristo/aristo_delete.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# nimbus-eth1
# Copyright (c) 2021 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 -- Patricia Trie delete funcionality
## ==============================================
##
## Deleate by `Hike` type chain of vertices.

{.push raises: [].}

import
std/[sets, tables],
chronicles,
eth/[common, trie/nibbles],
stew/results,
"."/[aristo_constants, aristo_desc, aristo_error, aristo_get, aristo_hike,
aristo_path, aristo_vid]

logScope:
topics = "aristo-delete"

# ------------------------------------------------------------------------------
# Private functions
# ------------------------------------------------------------------------------

proc branchStillNeeded(vtx: VertexRef): bool =
for n in 0 .. 15:
if vtx.bVid[n] != VertexID(0):
return true

proc clearKey(db: AristoDbRef; vid: VertexID) =
let key = db.kMap.getOrDefault(vid, EMPTY_ROOT_KEY)
if key != EMPTY_ROOT_KEY:
db.kMap.del vid
db.pAmk.del key

proc doneWith(db: AristoDbRef; vid: VertexID) =
# Remove entry
db.vidDispose vid
db.sTab.del vid
db.clearKey vid # Update Merkle hash


proc deleteImpl(
hike: Hike; # Fully expanded path
pathTag: NodeTag; # `Patricia Trie` path root-to-leaf
db: AristoDbRef; # Database, top layer
): Result[void,(VertexID,AristoError)] =
## Implementation of *delete* functionality.
if hike.error != AristoError(0):
if 0 < hike.legs.len:
return err((hike.legs[^1].wp.vid,hike.error))
return err((VertexID(0),hike.error))

# doAssert 0 < hike.legs.len and hike.tail.len == 0 # as assured by `hikeUp()`
var inx = hike.legs.len - 1

# Remove leaf entry on the top
let lf = hike.legs[inx].wp
if lf.vtx.vType != Leaf:
return err((lf.vid,DelLeafExpexted))
if lf.vid in db.pPrf:
return err((lf.vid, DelLeafLocked))
db.doneWith lf.vid
inx.dec

while 0 <= inx:
# Unlink child node
let br = hike.legs[inx].wp
if br.vtx.vType != Branch:
return err((br.vid,DelBranchExpexted))
if br.vid in db.pPrf:
return err((br.vid, DelBranchLocked))
br.vtx.bVid[hike.legs[inx].nibble] = VertexID(0)

if br.vtx.branchStillNeeded:
db.clearKey br.vid
break

# Remove this `Branch` entry
db.doneWith br.vid
inx.dec

if inx < 0:
break

# There might be an optional `Extension` to remove
let ext = hike.legs[inx].wp
if ext.vtx.vType == Extension:
if br.vid in db.pPrf:
return err((ext.vid, DelExtLocked))
db.doneWith ext.vid
inx.dec

# Delete leaf entry
db.lTab.del pathTag
if db.lTab.len == 0:
db.lRoot = VertexID(0)

ok()

# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------

proc delete*(
hike: Hike; # Fully expanded chain of vertices
db: AristoDbRef; # Database, top layer
): Result[void,(VertexID,AristoError)] =
## Delete argument `hike` chain of vertices from the database
# Need path in order to remove it from `lTab[]`
let pathTag = block:
let rc = hike.to(NibblesSeq).pathToTag()
if rc.isErr:
return err((VertexID(0),DelPathTagError))
rc.value
hike.deleteImpl(pathTag, db)

proc delete*(
pathTag: NodeTag; # `Patricia Trie` path root-to-leaf
db: AristoDbRef; # Database, top layer
): Result[void,(VertexID,AristoError)] =
## Variant of `delete()`
pathTag.hikeUp(db.lRoot, db).deleteImpl(pathTag, db)

# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------
8 changes: 8 additions & 0 deletions nimbus/db/aristo/aristo_error.nim
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,12 @@ type
NearbyPathTailInxOverflow
NearbyUnexpectedVtx

# Deletion of vertices, `delete()`
DelPathTagError
DelLeafExpexted
DelLeafLocked
DelBranchExpexted
DelBranchLocked
DelExtLocked

# End
3 changes: 3 additions & 0 deletions nimbus/db/aristo/aristo_merge.nim
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ proc `xPfx=`(vtx: VertexRef, val: NibblesSeq) =
of Branch:
doAssert vtx.vType != Branch # Ooops

# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------

proc clearMerkleKeys(
db: AristoDbRef; # Database, top layer
Expand Down
26 changes: 13 additions & 13 deletions nimbus/db/aristo/aristo_nearby.nim
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ proc branchNibbleMax*(vtx: VertexRef; maxInx: int8): int8 =
# ------------------------------------------------------------------------------

proc complete(
hike: Hike; # Partially expanded path
hike: Hike; # Partially expanded chain of vertices
vid: VertexID; # Start ID
db: AristoDbRef; # Database layer
hikeLenMax: static[int]; # Beware of loops (if any)
Expand Down Expand Up @@ -123,7 +123,7 @@ proc complete(


proc zeroAdjust(
hike: Hike; # Partially expanded path
hike: Hike; # Partially expanded chain of vertices
db: AristoDbRef; # Database layer
doLeast: static[bool]; # Direction: *least* or *most*
): Hike =
Expand Down Expand Up @@ -204,9 +204,9 @@ proc zeroAdjust(


proc finalise(
hike: Hike; # Partially expanded path
hike: Hike; # Partially expanded chain of vertices
db: AristoDbRef; # Database layer
moveRight: static[bool]; # Direction of next node
moveRight: static[bool]; # Direction of next vertex
): Hike =
## Handle some pathological cases after main processing failed
proc beyond(p: Hike; pfx: NibblesSeq): bool =
Expand Down Expand Up @@ -258,10 +258,10 @@ proc finalise(


proc nearbyNext(
hike: Hike; # Partially expanded path
hike: Hike; # Partially expanded chain of vertices
db: AristoDbRef; # Database layer
hikeLenMax: static[int]; # Beware of loops (if any)
moveRight: static[bool]; # Direction of next node
moveRight: static[bool]; # Direction of next vertex
): Hike =
## Unified implementation of `nearbyRight()` and `nearbyLeft()`.
proc accept(nibble: int8): bool =
Expand Down Expand Up @@ -364,11 +364,11 @@ proc nearbyNext(


proc nearbyNext(
baseTag: NodeTag; # Some node
baseTag: NodeTag; # Some `Patricia Trie` path
root: VertexID; # State root
db: AristoDbRef; # Database layer
hikeLenMax: static[int]; # Beware of loops (if any)
moveRight:static[ bool]; # Direction of next node
moveRight:static[ bool]; # Direction of next vertex
): Result[NodeTag,AristoError] =
## Variant of `nearbyNext()`, convenience wrapper
let hike = baseTag.hikeUp(root,db).nearbyNext(db, hikeLenMax, moveRight)
Expand All @@ -388,7 +388,7 @@ proc nearbyNext(
# ------------------------------------------------------------------------------

proc nearbyRight*(
hike: Hike; # Partially expanded path
hike: Hike; # Partially expanded chain of vertices
db: AristoDbRef; # Database layer
): Hike =
## Extends the maximally extended argument nodes `hike` to the right (i.e.
Expand All @@ -403,7 +403,7 @@ proc nearbyRight*(
hike.nearbyNext(db, 64, moveRight=true)

proc nearbyRight*(
nodeTag: NodeTag; # Some node
nodeTag: NodeTag; # Some `Patricia Trie` path
root: VertexID; # State root
db: AristoDbRef; # Database layer
): Result[NodeTag,AristoError] =
Expand All @@ -412,7 +412,7 @@ proc nearbyRight*(
nodeTag.nearbyNext(root, db, 64, moveRight=true)

proc nearbyLeft*(
hike: Hike; # Partially expanded path
hike: Hike; # Partially expanded chain of vertices
db: AristoDbRef; # Database layer
): Hike =
## Similar to `nearbyRight()`.
Expand All @@ -422,7 +422,7 @@ proc nearbyLeft*(
hike.nearbyNext(db, 64, moveRight=false)

proc nearbyLeft*(
nodeTag: NodeTag; # Some node
nodeTag: NodeTag; # Some `Patricia Trie` path
root: VertexID; # State root
db: AristoDbRef; # Database layer
): Result[NodeTag,AristoError] =
Expand All @@ -435,7 +435,7 @@ proc nearbyLeft*(
# ------------------------------------------------------------------------------

proc nearbyRightMissing*(
hike: Hike; # Partially expanded path
hike: Hike; # Partially expanded chain of vertices
db: AristoDbRef; # Database layer
): Result[bool,AristoError] =
## Returns `true` if the maximally extended argument nodes `hike` is the
Expand Down
19 changes: 13 additions & 6 deletions tests/test_aristo.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import
../nimbus/sync/snap/worker/db/[rocky_bulk_load, snapdb_accounts, snapdb_desc],
./replay/[pp, undump_accounts, undump_storages],
./test_sync_snap/[snap_test_xx, test_accounts, test_types],
./test_aristo/[test_helpers, test_merge, test_nearby, test_transcode]
./test_aristo/[
test_delete, test_helpers, test_merge, test_nearby, test_transcode]

const
baseDir = [".", "..", ".."/"..", $DirSep]
Expand Down Expand Up @@ -200,6 +201,9 @@ proc accountsRunner(noisy=true; sample=accSample, resetDb=false) =
test &"Traverse accounts database w/{accLst.len} account lists":
noisy.test_nearbyKvpList(accLst, resetDb)

test &"Delete accounts database, successively {accLst.len} entries":
noisy.test_delete accLst


proc storagesRunner(
noisy = true;
Expand All @@ -223,6 +227,9 @@ proc storagesRunner(
test &"Traverse storage slots database w/{stoLst.len} account lists":
noisy.test_nearbyKvpList(stoLst, resetDb)

test &"Delete storage database, successively {stoLst.len} entries":
noisy.test_delete stoLst

# ------------------------------------------------------------------------------
# Main function(s)
# ------------------------------------------------------------------------------
Expand All @@ -237,7 +244,7 @@ when isMainModule:
noisy = defined(debug) or true

# Borrowed from `test_sync_snap.nim`
when true and false:
when true: # and false:
for n,sam in snapTestList:
noisy.transcodeRunner(sam)
for n,sam in snapTestStorageList:
Expand All @@ -248,18 +255,18 @@ when isMainModule:
import ./test_sync_snap/snap_other_xx
noisy.showElapsed("@snap_other_xx"):
for n,sam in snapOtherList:
noisy.accountsRunner(sam)
noisy.accountsRunner(sam, resetDb=true)

# This one usues dumps from the external `nimbus-eth1-blob` repo
when true: # and false:
when true and false:
import ./test_sync_snap/snap_storage_xx
let knownFailures: KnownHasherFailure = @[
("storages5__34__41_dump#10.20512",(VertexID(1),HashifyRootHashMismatch)),
]
noisy.showElapsed("@snap_storage_xx"):
for n,sam in snapStorageList:
noisy.accountsRunner(sam)
noisy.storagesRunner(sam,oops=knownFailures)
noisy.accountsRunner(sam, resetDb=true)
noisy.storagesRunner(sam, resetDb=true, oops=knownFailures)

when true: # and false:
for n,sam in snapTestList:
Expand Down
Loading

0 comments on commit 11bb33d

Please sign in to comment.