mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 05:14:14 +00:00
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:
parent
488bdbc267
commit
38572bd8ea
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -163,7 +163,7 @@ proc fetchStorageID*(
|
||||
if not stoID.isValid:
|
||||
return err(FetchPathNotFound)
|
||||
|
||||
ok stoID
|
||||
ok stoID.vid
|
||||
|
||||
proc retrieveStoragePayload(
|
||||
db: AristoDbRef;
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user