Cache a storage root ID forever in the leaf payload of an account (#2551)

details:
  Stale root IDs are marked disabled while the ID is kept in the leaf
  payload.

why:
  This might lead to further caching advantages.
This commit is contained in:
Jordan Hrycaj 2024-08-07 13:28:01 +00:00 committed by GitHub
parent 488bdbc267
commit 38572bd8ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 61 additions and 51 deletions

View File

@ -16,7 +16,3 @@
function mentioned above.
* `aristo_nearby` also qualifies for a re-write, now
* A storage tree vid should be allowed to become stale (or locally deactivated)
if the vertex vanishes to be re-used when the tree is re-filled. Currently
the vid is removed and then re-allocated.

View File

@ -146,9 +146,9 @@ proc blobifyTo*(pyl: LeafPayload, data: var Blob) =
lens += uint16(tmp.len - 1) shl 3 # 5 bits
data &= tmp.data()
if VertexID(0) < pyl.stoID:
if pyl.stoID.isValid:
mask = mask or 0x04
let tmp = pyl.stoID.blobify()
let tmp = pyl.stoID.vid.blobify()
lens += uint16(tmp.len - 1) shl 8 # 3 bits
data &= tmp.data()
@ -275,7 +275,7 @@ proc deblobify(
if (mask and 0x04) > 0:
let len = (lens shr 8) and 0b111
pAcc.stoID = VertexID(? load64(data, start, int(len + 1)))
pAcc.stoID = (true, VertexID(? load64(data, start, int(len + 1))))
if (mask and 0x08) > 0:
if data.len() < start + 32:

View File

@ -89,8 +89,9 @@ proc checkTopCommon*(
case vtx.vType:
of Leaf:
if vtx.lData.pType == AccountData:
let stoVid = vtx.lData.stoID
if stoVid.isValid:
let stoID = vtx.lData.stoID
if stoID.isValid:
let stoVid = stoID.vid
if stoVid in stoRoots:
return err((stoVid,CheckAnyVidSharedStorageRoot))
if vTop < stoVid:

View File

@ -76,7 +76,7 @@ proc computeKeyImpl(
stoID = vtx.lData.stoID
skey =
if stoID.isValid:
let (skey, sl) = ?db.computeKeyImpl((stoID, stoID))
let (skey, sl) = ?db.computeKeyImpl((stoID.vid, stoID.vid))
level = maxLevel(level, sl)
skey
else:

View File

@ -100,6 +100,12 @@ proc ppVid(vid: VertexID; pfx = true): string =
else:
result &= "ø"
proc ppVid(sid: StorageID; pfx = true): string =
if sid.isValid or not sid.vid.isValid:
sid.vid.ppVid(pfx)
else:
(if pfx: "$" else: "") & "®" & sid.vid.ppVid(false)
proc ppVid(rvid: RootedVertexID; pfx = true): string =
if pfx:
result = "$"
@ -234,7 +240,7 @@ proc ppNode(
if nd.lData.pType == AccountData:
result &= "(" & nd.lData.account.ppAriAccount() & ","
if nd.lData.stoID.isValid:
let tag = db.ppKeyOk(nd.key[0],(rvid.root,nd.lData.stoID))
let tag = db.ppKeyOk(nd.key[0],(rvid.root,nd.lData.stoID.vid))
result &= nd.lData.stoID.ppVid & tag
else:
result &= nd.lData.stoID.ppVid

View File

@ -200,7 +200,7 @@ proc deleteAccountRecord*(
# Delete storage tree if present
if stoID.isValid:
? db.delStoTreeImpl((stoID, stoID), accPath, NibblesBuf())
? db.delStoTreeImpl((stoID.vid, stoID.vid), accPath, NibblesBuf())
?db.deleteImpl(hike)
@ -279,7 +279,7 @@ proc deleteStorageData*(
if not stoID.isValid:
return err(DelStoRootMissing)
let stoHike = stoPath.hikeUp(stoID, db).valueOr:
let stoHike = stoPath.hikeUp(stoID.vid, db).valueOr:
if error[1] in HikeAcceptableStopsNotFound:
return err(DelPathNotFound)
return err(error[1])
@ -292,12 +292,12 @@ proc deleteStorageData*(
db.layersPutStoLeaf(AccountKey.mixUp(accPath, stoPath), nil)
# Make sure that an account leaf has no dangling sub-trie
if db.getVtx((stoID, stoID)).isValid:
if db.getVtx((stoID.vid, stoID.vid)).isValid:
return ok(false)
# De-register the deleted storage tree from the account record
let leaf = wpAcc.vtx.dup # Dup on modify
leaf.lData.stoID = VertexID(0)
leaf.lData.stoID.isValid = false
db.layersPutAccLeaf(accPath, leaf)
db.layersPutVtx((accHike.root, wpAcc.vid), leaf)
ok(true)
@ -323,11 +323,11 @@ proc deleteStorageTree*(
# Mark account path Merkle keys for update
db.updateAccountForHasher accHike
? db.delStoTreeImpl((stoID, stoID), accPath, NibblesBuf())
? db.delStoTreeImpl((stoID.vid, stoID.vid), accPath, NibblesBuf())
# De-register the deleted storage tree from the accounts record
let leaf = wpAcc.vtx.dup # Dup on modify
leaf.lData.stoID = VertexID(0)
leaf.lData.stoID.isValid = false
db.layersPutAccLeaf(accPath, leaf)
db.layersPutVtx((accHike.root, wpAcc.vid), leaf)
ok()

View File

@ -47,6 +47,14 @@ type
AccountData ## `Aristo account` with vertex IDs links
StoData ## Slot storage data
StorageID* = tuple
## Once a storage tree is allocated, its root vertex ID is registered in
## the leaf payload of an acoount. After subsequent storage tree deletion
## the root vertex ID will be kept in the leaf payload for re-use but set
## disabled (`.isValid` = `false`).
isValid: bool ## See also `isValid()` for `VertexID`
vid: VertexID ## Storage root vertex ID
LeafPayload* = object
## The payload type depends on the sub-tree used. The `VertexID(1)` rooted
## sub-tree only has `AccountData` type payload, stoID-based have StoData
@ -56,7 +64,7 @@ type
rawBlob*: Blob ## Opaque data, default value
of AccountData:
account*: AristoAccount
stoID*: VertexID ## Storage vertex ID (if any)
stoID*: StorageID ## Storage vertex ID (if any)
of StoData:
stoData*: UInt256

View File

@ -163,7 +163,7 @@ proc fetchStorageID*(
if not stoID.isValid:
return err(FetchPathNotFound)
ok stoID
ok stoID.vid
proc retrieveStoragePayload(
db: AristoDbRef;

View File

@ -127,11 +127,14 @@ proc mergeStorageData*(
stoID = vtx.lData.stoID
# Provide new storage ID when needed
useID = if stoID.isValid: stoID else: db.vidFetch()
useID =
if stoID.isValid: stoID # Use as is
elif stoID.vid.isValid: (true, stoID.vid) # Re-use previous vid
else: (true, db.vidFetch()) # Create new vid
# Call merge
pyl = LeafPayload(pType: StoData, stoData: stoData)
rc = db.mergePayloadImpl(useID, stoPath.data, pyl)
rc = db.mergePayloadImpl(useID.vid, stoPath.data, pyl)
if rc.isOk:
# Mark account path Merkle keys for update

View File

@ -240,7 +240,7 @@ proc partPut*(
of Leaf:
let lKey = node.key[0]
if node.lData.pType == AccountData and lKey.isValid:
node.lData.stoID = (? ps.getRvid(root, lKey))[0].vid
node.lData.stoID = (true, (? ps.getRvid(root, lKey))[0].vid)
of Branch:
for n in 0 .. 15:
let bKey = node.key[n]

View File

@ -37,15 +37,13 @@ proc serialise(
of RawData:
ok pyl.rawBlob
of AccountData:
let
vid = pyl.stoID
key = block:
if vid.isValid:
vid.getKey.valueOr:
let w = (vid,error)
return err(w)
else:
VOID_HASH_KEY
let key = block:
if pyl.stoID.isValid:
pyl.stoID.vid.getKey.valueOr:
let w = (pyl.stoID.vid, error)
return err(w)
else:
VOID_HASH_KEY
ok rlp.encode Account(
nonce: pyl.account.nonce,

View File

@ -59,11 +59,11 @@ proc toNode*(
let node = NodeRef(vType: Leaf, lPfx: vtx.lPfx, lData: vtx.lData)
# Need to resolve storage root for account leaf
if vtx.lData.pType == AccountData:
let vid = vtx.lData.stoID
if vid.isValid:
let key = db.getKey (vid, vid)
let stoID = vtx.lData.stoID
if stoID.isValid:
let key = db.getKey (stoID.vid, stoID.vid)
if not key.isValid:
return err(@[vid])
return err(@[stoID.vid])
node.key[0] = key
return ok node
@ -90,9 +90,9 @@ iterator subVids*(vtx: VertexRef): VertexID =
case vtx.vType:
of Leaf:
if vtx.lData.pType == AccountData:
let vid = vtx.lData.stoID
if vid.isValid:
yield vid
let stoID = vtx.lData.stoID
if stoID.isValid:
yield stoID.vid
of Branch:
for vid in vtx.bVid:
if vid.isValid:
@ -103,9 +103,9 @@ iterator subVidKeys*(node: NodeRef): (VertexID,HashKey) =
case node.vType:
of Leaf:
if node.lData.pType == AccountData:
let vid = node.lData.stoID
if node.isValid:
yield (vid,node.key[0])
let stoID = node.lData.stoID
if stoID.isValid:
yield (stoID.vid, node.key[0])
of Branch:
for n in 0 .. 15:
let vid = node.bVid[n]

View File

@ -90,16 +90,14 @@ proc payloadAsBlob(pyl: LeafPayload; ps: PartStateRef): Blob =
of RawData:
pyl.rawBlob
of AccountData:
let
vid = pyl.stoID
key = block:
if vid.isValid:
let rc = ps.db.getKeyRc (VertexID(1),vid)
if rc.isErr:
raiseAssert info & ": getKey => " & $rc.error
rc.value[0]
else:
VOID_HASH_KEY
let key = block:
if pyl.stoID.isValid:
let rc = ps.db.getKeyRc (VertexID(1),pyl.stoID.vid)
if rc.isErr:
raiseAssert info & ": getKey => " & $rc.error
rc.value[0]
else:
VOID_HASH_KEY
rlp.encode Account(
nonce: pyl.account.nonce,