simplify VertexRef (#2626)
* move pfx out of variant which avoids pointless field type panic checks and copies on access * make `VertexRef` a non-inheritable object which reduces its memory footprint and simplifies its use - it's also unclear from a semantic point of view why inheritance makes sense for storing keys
This commit is contained in:
parent
0be6291fba
commit
adb8d64377
|
@ -200,8 +200,8 @@ proc blobifyTo*(vtx: VertexRef; data: var Blob): Result[void,AristoError] =
|
||||||
|
|
||||||
let
|
let
|
||||||
pSegm =
|
pSegm =
|
||||||
if vtx.ePfx.len > 0:
|
if vtx.pfx.len > 0:
|
||||||
vtx.ePfx.toHexPrefix(isleaf = false)
|
vtx.pfx.toHexPrefix(isleaf = false)
|
||||||
else:
|
else:
|
||||||
default(HexPrefixBuf)
|
default(HexPrefixBuf)
|
||||||
psLen = pSegm.len.byte
|
psLen = pSegm.len.byte
|
||||||
|
@ -214,7 +214,7 @@ proc blobifyTo*(vtx: VertexRef; data: var Blob): Result[void,AristoError] =
|
||||||
|
|
||||||
of Leaf:
|
of Leaf:
|
||||||
let
|
let
|
||||||
pSegm = vtx.lPfx.toHexPrefix(isleaf = true)
|
pSegm = vtx.pfx.toHexPrefix(isleaf = true)
|
||||||
psLen = pSegm.len.byte
|
psLen = pSegm.len.byte
|
||||||
if psLen == 0 or 33 < psLen:
|
if psLen == 0 or 33 < psLen:
|
||||||
return err(BlobifyLeafPathOverflow)
|
return err(BlobifyLeafPathOverflow)
|
||||||
|
@ -325,7 +325,7 @@ proc deblobify*(
|
||||||
# End `while`
|
# End `while`
|
||||||
VertexRef(
|
VertexRef(
|
||||||
vType: Branch,
|
vType: Branch,
|
||||||
ePfx: pathSegment,
|
pfx: pathSegment,
|
||||||
bVid: vtxList)
|
bVid: vtxList)
|
||||||
|
|
||||||
of 3: # `Leaf` vertex
|
of 3: # `Leaf` vertex
|
||||||
|
@ -341,7 +341,7 @@ proc deblobify*(
|
||||||
return err(DeblobLeafGotExtPrefix)
|
return err(DeblobLeafGotExtPrefix)
|
||||||
let vtx = VertexRef(
|
let vtx = VertexRef(
|
||||||
vType: Leaf,
|
vType: Leaf,
|
||||||
lPfx: pathSegment)
|
pfx: pathSegment)
|
||||||
|
|
||||||
? record.toOpenArray(0, pLen - 1).deblobify(vtx.lData)
|
? record.toOpenArray(0, pLen - 1).deblobify(vtx.lData)
|
||||||
vtx
|
vtx
|
||||||
|
|
|
@ -68,7 +68,7 @@ proc computeKeyImpl(
|
||||||
case vtx.vType:
|
case vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
writer.startList(2)
|
writer.startList(2)
|
||||||
writer.append(vtx.lPfx.toHexPrefix(isLeaf = true).data())
|
writer.append(vtx.pfx.toHexPrefix(isLeaf = true).data())
|
||||||
|
|
||||||
case vtx.lData.pType
|
case vtx.lData.pType
|
||||||
of AccountData:
|
of AccountData:
|
||||||
|
@ -106,12 +106,12 @@ proc computeKeyImpl(
|
||||||
else:
|
else:
|
||||||
w.append(VOID_HASH_KEY)
|
w.append(VOID_HASH_KEY)
|
||||||
w.append EmptyBlob
|
w.append EmptyBlob
|
||||||
if vtx.ePfx.len > 0: # Extension node
|
if vtx.pfx.len > 0: # Extension node
|
||||||
var bwriter = initRlpWriter()
|
var bwriter = initRlpWriter()
|
||||||
writeBranch(bwriter)
|
writeBranch(bwriter)
|
||||||
|
|
||||||
writer.startList(2)
|
writer.startList(2)
|
||||||
writer.append(vtx.ePfx.toHexPrefix(isleaf = false).data())
|
writer.append(vtx.pfx.toHexPrefix(isleaf = false).data())
|
||||||
writer.append(bwriter.finish().digestTo(HashKey))
|
writer.append(bwriter.finish().digestTo(HashKey))
|
||||||
else:
|
else:
|
||||||
writeBranch(writer)
|
writeBranch(writer)
|
||||||
|
|
|
@ -209,9 +209,9 @@ proc ppVtx(nd: VertexRef, db: AristoDbRef, rvid: RootedVertexID): string =
|
||||||
result = ["ł(", "þ("][nd.vType.ord]
|
result = ["ł(", "þ("][nd.vType.ord]
|
||||||
case nd.vType:
|
case nd.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
result &= nd.lPfx.ppPathPfx & "," & nd.lData.ppPayload(db)
|
result &= nd.pfx.ppPathPfx & "," & nd.lData.ppPayload(db)
|
||||||
of Branch:
|
of Branch:
|
||||||
result &= nd.ePfx.ppPathPfx & ":"
|
result &= nd.pfx.ppPathPfx & ":"
|
||||||
for n in 0..15:
|
for n in 0..15:
|
||||||
if nd.bVid[n].isValid:
|
if nd.bVid[n].isValid:
|
||||||
result &= nd.bVid[n].ppVid
|
result &= nd.bVid[n].ppVid
|
||||||
|
@ -229,33 +229,33 @@ proc ppNode(
|
||||||
result = "ø"
|
result = "ø"
|
||||||
else:
|
else:
|
||||||
if not rvid.isValid:
|
if not rvid.isValid:
|
||||||
result = ["L(", "B("][nd.vType.ord]
|
result = ["L(", "B("][nd.vtx.vType.ord]
|
||||||
elif db.layersGetKey(rvid).isOk:
|
elif db.layersGetKey(rvid).isOk:
|
||||||
result = ["l(", "b("][nd.vType.ord]
|
result = ["l(", "b("][nd.vtx.vType.ord]
|
||||||
else:
|
else:
|
||||||
result = ["ł(", "þ("][nd.vType.ord]
|
result = ["ł(", "þ("][nd.vtx.vType.ord]
|
||||||
case nd.vType:
|
case nd.vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
result &= nd.lPfx.ppPathPfx & ","
|
result &= nd.vtx.pfx.ppPathPfx & ","
|
||||||
if nd.lData.pType == AccountData:
|
if nd.vtx.lData.pType == AccountData:
|
||||||
result &= "(" & nd.lData.account.ppAriAccount() & ","
|
result &= "(" & nd.vtx.lData.account.ppAriAccount() & ","
|
||||||
if nd.lData.stoID.isValid:
|
if nd.vtx.lData.stoID.isValid:
|
||||||
let tag = db.ppKeyOk(nd.key[0],(rvid.root,nd.lData.stoID.vid))
|
let tag = db.ppKeyOk(nd.key[0],(rvid.root,nd.vtx.lData.stoID.vid))
|
||||||
result &= nd.lData.stoID.ppVid & tag
|
result &= nd.vtx.lData.stoID.ppVid & tag
|
||||||
else:
|
else:
|
||||||
result &= nd.lData.stoID.ppVid
|
result &= nd.vtx.lData.stoID.ppVid
|
||||||
if nd.key[0].isValid:
|
if nd.key[0].isValid:
|
||||||
result &= nd.key[0].ppKey(db)
|
result &= nd.key[0].ppKey(db)
|
||||||
result &= ")"
|
result &= ")"
|
||||||
else:
|
else:
|
||||||
result &= nd.lData.ppPayload(db)
|
result &= nd.vtx.lData.ppPayload(db)
|
||||||
of Branch:
|
of Branch:
|
||||||
let keyOnly = nd.bVid.toSeq.filterIt(it.isValid).len == 0
|
let keyOnly = nd.vtx.bVid.toSeq.filterIt(it.isValid).len == 0
|
||||||
result &= nd.ePfx.ppPathPfx & ":"
|
result &= nd.vtx.pfx.ppPathPfx & ":"
|
||||||
for n in 0..15:
|
for n in 0..15:
|
||||||
if nd.bVid[n].isValid:
|
if nd.vtx.bVid[n].isValid:
|
||||||
let tag = db.ppKeyOk(nd.key[n],(rvid.root,nd.bVid[n]))
|
let tag = db.ppKeyOk(nd.key[n],(rvid.root,nd.vtx.bVid[n]))
|
||||||
result &= nd.bVid[n].ppVid & tag
|
result &= nd.vtx.bVid[n].ppVid & tag
|
||||||
elif keyOnly and nd.key[n].isValid:
|
elif keyOnly and nd.key[n].isValid:
|
||||||
result &= nd.key[n].ppKey(db)
|
result &= nd.key[n].ppKey(db)
|
||||||
if n < 15:
|
if n < 15:
|
||||||
|
|
|
@ -97,12 +97,12 @@ proc deleteImpl(
|
||||||
of Leaf:
|
of Leaf:
|
||||||
VertexRef(
|
VertexRef(
|
||||||
vType: Leaf,
|
vType: Leaf,
|
||||||
lPfx: br.vtx.ePfx & NibblesBuf.nibble(nbl.byte) & nxt.lPfx,
|
pfx: br.vtx.pfx & NibblesBuf.nibble(nbl.byte) & nxt.pfx,
|
||||||
lData: nxt.lData)
|
lData: nxt.lData)
|
||||||
of Branch:
|
of Branch:
|
||||||
VertexRef(
|
VertexRef(
|
||||||
vType: Branch,
|
vType: Branch,
|
||||||
ePfx: br.vtx.ePfx & NibblesBuf.nibble(nbl.byte) & nxt.ePfx,
|
pfx: br.vtx.pfx & NibblesBuf.nibble(nbl.byte) & nxt.pfx,
|
||||||
bVid: nxt.bVid)
|
bVid: nxt.bVid)
|
||||||
|
|
||||||
# Put the new vertex at the id of the obsolete branch
|
# Put the new vertex at the id of the obsolete branch
|
||||||
|
|
|
@ -58,10 +58,10 @@ proc delStoTreeNow(
|
||||||
if vtx.bVid[i].isValid:
|
if vtx.bVid[i].isValid:
|
||||||
? db.delStoTreeNow(
|
? db.delStoTreeNow(
|
||||||
(rvid.root, vtx.bVid[i]), accPath,
|
(rvid.root, vtx.bVid[i]), accPath,
|
||||||
stoPath & vtx.ePfx & NibblesBuf.nibble(byte i))
|
stoPath & vtx.pfx & NibblesBuf.nibble(byte i))
|
||||||
|
|
||||||
of Leaf:
|
of Leaf:
|
||||||
let stoPath = Hash256(data: (stoPath & vtx.lPfx).getBytes())
|
let stoPath = Hash256(data: (stoPath & vtx.pfx).getBytes())
|
||||||
db.layersPutStoLeaf(mixUp(accPath, stoPath), nil)
|
db.layersPutStoLeaf(mixUp(accPath, stoPath), nil)
|
||||||
|
|
||||||
db.disposeOfVtx(rvid)
|
db.disposeOfVtx(rvid)
|
||||||
|
|
|
@ -68,20 +68,21 @@ type
|
||||||
of StoData:
|
of StoData:
|
||||||
stoData*: UInt256
|
stoData*: UInt256
|
||||||
|
|
||||||
VertexRef* = ref object of RootRef
|
VertexRef* = ref object
|
||||||
## Vertex for building a hexary Patricia or Merkle Patricia Trie
|
## Vertex for building a hexary Patricia or Merkle Patricia Trie
|
||||||
|
pfx*: NibblesBuf
|
||||||
|
## Portion of path segment - extension nodes are branch nodes with
|
||||||
|
## non-empty prefix
|
||||||
case vType*: VertexType
|
case vType*: VertexType
|
||||||
of Leaf:
|
of Leaf:
|
||||||
lPfx*: NibblesBuf ## Portion of path segment
|
|
||||||
lData*: LeafPayload ## Reference to data payload
|
lData*: LeafPayload ## Reference to data payload
|
||||||
of Branch:
|
of Branch:
|
||||||
ePfx*: NibblesBuf ## Portion of path segment - if non-empty,
|
|
||||||
## it's an extension node!
|
|
||||||
bVid*: array[16,VertexID] ## Edge list with vertex IDs
|
bVid*: array[16,VertexID] ## Edge list with vertex IDs
|
||||||
|
|
||||||
NodeRef* = ref object of VertexRef
|
NodeRef* = ref object of RootRef
|
||||||
## Combined record for a *traditional* ``Merkle Patricia Tree` node merged
|
## Combined record for a *traditional* ``Merkle Patricia Tree` node merged
|
||||||
## with a structural `VertexRef` type object.
|
## with a structural `VertexRef` type object.
|
||||||
|
vtx*: VertexRef
|
||||||
key*: array[16,HashKey] ## Merkle hash/es for vertices
|
key*: array[16,HashKey] ## Merkle hash/es for vertices
|
||||||
|
|
||||||
# ----------------------
|
# ----------------------
|
||||||
|
@ -174,21 +175,21 @@ proc `==`*(a, b: VertexRef): bool =
|
||||||
return false
|
return false
|
||||||
case a.vType:
|
case a.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
if a.lPfx != b.lPfx or a.lData != b.lData:
|
if a.pfx != b.pfx or a.lData != b.lData:
|
||||||
return false
|
return false
|
||||||
of Branch:
|
of Branch:
|
||||||
if a.ePfx != b.ePfx or a.bVid != b.bVid:
|
if a.pfx != b.pfx or a.bVid != b.bVid:
|
||||||
return false
|
return false
|
||||||
true
|
true
|
||||||
|
|
||||||
proc `==`*(a, b: NodeRef): bool =
|
proc `==`*(a, b: NodeRef): bool =
|
||||||
## Beware, potential deep comparison
|
## Beware, potential deep comparison
|
||||||
if a.VertexRef != b.VertexRef:
|
if a.vtx != b.vtx:
|
||||||
return false
|
return false
|
||||||
case a.vType:
|
case a.vtx.vType:
|
||||||
of Branch:
|
of Branch:
|
||||||
for n in 0..15:
|
for n in 0..15:
|
||||||
if a.bVid[n] != 0.VertexID or b.bVid[n] != 0.VertexID:
|
if a.vtx.bVid[n] != 0.VertexID or b.vtx.bVid[n] != 0.VertexID:
|
||||||
if a.key[n] != b.key[n]:
|
if a.key[n] != b.key[n]:
|
||||||
return false
|
return false
|
||||||
else:
|
else:
|
||||||
|
@ -227,12 +228,12 @@ func dup*(vtx: VertexRef): VertexRef =
|
||||||
of Leaf:
|
of Leaf:
|
||||||
VertexRef(
|
VertexRef(
|
||||||
vType: Leaf,
|
vType: Leaf,
|
||||||
lPfx: vtx.lPfx,
|
pfx: vtx.pfx,
|
||||||
lData: vtx.lData.dup)
|
lData: vtx.lData.dup)
|
||||||
of Branch:
|
of Branch:
|
||||||
VertexRef(
|
VertexRef(
|
||||||
vType: Branch,
|
vType: Branch,
|
||||||
ePfx: vtx.ePfx,
|
pfx: vtx.pfx,
|
||||||
bVid: vtx.bVid)
|
bVid: vtx.bVid)
|
||||||
|
|
||||||
func dup*(node: NodeRef): NodeRef =
|
func dup*(node: NodeRef): NodeRef =
|
||||||
|
@ -241,19 +242,9 @@ func dup*(node: NodeRef): NodeRef =
|
||||||
if node.isNil:
|
if node.isNil:
|
||||||
NodeRef(nil)
|
NodeRef(nil)
|
||||||
else:
|
else:
|
||||||
case node.vType:
|
NodeRef(
|
||||||
of Leaf:
|
vtx: node.vtx.dup(),
|
||||||
NodeRef(
|
key: node.key)
|
||||||
vType: Leaf,
|
|
||||||
lPfx: node.lPfx,
|
|
||||||
lData: node.lData.dup,
|
|
||||||
key: node.key)
|
|
||||||
of Branch:
|
|
||||||
NodeRef(
|
|
||||||
vType: Branch,
|
|
||||||
ePfx: node.ePfx,
|
|
||||||
bVid: node.bVid,
|
|
||||||
key: node.key)
|
|
||||||
|
|
||||||
func dup*(wp: VidVtxPair): VidVtxPair =
|
func dup*(wp: VidVtxPair): VidVtxPair =
|
||||||
## Safe copy of `wp` argument
|
## Safe copy of `wp` argument
|
||||||
|
|
|
@ -47,9 +47,9 @@ func getNibblesImpl(hike: Hike; start = 0; maxLen = high(int)): NibblesBuf =
|
||||||
let leg = hike.legs[n]
|
let leg = hike.legs[n]
|
||||||
case leg.wp.vtx.vType:
|
case leg.wp.vtx.vType:
|
||||||
of Branch:
|
of Branch:
|
||||||
result = result & leg.wp.vtx.ePfx & NibblesBuf.nibble(leg.nibble.byte)
|
result = result & leg.wp.vtx.pfx & NibblesBuf.nibble(leg.nibble.byte)
|
||||||
of Leaf:
|
of Leaf:
|
||||||
result = result & leg.wp.vtx.lPfx
|
result = result & leg.wp.vtx.pfx
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public functions
|
# Public functions
|
||||||
|
@ -89,24 +89,24 @@ proc step*(
|
||||||
case vtx.vType:
|
case vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
# This must be the last vertex, so there cannot be any `tail` left.
|
# This must be the last vertex, so there cannot be any `tail` left.
|
||||||
if path.len != path.sharedPrefixLen(vtx.lPfx):
|
if path.len != path.sharedPrefixLen(vtx.pfx):
|
||||||
return err(HikeLeafUnexpected)
|
return err(HikeLeafUnexpected)
|
||||||
|
|
||||||
ok (vtx, NibblesBuf(), VertexID(0))
|
ok (vtx, NibblesBuf(), VertexID(0))
|
||||||
|
|
||||||
of Branch:
|
of Branch:
|
||||||
# There must be some more data (aka `tail`) after a `Branch` vertex.
|
# There must be some more data (aka `tail`) after a `Branch` vertex.
|
||||||
if path.len <= vtx.ePfx.len:
|
if path.len <= vtx.pfx.len:
|
||||||
return err(HikeBranchTailEmpty)
|
return err(HikeBranchTailEmpty)
|
||||||
|
|
||||||
let
|
let
|
||||||
nibble = path[vtx.ePfx.len].int8
|
nibble = path[vtx.pfx.len].int8
|
||||||
nextVid = vtx.bVid[nibble]
|
nextVid = vtx.bVid[nibble]
|
||||||
|
|
||||||
if not nextVid.isValid:
|
if not nextVid.isValid:
|
||||||
return err(HikeBranchMissingEdge)
|
return err(HikeBranchMissingEdge)
|
||||||
|
|
||||||
ok (vtx, path.slice(vtx.ePfx.len + 1), nextVid)
|
ok (vtx, path.slice(vtx.pfx.len + 1), nextVid)
|
||||||
|
|
||||||
|
|
||||||
iterator stepUp*(
|
iterator stepUp*(
|
||||||
|
@ -162,7 +162,7 @@ proc hikeUp*(
|
||||||
break
|
break
|
||||||
|
|
||||||
of Branch:
|
of Branch:
|
||||||
hike.legs.add Leg(wp: wp, nibble: int8 hike.tail[vtx.ePfx.len])
|
hike.legs.add Leg(wp: wp, nibble: int8 hike.tail[vtx.pfx.len])
|
||||||
|
|
||||||
hike.tail = path
|
hike.tail = path
|
||||||
vid = next
|
vid = next
|
||||||
|
|
|
@ -16,17 +16,12 @@ import eth/common, results, ".."/[aristo_desc, aristo_get, aristo_layers, aristo
|
||||||
# Private getters & setters
|
# Private getters & setters
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc xPfx(vtx: VertexRef): NibblesBuf =
|
|
||||||
case vtx.vType
|
|
||||||
of Leaf: vtx.lPfx
|
|
||||||
of Branch: vtx.ePfx
|
|
||||||
|
|
||||||
# -----------
|
# -----------
|
||||||
|
|
||||||
proc layersPutLeaf(
|
proc layersPutLeaf(
|
||||||
db: AristoDbRef, rvid: RootedVertexID, path: NibblesBuf, payload: LeafPayload
|
db: AristoDbRef, rvid: RootedVertexID, path: NibblesBuf, payload: LeafPayload
|
||||||
): VertexRef =
|
): VertexRef =
|
||||||
let vtx = VertexRef(vType: Leaf, lPfx: path, lData: payload)
|
let vtx = VertexRef(vType: Leaf, pfx: path, lData: payload)
|
||||||
db.layersPutVtx(rvid, vtx)
|
db.layersPutVtx(rvid, vtx)
|
||||||
vtx
|
vtx
|
||||||
|
|
||||||
|
@ -68,11 +63,11 @@ proc mergePayloadImpl*(
|
||||||
touched[pos] = cur
|
touched[pos] = cur
|
||||||
pos += 1
|
pos += 1
|
||||||
|
|
||||||
let n = path.sharedPrefixLen(vtx.xPfx)
|
let n = path.sharedPrefixLen(vtx.pfx)
|
||||||
case vtx.vType
|
case vtx.vType
|
||||||
of Leaf:
|
of Leaf:
|
||||||
let leafVtx =
|
let leafVtx =
|
||||||
if n == vtx.lPfx.len:
|
if n == vtx.pfx.len:
|
||||||
# Same path - replace the current vertex with a new payload
|
# Same path - replace the current vertex with a new payload
|
||||||
|
|
||||||
if vtx.lData == payload:
|
if vtx.lData == payload:
|
||||||
|
@ -92,11 +87,11 @@ proc mergePayloadImpl*(
|
||||||
else:
|
else:
|
||||||
# Turn leaf into a branch (or extension) then insert the two leaves
|
# Turn leaf into a branch (or extension) then insert the two leaves
|
||||||
# into the branch
|
# into the branch
|
||||||
let branch = VertexRef(vType: Branch, ePfx: path.slice(0, n))
|
let branch = VertexRef(vType: Branch, pfx: path.slice(0, n))
|
||||||
block: # Copy of existing leaf node, now one level deeper
|
block: # Copy of existing leaf node, now one level deeper
|
||||||
let local = db.vidFetch()
|
let local = db.vidFetch()
|
||||||
branch.bVid[vtx.lPfx[n]] = local
|
branch.bVid[vtx.pfx[n]] = local
|
||||||
discard db.layersPutLeaf((root, local), vtx.lPfx.slice(n + 1), vtx.lData)
|
discard db.layersPutLeaf((root, local), vtx.pfx.slice(n + 1), vtx.lData)
|
||||||
|
|
||||||
let leafVtx = block: # Newly inserted leaf node
|
let leafVtx = block: # Newly inserted leaf node
|
||||||
let local = db.vidFetch()
|
let local = db.vidFetch()
|
||||||
|
@ -111,10 +106,10 @@ proc mergePayloadImpl*(
|
||||||
resetKeys()
|
resetKeys()
|
||||||
return ok(leafVtx)
|
return ok(leafVtx)
|
||||||
of Branch:
|
of Branch:
|
||||||
if vtx.ePfx.len == n:
|
if vtx.pfx.len == n:
|
||||||
# The existing branch is a prefix of the new entry
|
# The existing branch is a prefix of the new entry
|
||||||
let
|
let
|
||||||
nibble = path[vtx.ePfx.len]
|
nibble = path[vtx.pfx.len]
|
||||||
next = vtx.bVid[nibble]
|
next = vtx.bVid[nibble]
|
||||||
|
|
||||||
if next.isValid:
|
if next.isValid:
|
||||||
|
@ -137,14 +132,14 @@ proc mergePayloadImpl*(
|
||||||
else:
|
else:
|
||||||
# Partial path match - we need to split the existing branch at
|
# Partial path match - we need to split the existing branch at
|
||||||
# the point of divergence, inserting a new branch
|
# the point of divergence, inserting a new branch
|
||||||
let branch = VertexRef(vType: Branch, ePfx: path.slice(0, n))
|
let branch = VertexRef(vType: Branch, pfx: path.slice(0, n))
|
||||||
block: # Copy the existing vertex and add it to the new branch
|
block: # Copy the existing vertex and add it to the new branch
|
||||||
let local = db.vidFetch()
|
let local = db.vidFetch()
|
||||||
branch.bVid[vtx.ePfx[n]] = local
|
branch.bVid[vtx.pfx[n]] = local
|
||||||
|
|
||||||
db.layersPutVtx(
|
db.layersPutVtx(
|
||||||
(root, local),
|
(root, local),
|
||||||
VertexRef(vType: Branch, ePfx: vtx.ePfx.slice(n + 1), bVid: vtx.bVid),
|
VertexRef(vType: Branch, pfx: vtx.pfx.slice(n + 1), bVid: vtx.bVid),
|
||||||
)
|
)
|
||||||
|
|
||||||
let leafVtx = block: # add the new entry
|
let leafVtx = block: # add the new entry
|
||||||
|
|
|
@ -170,10 +170,10 @@ proc zeroAdjust(
|
||||||
if n < 0:
|
if n < 0:
|
||||||
# Before or after the database range
|
# Before or after the database range
|
||||||
return err((hike.root,NearbyBeyondRange))
|
return err((hike.root,NearbyBeyondRange))
|
||||||
pfx = rootVtx.ePfx & NibblesBuf.nibble(n.byte)
|
pfx = rootVtx.pfx & NibblesBuf.nibble(n.byte)
|
||||||
|
|
||||||
of Leaf:
|
of Leaf:
|
||||||
pfx = rootVtx.lPfx
|
pfx = rootVtx.pfx
|
||||||
if not hike.accept pfx:
|
if not hike.accept pfx:
|
||||||
# Before or after the database range
|
# Before or after the database range
|
||||||
return err((hike.root,NearbyBeyondRange))
|
return err((hike.root,NearbyBeyondRange))
|
||||||
|
@ -230,12 +230,12 @@ proc finalise(
|
||||||
if not vtx.isValid:
|
if not vtx.isValid:
|
||||||
return err((vid,NearbyDanglingLink))
|
return err((vid,NearbyDanglingLink))
|
||||||
|
|
||||||
var pfx: NibblesBuf
|
let pfx =
|
||||||
case vtx.vType:
|
case vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
pfx = vtx.lPfx
|
vtx.pfx
|
||||||
of Branch:
|
of Branch:
|
||||||
pfx = vtx.ePfx & NibblesBuf.nibble(vtx.branchBorderNibble.byte)
|
vtx.pfx & NibblesBuf.nibble(vtx.branchBorderNibble.byte)
|
||||||
if hike.beyond pfx:
|
if hike.beyond pfx:
|
||||||
return err((vid,NearbyBeyondRange))
|
return err((vid,NearbyBeyondRange))
|
||||||
|
|
||||||
|
@ -308,7 +308,7 @@ proc nearbyNext(
|
||||||
|
|
||||||
case vtx.vType
|
case vtx.vType
|
||||||
of Leaf:
|
of Leaf:
|
||||||
if uHike.accept vtx.lPfx:
|
if uHike.accept vtx.pfx:
|
||||||
return uHike.complete(vid, db, hikeLenMax, doLeast=moveRight)
|
return uHike.complete(vid, db, hikeLenMax, doLeast=moveRight)
|
||||||
of Branch:
|
of Branch:
|
||||||
let nibble = uHike.tail[0].int8
|
let nibble = uHike.tail[0].int8
|
||||||
|
@ -408,7 +408,7 @@ iterator rightPairs*(
|
||||||
# Increment `key` by one and update `hike`. In many cases, the current
|
# Increment `key` by one and update `hike`. In many cases, the current
|
||||||
# `hike` can be modified and re-used which saves some database lookups.
|
# `hike` can be modified and re-used which saves some database lookups.
|
||||||
block reuseHike:
|
block reuseHike:
|
||||||
let tail = hike.legs[^1].wp.vtx.lPfx
|
let tail = hike.legs[^1].wp.vtx.pfx
|
||||||
if 0 < tail.len:
|
if 0 < tail.len:
|
||||||
let topNibble = tail[tail.len - 1]
|
let topNibble = tail[tail.len - 1]
|
||||||
if topNibble < 15:
|
if topNibble < 15:
|
||||||
|
@ -503,7 +503,7 @@ iterator leftPairs*(
|
||||||
# Decrement `key` by one and update `hike`. In many cases, the current
|
# Decrement `key` by one and update `hike`. In many cases, the current
|
||||||
# `hike` can be modified and re-used which saves some database lookups.
|
# `hike` can be modified and re-used which saves some database lookups.
|
||||||
block reuseHike:
|
block reuseHike:
|
||||||
let tail = hike.legs[^1].wp.vtx.lPfx
|
let tail = hike.legs[^1].wp.vtx.pfx
|
||||||
if 0 < tail.len:
|
if 0 < tail.len:
|
||||||
let topNibble = tail[tail.len - 1]
|
let topNibble = tail[tail.len - 1]
|
||||||
if 0 < topNibble:
|
if 0 < topNibble:
|
||||||
|
@ -567,7 +567,7 @@ proc rightMissing*(
|
||||||
|
|
||||||
case vtx.vType
|
case vtx.vType
|
||||||
of Leaf:
|
of Leaf:
|
||||||
return ok(vtx.lPfx < hike.tail)
|
return ok(vtx.pfx < hike.tail)
|
||||||
of Branch:
|
of Branch:
|
||||||
return ok(vtx.branchNibbleMin(hike.tail[0].int8) < 0)
|
return ok(vtx.branchNibbleMin(hike.tail[0].int8) < 0)
|
||||||
|
|
||||||
|
|
|
@ -238,11 +238,11 @@ proc partPut*(
|
||||||
# Register core node. Even though these nodes are only local to this
|
# Register core node. Even though these nodes are only local to this
|
||||||
# loop local, they need to be updated because another `chain` might
|
# loop local, they need to be updated because another `chain` might
|
||||||
# merge into this one at exactly this node.
|
# merge into this one at exactly this node.
|
||||||
case node.vType:
|
case node.vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
node.lData = vtx.lData
|
node.vtx.lData = vtx.lData
|
||||||
of Branch:
|
of Branch:
|
||||||
node.bVid = vtx.bVid
|
node.vtx.bVid = vtx.bVid
|
||||||
ps.addCore(root, key) # register core node
|
ps.addCore(root, key) # register core node
|
||||||
ps.pureExt.del key # core node can't be an extension
|
ps.pureExt.del key # core node can't be an extension
|
||||||
continue
|
continue
|
||||||
|
@ -251,27 +251,27 @@ proc partPut*(
|
||||||
# stored separately off the database and will only be temporarily
|
# stored separately off the database and will only be temporarily
|
||||||
# inserted into the database on demand.
|
# inserted into the database on demand.
|
||||||
if node.prfType == isExtension:
|
if node.prfType == isExtension:
|
||||||
ps.pureExt[key] = PrfExtension(xPfx: node.ePfx, xLink: node.key[0])
|
ps.pureExt[key] = PrfExtension(xPfx: node.vtx.pfx, xLink: node.key[0])
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Otherwise assign new VIDs to a core node. Even though these nodes are
|
# Otherwise assign new VIDs to a core node. Even though these nodes are
|
||||||
# only local to this loop local, they need to be updated because another
|
# only local to this loop local, they need to be updated because another
|
||||||
# `chain` might merge into this one at exactly this node.
|
# `chain` might merge into this one at exactly this node.
|
||||||
case node.vType:
|
case node.vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
let lKey = node.key[0]
|
let lKey = node.key[0]
|
||||||
if node.lData.pType == AccountData and lKey.isValid:
|
if node.vtx.lData.pType == AccountData and lKey.isValid:
|
||||||
node.lData.stoID = (true, (? ps.getRvid(root, lKey))[0].vid)
|
node.vtx.lData.stoID = (true, (? ps.getRvid(root, lKey))[0].vid)
|
||||||
of Branch:
|
of Branch:
|
||||||
for n in 0 .. 15:
|
for n in 0 .. 15:
|
||||||
let bKey = node.key[n]
|
let bKey = node.key[n]
|
||||||
if bKey.isValid:
|
if bKey.isValid:
|
||||||
node.bVid[n] = (? ps.getRvid(root, bKey))[0].vid
|
node.vtx.bVid[n] = (? ps.getRvid(root, bKey))[0].vid
|
||||||
ps.addCore(root, key) # register core node
|
ps.addCore(root, key) # register core node
|
||||||
ps.pureExt.del key # core node can't be an extension
|
ps.pureExt.del key # core node can't be an extension
|
||||||
|
|
||||||
# Store vertex on database
|
# Store vertex on database
|
||||||
ps.db.layersPutVtx(rvid, VertexRef(node))
|
ps.db.layersPutVtx(rvid, node.vtx)
|
||||||
seen.incl key # node was processed here
|
seen.incl key # node was processed here
|
||||||
if stopHere: # follow up tail of earlier chain
|
if stopHere: # follow up tail of earlier chain
|
||||||
#discard ps.pp()
|
#discard ps.pp()
|
||||||
|
@ -456,7 +456,7 @@ proc partWithExtBegin*(ps: PartStateRef): Result[void,AristoError] =
|
||||||
if ps.db.getKey(rvid).isValid:
|
if ps.db.getKey(rvid).isValid:
|
||||||
restore()
|
restore()
|
||||||
return err(PartExtVtxExistsAlready)
|
return err(PartExtVtxExistsAlready)
|
||||||
ps.db.layersPutVtx(rvid, VertexRef(vType: Branch, ePfx: ext.xPfx))
|
ps.db.layersPutVtx(rvid, VertexRef(vType: Branch, pfx: ext.xPfx))
|
||||||
rollback.add rvid
|
rollback.add rvid
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
@ -464,7 +464,7 @@ proc partWithExtEnd*(ps: PartStateRef): Result[void,AristoError] =
|
||||||
var rollback: seq[(RootedVertexID,PrfExtension)]
|
var rollback: seq[(RootedVertexID,PrfExtension)]
|
||||||
proc restore() =
|
proc restore() =
|
||||||
for (rvid,ext) in rollback:
|
for (rvid,ext) in rollback:
|
||||||
ps.db.layersPutVtx(rvid, VertexRef(vType: Branch, ePfx: ext.xPfx))
|
ps.db.layersPutVtx(rvid, VertexRef(vType: Branch, pfx: ext.xPfx))
|
||||||
|
|
||||||
for (key,ext) in ps.pureExt.pairs:
|
for (key,ext) in ps.pureExt.pairs:
|
||||||
let rvid = ps[key]
|
let rvid = ps[key]
|
||||||
|
@ -474,7 +474,7 @@ proc partWithExtEnd*(ps: PartStateRef): Result[void,AristoError] =
|
||||||
restore()
|
restore()
|
||||||
return err(PartExtVtxHasVanished)
|
return err(PartExtVtxHasVanished)
|
||||||
if vtx.vType != Branch or
|
if vtx.vType != Branch or
|
||||||
vtx.ePfx != ext.xPfx or
|
vtx.pfx != ext.xPfx or
|
||||||
vtx.bVid != array[16,VertexID].default:
|
vtx.bVid != array[16,VertexID].default:
|
||||||
restore()
|
restore()
|
||||||
return err(PartExtVtxWasModified)
|
return err(PartExtVtxWasModified)
|
||||||
|
|
|
@ -48,14 +48,14 @@ proc chainRlpNodes*(
|
||||||
# Follow up child node
|
# Follow up child node
|
||||||
case vtx.vType:
|
case vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
if path != vtx.lPfx:
|
if path != vtx.pfx:
|
||||||
err(PartChnLeafPathMismatch)
|
err(PartChnLeafPathMismatch)
|
||||||
else:
|
else:
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
of Branch:
|
of Branch:
|
||||||
let nChewOff = sharedPrefixLen(vtx.ePfx, path)
|
let nChewOff = sharedPrefixLen(vtx.pfx, path)
|
||||||
if nChewOff != vtx.ePfx.len:
|
if nChewOff != vtx.pfx.len:
|
||||||
err(PartChnExtPfxMismatch)
|
err(PartChnExtPfxMismatch)
|
||||||
elif path.len == nChewOff:
|
elif path.len == nChewOff:
|
||||||
err(PartChnBranchPathExhausted)
|
err(PartChnBranchPathExhausted)
|
||||||
|
|
|
@ -41,7 +41,7 @@ proc pp*(n: PrfNode; ps: PartStateRef): string =
|
||||||
elif n.prfType == isError:
|
elif n.prfType == isError:
|
||||||
"(" & $n.error & ")"
|
"(" & $n.error & ")"
|
||||||
elif n.prfType == isExtension:
|
elif n.prfType == isExtension:
|
||||||
"X(" & n.ePfx.pp & "," & n.key[0].pp(ps.db) & ")"
|
"X(" & n.vtx.pfx.pp & "," & n.key[0].pp(ps.db) & ")"
|
||||||
else:
|
else:
|
||||||
"(" & NodeRef(n).pp(ps.db) & ")"
|
"(" & NodeRef(n).pp(ps.db) & ")"
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ proc pp*(t: Table[VertexID,HashKey]; ps: PartStateRef; indent = 4): string =
|
||||||
.mapIt((it,t.getOrDefault it))
|
.mapIt((it,t.getOrDefault it))
|
||||||
.mapIt("(" & it[0].pp & "," & it[1].pp(ps.db) & ")")
|
.mapIt("(" & it[0].pp & "," & it[1].pp(ps.db) & ")")
|
||||||
.join("," & indent.toPfx(1)) & "}"
|
.join("," & indent.toPfx(1)) & "}"
|
||||||
|
|
||||||
proc pp*(q: seq[HashKey]; ps: PartStateRef): string =
|
proc pp*(q: seq[HashKey]; ps: PartStateRef): string =
|
||||||
"(" & q.mapIt(it.pp ps.db).join("->") & ")[#" & $q.len & "]"
|
"(" & q.mapIt(it.pp ps.db).join("->") & ")[#" & $q.len & "]"
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ proc read(rlp: var Rlp; T: type PrfNode): T {.gcsafe, raises: [RlpError].} =
|
||||||
##
|
##
|
||||||
func readError(error: AristoError): PrfNode =
|
func readError(error: AristoError): PrfNode =
|
||||||
## Prettify return code expression
|
## Prettify return code expression
|
||||||
PrfNode(vType: Leaf, prfType: isError, error: error)
|
PrfNode(vtx: VertexRef(vType: Leaf), prfType: isError, error: error)
|
||||||
|
|
||||||
if not rlp.isList:
|
if not rlp.isList:
|
||||||
# Otherwise `rlp.items` would raise a `Defect`
|
# Otherwise `rlp.items` would raise a `Defect`
|
||||||
|
@ -64,17 +64,20 @@ proc read(rlp: var Rlp; T: type PrfNode): T {.gcsafe, raises: [RlpError].} =
|
||||||
let (isLeaf, pathSegment) = NibblesBuf.fromHexPrefix blobs[0]
|
let (isLeaf, pathSegment) = NibblesBuf.fromHexPrefix blobs[0]
|
||||||
if isLeaf:
|
if isLeaf:
|
||||||
return PrfNode(
|
return PrfNode(
|
||||||
vType: Leaf,
|
|
||||||
prfType: ignore,
|
prfType: ignore,
|
||||||
lPfx: pathSegment,
|
|
||||||
lData: LeafPayload(
|
vtx: VertexRef(
|
||||||
pType: RawData,
|
vType: Leaf,
|
||||||
rawBlob: blobs[1]))
|
pfx: pathSegment,
|
||||||
|
lData: LeafPayload(
|
||||||
|
pType: RawData,
|
||||||
|
rawBlob: blobs[1])))
|
||||||
else:
|
else:
|
||||||
var node = PrfNode(
|
var node = PrfNode(
|
||||||
vType: Branch,
|
|
||||||
prfType: isExtension,
|
prfType: isExtension,
|
||||||
ePfx: pathSegment)
|
vtx: VertexRef(
|
||||||
|
vType: Branch,
|
||||||
|
pfx: pathSegment))
|
||||||
node.key[0] = HashKey.fromBytes(blobs[1]).valueOr:
|
node.key[0] = HashKey.fromBytes(blobs[1]).valueOr:
|
||||||
return readError(PartRlpExtHashKeyExpected)
|
return readError(PartRlpExtHashKeyExpected)
|
||||||
return node
|
return node
|
||||||
|
@ -83,7 +86,8 @@ proc read(rlp: var Rlp; T: type PrfNode): T {.gcsafe, raises: [RlpError].} =
|
||||||
links[n] = HashKey.fromBytes(blobs[n]).valueOr:
|
links[n] = HashKey.fromBytes(blobs[n]).valueOr:
|
||||||
return readError(PartRlpBranchHashKeyExpected)
|
return readError(PartRlpBranchHashKeyExpected)
|
||||||
return PrfNode(
|
return PrfNode(
|
||||||
vType: Branch,
|
vtx: VertexRef(
|
||||||
|
vType: Branch),
|
||||||
prfType: ignore,
|
prfType: ignore,
|
||||||
key: links)
|
key: links)
|
||||||
else:
|
else:
|
||||||
|
@ -137,11 +141,11 @@ func toNodesTab*(
|
||||||
nodes[w.digestTo HashKey] = nd
|
nodes[w.digestTo HashKey] = nd
|
||||||
|
|
||||||
# Special decoding for account `Leaf` nodes
|
# Special decoding for account `Leaf` nodes
|
||||||
if nd.vType == Leaf and mode != ForceGenericPayload:
|
if nd.vtx.vType == Leaf and mode != ForceGenericPayload:
|
||||||
# Decode payload to deficated format for storage or accounts
|
# Decode payload to deficated format for storage or accounts
|
||||||
var pyl: PrfPayload
|
var pyl: PrfPayload
|
||||||
try:
|
try:
|
||||||
pyl = rlp.decode(nd.lData.rawBlob, PrfPayload)
|
pyl = rlp.decode(nd.vtx.lData.rawBlob, PrfPayload)
|
||||||
except RlpError:
|
except RlpError:
|
||||||
pyl = PrfPayload(prfType: isError, error: PartRlpPayloadException)
|
pyl = PrfPayload(prfType: isError, error: PartRlpPayloadException)
|
||||||
|
|
||||||
|
@ -150,10 +154,10 @@ func toNodesTab*(
|
||||||
# Single value encoding might not be unique so it cannot be
|
# Single value encoding might not be unique so it cannot be
|
||||||
# automatically detected
|
# automatically detected
|
||||||
if mode != AutomaticPayload:
|
if mode != AutomaticPayload:
|
||||||
nd.lData = LeafPayload(pType: StoData, stoData: pyl.num)
|
nd.vtx.lData = LeafPayload(pType: StoData, stoData: pyl.num)
|
||||||
of isAccount:
|
of isAccount:
|
||||||
nd.key[0] = pyl.acc.storageRoot.to(HashKey)
|
nd.key[0] = pyl.acc.storageRoot.to(HashKey)
|
||||||
nd.lData = LeafPayload(
|
nd.vtx.lData = LeafPayload(
|
||||||
pType: AccountData,
|
pType: AccountData,
|
||||||
account: AristoAccount(
|
account: AristoAccount(
|
||||||
nonce: pyl.acc.nonce,
|
nonce: pyl.acc.nonce,
|
||||||
|
@ -174,11 +178,11 @@ func toNodesTab*(
|
||||||
# Need to store raw extension
|
# Need to store raw extension
|
||||||
nodes[xKey] = xNode
|
nodes[xKey] = xNode
|
||||||
continue
|
continue
|
||||||
if nd.ePfx.len != 0:
|
if nd.vtx.pfx.len != 0:
|
||||||
return err(PartGarbledExtsInProofs)
|
return err(PartGarbledExtsInProofs)
|
||||||
# Move extended `nd` branch node
|
# Move extended `nd` branch node
|
||||||
nd.prfType = ignore
|
nd.prfType = ignore
|
||||||
nd.ePfx = xNode.ePfx
|
nd.vtx.pfx = xNode.vtx.pfx
|
||||||
nodes.del xNode.key[0]
|
nodes.del xNode.key[0]
|
||||||
nodes[xKey] = nd
|
nodes[xKey] = nd
|
||||||
|
|
||||||
|
@ -196,8 +200,8 @@ proc backLinks*(nTab: TableRef[HashKey,PrfNode]): PrfBackLinks =
|
||||||
|
|
||||||
# Collect predecessor list
|
# Collect predecessor list
|
||||||
for (key,nd) in nTab.pairs:
|
for (key,nd) in nTab.pairs:
|
||||||
if nd.vType == Leaf:
|
if nd.vtx.vType == Leaf:
|
||||||
if nd.lData.pType == AccountData and nd.key[0].isValid:
|
if nd.vtx.lData.pType == AccountData and nd.key[0].isValid:
|
||||||
result.links[nd.key[0]] = key
|
result.links[nd.key[0]] = key
|
||||||
elif nd.prfType == isExtension:
|
elif nd.prfType == isExtension:
|
||||||
result.links[nd.key[0]] = key
|
result.links[nd.key[0]] = key
|
||||||
|
@ -280,7 +284,7 @@ proc updateAccountsTree*(
|
||||||
for chain in bl.chains:
|
for chain in bl.chains:
|
||||||
for key in chain:
|
for key in chain:
|
||||||
nodes[].withValue(key,node):
|
nodes[].withValue(key,node):
|
||||||
if node.vType == Leaf and node.lData.pType == AccountData:
|
if node.vtx.vType == Leaf and node.vtx.lData.pType == AccountData:
|
||||||
|
|
||||||
# Ok, got an accounts leaf node
|
# Ok, got an accounts leaf node
|
||||||
if not accRootKey.isValid:
|
if not accRootKey.isValid:
|
||||||
|
|
|
@ -70,7 +70,7 @@ proc to*(node: NodeRef; T: type seq[Blob]): T =
|
||||||
## `<rlp-encoded-node>` type entries. Only in case of a combined extension
|
## `<rlp-encoded-node>` type entries. Only in case of a combined extension
|
||||||
## and branch vertex argument, there will be a double item list result.
|
## and branch vertex argument, there will be a double item list result.
|
||||||
##
|
##
|
||||||
case node.vType:
|
case node.vtx.vType:
|
||||||
of Branch:
|
of Branch:
|
||||||
# Do branch node
|
# Do branch node
|
||||||
var wr = initRlpWriter()
|
var wr = initRlpWriter()
|
||||||
|
@ -80,13 +80,13 @@ proc to*(node: NodeRef; T: type seq[Blob]): T =
|
||||||
wr.append EmptyBlob
|
wr.append EmptyBlob
|
||||||
let brData = wr.finish()
|
let brData = wr.finish()
|
||||||
|
|
||||||
if 0 < node.ePfx.len:
|
if 0 < node.vtx.pfx.len:
|
||||||
# Prefix branch by embedded extension node
|
# Prefix branch by embedded extension node
|
||||||
let brHash = brData.digestTo(HashKey)
|
let brHash = brData.digestTo(HashKey)
|
||||||
|
|
||||||
var wrx = initRlpWriter()
|
var wrx = initRlpWriter()
|
||||||
wrx.startList(2)
|
wrx.startList(2)
|
||||||
wrx.append node.ePfx.toHexPrefix(isleaf = false).data()
|
wrx.append node.vtx.pfx.toHexPrefix(isleaf = false).data()
|
||||||
wrx.append brHash
|
wrx.append brHash
|
||||||
|
|
||||||
result.add wrx.finish()
|
result.add wrx.finish()
|
||||||
|
@ -104,8 +104,8 @@ proc to*(node: NodeRef; T: type seq[Blob]): T =
|
||||||
|
|
||||||
var wr = initRlpWriter()
|
var wr = initRlpWriter()
|
||||||
wr.startList(2)
|
wr.startList(2)
|
||||||
wr.append node.lPfx.toHexPrefix(isleaf = true).data()
|
wr.append node.vtx.pfx.toHexPrefix(isleaf = true).data()
|
||||||
wr.append node.lData.serialise(getKey0).value
|
wr.append node.vtx.lData.serialise(getKey0).value
|
||||||
|
|
||||||
result.add (wr.finish())
|
result.add (wr.finish())
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ proc digestTo*(node: NodeRef; T: type HashKey): T =
|
||||||
## that a `Dummy` node is encoded as as a `Leaf`.
|
## that a `Dummy` node is encoded as as a `Leaf`.
|
||||||
##
|
##
|
||||||
var wr = initRlpWriter()
|
var wr = initRlpWriter()
|
||||||
case node.vType:
|
case node.vtx.vType:
|
||||||
of Branch:
|
of Branch:
|
||||||
# Do branch node
|
# Do branch node
|
||||||
wr.startList(17)
|
wr.startList(17)
|
||||||
|
@ -123,11 +123,11 @@ proc digestTo*(node: NodeRef; T: type HashKey): T =
|
||||||
wr.append EmptyBlob
|
wr.append EmptyBlob
|
||||||
|
|
||||||
# Do for embedded extension node
|
# Do for embedded extension node
|
||||||
if 0 < node.ePfx.len:
|
if 0 < node.vtx.pfx.len:
|
||||||
let brHash = wr.finish().digestTo(HashKey)
|
let brHash = wr.finish().digestTo(HashKey)
|
||||||
wr = initRlpWriter()
|
wr = initRlpWriter()
|
||||||
wr.startList(2)
|
wr.startList(2)
|
||||||
wr.append node.ePfx.toHexPrefix(isleaf = false).data()
|
wr.append node.vtx.pfx.toHexPrefix(isleaf = false).data()
|
||||||
wr.append brHash
|
wr.append brHash
|
||||||
|
|
||||||
of Leaf:
|
of Leaf:
|
||||||
|
@ -138,8 +138,8 @@ proc digestTo*(node: NodeRef; T: type HashKey): T =
|
||||||
ok(node.key[0]) # always succeeds
|
ok(node.key[0]) # always succeeds
|
||||||
|
|
||||||
wr.startList(2)
|
wr.startList(2)
|
||||||
wr.append node.lPfx.toHexPrefix(isleaf = true).data()
|
wr.append node.vtx.pfx.toHexPrefix(isleaf = true).data()
|
||||||
wr.append node.lData.serialise(getKey0).value
|
wr.append node.vtx.lData.serialise(getKey0).value
|
||||||
|
|
||||||
wr.finish().digestTo(HashKey)
|
wr.finish().digestTo(HashKey)
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ proc toNode*(
|
||||||
|
|
||||||
case vtx.vType:
|
case vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
let node = NodeRef(vType: Leaf, lPfx: vtx.lPfx, lData: vtx.lData)
|
let node = NodeRef(vtx: vtx.dup())
|
||||||
# Need to resolve storage root for account leaf
|
# Need to resolve storage root for account leaf
|
||||||
if vtx.lData.pType == AccountData:
|
if vtx.lData.pType == AccountData:
|
||||||
let stoID = vtx.lData.stoID
|
let stoID = vtx.lData.stoID
|
||||||
|
@ -68,7 +68,7 @@ proc toNode*(
|
||||||
return ok node
|
return ok node
|
||||||
|
|
||||||
of Branch:
|
of Branch:
|
||||||
let node = NodeRef(vType: Branch, bVid: vtx.bVid, ePfx: vtx.ePfx)
|
let node = NodeRef(vtx: vtx.dup())
|
||||||
var missing: seq[VertexID]
|
var missing: seq[VertexID]
|
||||||
for n in 0 .. 15:
|
for n in 0 .. 15:
|
||||||
let vid = vtx.bVid[n]
|
let vid = vtx.bVid[n]
|
||||||
|
@ -100,15 +100,15 @@ iterator subVids*(vtx: VertexRef): VertexID =
|
||||||
|
|
||||||
iterator subVidKeys*(node: NodeRef): (VertexID,HashKey) =
|
iterator subVidKeys*(node: NodeRef): (VertexID,HashKey) =
|
||||||
## Simolar to `subVids()` but for nodes
|
## Simolar to `subVids()` but for nodes
|
||||||
case node.vType:
|
case node.vtx.vType:
|
||||||
of Leaf:
|
of Leaf:
|
||||||
if node.lData.pType == AccountData:
|
if node.vtx.lData.pType == AccountData:
|
||||||
let stoID = node.lData.stoID
|
let stoID = node.vtx.lData.stoID
|
||||||
if stoID.isValid:
|
if stoID.isValid:
|
||||||
yield (stoID.vid, node.key[0])
|
yield (stoID.vid, node.key[0])
|
||||||
of Branch:
|
of Branch:
|
||||||
for n in 0 .. 15:
|
for n in 0 .. 15:
|
||||||
let vid = node.bVid[n]
|
let vid = node.vtx.bVid[n]
|
||||||
if vid.isValid:
|
if vid.isValid:
|
||||||
yield (vid,node.key[n])
|
yield (vid,node.key[n])
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ suite "Aristo blobify":
|
||||||
|
|
||||||
extension = VertexRef(
|
extension = VertexRef(
|
||||||
vType: Branch,
|
vType: Branch,
|
||||||
ePfx: NibblesBuf.nibble(2),
|
pfx: NibblesBuf.nibble(2),
|
||||||
bVid: [
|
bVid: [
|
||||||
VertexID(0),
|
VertexID(0),
|
||||||
VertexID(0),
|
VertexID(0),
|
||||||
|
|
Loading…
Reference in New Issue