tidying up branch node code

This commit is contained in:
andri lim 2020-05-07 22:03:00 +07:00
parent ba4360ba34
commit bac4913a5a
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 30 additions and 19 deletions

View File

@ -176,7 +176,7 @@ proc writeAccountNode(wb: var WitnessBuilder, kd: KeyData, acc: Account, nibbles
node: wb.db.get(acc.storageRoot.data), node: wb.db.get(acc.storageRoot.data),
parentGroup: kd.storageKeys.initGroup(), parentGroup: kd.storageKeys.initGroup(),
keys: kd.storageKeys, keys: kd.storageKeys,
depth: 0, # reset depth depth: 0, # set depth to zero
storageMode: true # switch to storage mode storageMode: true # switch to storage mode
) )
getBranchRecurse(wb, zz) getBranchRecurse(wb, zz)
@ -234,7 +234,7 @@ proc getBranchRecurse(wb: var WitnessBuilder, z: var StackElem) =
node: value.getNode, node: value.getNode,
parentGroup: mg.group, parentGroup: mg.group,
keys: z.keys, keys: z.keys,
depth: z.depth + k.len, depth: z.depth + k.len, # increase the depth by k.len
storageMode: z.storageMode storageMode: z.storageMode
) )
getBranchRecurse(wb, zz) getBranchRecurse(wb, zz)
@ -252,25 +252,27 @@ proc getBranchRecurse(wb: var WitnessBuilder, z: var StackElem) =
of 17: of 17:
let branchMask = rlpListToBitmask(nodeRlp) let branchMask = rlpListToBitmask(nodeRlp)
writeBranchNode(wb, branchMask, z.depth, z.node) writeBranchNode(wb, branchMask, z.depth, z.node)
let path = groups(z.keys, z.parentGroup, z.depth)
# if there is a match in any branch elem # if there is a match in any branch elem
# 1st to 16th, the recursion will go deeper # 1st to 16th, the recursion will go deeper
# by one nibble # by one nibble
let notLeaf = z.depth != 63 # path.len == 0 doAssert(z.depth != 64) # notLeaf or path.len == 0
for i in 0..<16:
if not branchMask.branchMaskBitIsSet(i): continue let path = groups(z.keys, z.parentGroup, z.depth)
var branch = nodeRlp.listElem(i) for i in nonEmpty(branchMask):
if notLeaf and branchMaskBitIsSet(path.mask, i): let branch = nodeRlp.listElem(i)
if branchMaskBitIsSet(path.mask, i):
# it is a match between multikeys and Branch Node elem
var zz = StackElem( var zz = StackElem(
node: branch.getNode, node: branch.getNode,
parentGroup: path.groups[i], parentGroup: path.groups[i],
keys: z.keys, keys: z.keys,
depth: z.depth + 1, depth: z.depth + 1, # increase the depth by one
storageMode: z.storageMode storageMode: z.storageMode
) )
getBranchRecurse(wb, zz) getBranchRecurse(wb, zz)
else: continue
if branch.isList: if branch.isList:
# short node appear in yellow paper # short node appear in yellow paper
# but never in the actual ethereum state trie # but never in the actual ethereum state trie
@ -278,6 +280,7 @@ proc getBranchRecurse(wb: var WitnessBuilder, z: var StackElem) =
# block witness spec silent about this # block witness spec silent about this
doAssert(false, "Short node should not exist in block witness") doAssert(false, "Short node should not exist in block witness")
else: else:
# if branch elem not empty and not a match, emit hash
writeHashNode(wb, branch.expectHash) writeHashNode(wb, branch.expectHash)
# 17th elem should always empty # 17th elem should always empty
@ -306,8 +309,8 @@ proc buildWitness*(wb: var WitnessBuilder, keys: MultikeysRef): seq[byte]
node: @(wb.db.get(wb.root.data)), node: @(wb.db.get(wb.root.data)),
parentGroup: keys.initGroup(), parentGroup: keys.initGroup(),
keys: keys, keys: keys,
depth: 0, depth: 0, # always start with a zero depth
storageMode: false storageMode: false # build account witness first
) )
getBranchRecurse(wb, z) getBranchRecurse(wb, z)

View File

@ -43,3 +43,11 @@ func constructBranchMask*(b1, b2: byte): uint {.inline.} =
result = uint(b1) shl 8 or uint(b2) result = uint(b1) shl 8 or uint(b2)
if countOnes(result) < 2 or ((result and (not 0x1FFFF'u)) != 0): if countOnes(result) < 2 or ((result and (not 0x1FFFF'u)) != 0):
raise newException(ParsingError, "Invalid branch mask pattern " & $result) raise newException(ParsingError, "Invalid branch mask pattern " & $result)
iterator nonEmpty*(branchMask: uint): int =
for i in 0..<16:
if not branchMask.branchMaskBitIsSet(i):
# we skip an empty elem
continue
yield i