diff --git a/nimbus/db/aristo/TODO.md b/nimbus/db/aristo/TODO.md index fab7e70b0..a35630bf9 100644 --- a/nimbus/db/aristo/TODO.md +++ b/nimbus/db/aristo/TODO.md @@ -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. diff --git a/nimbus/db/aristo/aristo_blobify.nim b/nimbus/db/aristo/aristo_blobify.nim index 8e0fef392..493a11497 100644 --- a/nimbus/db/aristo/aristo_blobify.nim +++ b/nimbus/db/aristo/aristo_blobify.nim @@ -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: diff --git a/nimbus/db/aristo/aristo_check/check_top.nim b/nimbus/db/aristo/aristo_check/check_top.nim index e9058bef1..27b9d79bc 100644 --- a/nimbus/db/aristo/aristo_check/check_top.nim +++ b/nimbus/db/aristo/aristo_check/check_top.nim @@ -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: diff --git a/nimbus/db/aristo/aristo_compute.nim b/nimbus/db/aristo/aristo_compute.nim index dbbf408b2..e3c26d3f6 100644 --- a/nimbus/db/aristo/aristo_compute.nim +++ b/nimbus/db/aristo/aristo_compute.nim @@ -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: diff --git a/nimbus/db/aristo/aristo_debug.nim b/nimbus/db/aristo/aristo_debug.nim index bb0d0b5fe..2f0bb4a6e 100644 --- a/nimbus/db/aristo/aristo_debug.nim +++ b/nimbus/db/aristo/aristo_debug.nim @@ -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 diff --git a/nimbus/db/aristo/aristo_delete.nim b/nimbus/db/aristo/aristo_delete.nim index 2459de7e9..df04aa865 100644 --- a/nimbus/db/aristo/aristo_delete.nim +++ b/nimbus/db/aristo/aristo_delete.nim @@ -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() diff --git a/nimbus/db/aristo/aristo_desc/desc_structural.nim b/nimbus/db/aristo/aristo_desc/desc_structural.nim index 49648ad89..b1e277ac5 100644 --- a/nimbus/db/aristo/aristo_desc/desc_structural.nim +++ b/nimbus/db/aristo/aristo_desc/desc_structural.nim @@ -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 diff --git a/nimbus/db/aristo/aristo_fetch.nim b/nimbus/db/aristo/aristo_fetch.nim index 4fc8403eb..240154697 100644 --- a/nimbus/db/aristo/aristo_fetch.nim +++ b/nimbus/db/aristo/aristo_fetch.nim @@ -163,7 +163,7 @@ proc fetchStorageID*( if not stoID.isValid: return err(FetchPathNotFound) - ok stoID + ok stoID.vid proc retrieveStoragePayload( db: AristoDbRef; diff --git a/nimbus/db/aristo/aristo_merge.nim b/nimbus/db/aristo/aristo_merge.nim index 5da23e9c3..05d8d0abb 100644 --- a/nimbus/db/aristo/aristo_merge.nim +++ b/nimbus/db/aristo/aristo_merge.nim @@ -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 diff --git a/nimbus/db/aristo/aristo_part.nim b/nimbus/db/aristo/aristo_part.nim index 771194170..b10130de2 100644 --- a/nimbus/db/aristo/aristo_part.nim +++ b/nimbus/db/aristo/aristo_part.nim @@ -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] diff --git a/nimbus/db/aristo/aristo_serialise.nim b/nimbus/db/aristo/aristo_serialise.nim index 90fa2cba8..77b1b9a9c 100644 --- a/nimbus/db/aristo/aristo_serialise.nim +++ b/nimbus/db/aristo/aristo_serialise.nim @@ -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, diff --git a/nimbus/db/aristo/aristo_utils.nim b/nimbus/db/aristo/aristo_utils.nim index 1dc7b5162..6492280d9 100644 --- a/nimbus/db/aristo/aristo_utils.nim +++ b/nimbus/db/aristo/aristo_utils.nim @@ -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] diff --git a/tests/test_aristo/test_portal_proof.nim b/tests/test_aristo/test_portal_proof.nim index 72f362b43..4d6b5db70 100644 --- a/tests/test_aristo/test_portal_proof.nim +++ b/tests/test_aristo/test_portal_proof.nim @@ -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,