implement witness header encoding decoding and implement buildForest

This commit is contained in:
andri lim 2020-04-29 15:29:25 +07:00
parent 90c2ede43b
commit fdb750f67e
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
5 changed files with 59 additions and 10 deletions

View File

@ -40,7 +40,7 @@ proc testGetBranch(tester: Tester, rootHash: KeccakHash, testStatusIMPL: var Tes
else:
var tb = initTreeBuilder(witness, db, flags)
var root = tb.treeNode()
var root = tb.buildTree()
check root.data == rootHash.data
except ContractCodeError as e:
debugEcho "CONTRACT CODE ERROR: ", e.msg

View File

@ -67,7 +67,7 @@ proc runTest(numPairs: int) =
var tb = initTreeBuilder(input, db, {wfEIP170})
else:
var tb = initTreeBuilder(witness, db, {wfEIP170})
var root = tb.treeNode()
var root = tb.buildTree()
debugEcho "root: ", root.data.toHex
debugEcho "rootHash: ", rootHash.data.toHex
doAssert root.data == rootHash.data

View File

@ -60,6 +60,8 @@ when defined(useInputStream):
template read(t: var TreeBuilder, len: int): auto =
t.input.read(len)
template readable(t: var TreeBuilder): bool =
t.input.readable
else:
template readByte(t: var TreeBuilder): byte =
let pos = t.pos
@ -69,9 +71,8 @@ else:
template len(t: TreeBuilder): int =
t.input.len
template peek(t: TreeBuilder): byte =
t.input.peek
t.input[t.pos]
template readable(t: var TreeBuilder): bool =
t.pos < t.input.len
template read(t: var TreeBuilder, len: int): auto =
let pos = t.pos
@ -115,8 +116,43 @@ proc extensionNode(t: var TreeBuilder, depth: int, storageMode: bool): NodeKey
proc accountNode(t: var TreeBuilder, depth: int): NodeKey
proc accountStorageLeafNode(t: var TreeBuilder, depth: int): NodeKey
proc hashNode(t: var TreeBuilder): NodeKey
proc treeNode(t: var TreeBuilder, depth: int = 0, storageMode = false): NodeKey
proc treeNode*(t: var TreeBuilder, depth: int = 0, storageMode = false): NodeKey =
proc buildTree*(t: var TreeBuilder): KeccakHash =
let version = t.readByte().int
if version != BlockWitnessVersion.int:
raise newException(ParsingError, "Wrong block witness version")
# one or more trees
# we only parse one tree here
let metadataType = t.readByte().int
if metadataType != MetadataNothing.int:
raise newException(ParsingError, "This tree builder support no metadata")
var res = treeNode(t)
if res.usedBytes != 32:
raise newException(ParsingError, "Buildtree should produce hash")
result.data = res.data
proc buildForest*(t: var TreeBuilder): seq[KeccakHash] =
let version = t.readByte().int
if version != BlockWitnessVersion.int:
raise newException(ParsingError, "Wrong block witness version")
while t.readable:
let metadataType = t.readByte().int
if metadataType != MetadataNothing.int:
raise newException(ParsingError, "This tree builder support no metadata")
var res = treeNode(t)
if res.usedBytes != 32:
raise newException(ParsingError, "Buildtree should produce hash")
result.add KeccakHash(data: res.data)
proc treeNode(t: var TreeBuilder, depth: int = 0, storageMode = false): NodeKey =
assert(depth < 64)
let nodeType = TrieNodeType(t.readByte)

View File

@ -244,8 +244,17 @@ proc getBranchRecurseAux(wb: var WitnessBuilder, node: openArray[byte], path: Ni
raise newException(CorruptedTrieDatabase,
"HexaryTrie node with an unexpected number of children")
proc buildWitness*(wb: var WitnessBuilder; address: EthAddress): seq[byte] =
proc buildWitness*(wb: var WitnessBuilder; address: EthAddress, withVersion: bool = true): seq[byte] =
# witness version
wb.output.append(BlockWitnessVersion.byte)
# one or more trees
# we only output one tree
wb.output.append(MetadataNothing.byte)
let key = keccak(address)
var node = wb.db.get(wb.root.data)
getBranchRecurseAux(wb, node, initNibbleRange(key.data), 0, false)
# result
result = wb.output.getOutput(seq[byte])

View File

@ -15,9 +15,14 @@ type
wfNoFlag
wfEIP170 # fork >= Spurious Dragon
MetadataType* = enum
MetadataNothing
MetadataSomething
WitnessFlags* = set[WitnessFlag]
ContractCodeError* = object of ValueError
ParsingError* = object of ValueError
const
StorageLeafNodeType* = AccountNodeType
@ -33,6 +38,5 @@ func branchMaskBitIsSet*(x: uint, i: int): bool {.inline.} =
func constructBranchMask*(b1, b2: byte): uint {.inline.} =
result = uint(b1) shl 8 or uint(b2)
if countOnes(result) < 2:
debugEcho "MASK: ", result
assert(countOnes(result) > 1)
if countOnes(result) < 2 or ((result and (not 0x1FFFF'u)) != 0):
raise newException(ParsingError, "Invalid branch mask pattern")