implement witness header encoding decoding and implement buildForest
This commit is contained in:
parent
90c2ede43b
commit
fdb750f67e
|
@ -40,7 +40,7 @@ proc testGetBranch(tester: Tester, rootHash: KeccakHash, testStatusIMPL: var Tes
|
||||||
else:
|
else:
|
||||||
var tb = initTreeBuilder(witness, db, flags)
|
var tb = initTreeBuilder(witness, db, flags)
|
||||||
|
|
||||||
var root = tb.treeNode()
|
var root = tb.buildTree()
|
||||||
check root.data == rootHash.data
|
check root.data == rootHash.data
|
||||||
except ContractCodeError as e:
|
except ContractCodeError as e:
|
||||||
debugEcho "CONTRACT CODE ERROR: ", e.msg
|
debugEcho "CONTRACT CODE ERROR: ", e.msg
|
||||||
|
|
|
@ -67,7 +67,7 @@ proc runTest(numPairs: int) =
|
||||||
var tb = initTreeBuilder(input, db, {wfEIP170})
|
var tb = initTreeBuilder(input, db, {wfEIP170})
|
||||||
else:
|
else:
|
||||||
var tb = initTreeBuilder(witness, db, {wfEIP170})
|
var tb = initTreeBuilder(witness, db, {wfEIP170})
|
||||||
var root = tb.treeNode()
|
var root = tb.buildTree()
|
||||||
debugEcho "root: ", root.data.toHex
|
debugEcho "root: ", root.data.toHex
|
||||||
debugEcho "rootHash: ", rootHash.data.toHex
|
debugEcho "rootHash: ", rootHash.data.toHex
|
||||||
doAssert root.data == rootHash.data
|
doAssert root.data == rootHash.data
|
||||||
|
|
|
@ -60,6 +60,8 @@ when defined(useInputStream):
|
||||||
template read(t: var TreeBuilder, len: int): auto =
|
template read(t: var TreeBuilder, len: int): auto =
|
||||||
t.input.read(len)
|
t.input.read(len)
|
||||||
|
|
||||||
|
template readable(t: var TreeBuilder): bool =
|
||||||
|
t.input.readable
|
||||||
else:
|
else:
|
||||||
template readByte(t: var TreeBuilder): byte =
|
template readByte(t: var TreeBuilder): byte =
|
||||||
let pos = t.pos
|
let pos = t.pos
|
||||||
|
@ -69,9 +71,8 @@ else:
|
||||||
template len(t: TreeBuilder): int =
|
template len(t: TreeBuilder): int =
|
||||||
t.input.len
|
t.input.len
|
||||||
|
|
||||||
template peek(t: TreeBuilder): byte =
|
template readable(t: var TreeBuilder): bool =
|
||||||
t.input.peek
|
t.pos < t.input.len
|
||||||
t.input[t.pos]
|
|
||||||
|
|
||||||
template read(t: var TreeBuilder, len: int): auto =
|
template read(t: var TreeBuilder, len: int): auto =
|
||||||
let pos = t.pos
|
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 accountNode(t: var TreeBuilder, depth: int): NodeKey
|
||||||
proc accountStorageLeafNode(t: var TreeBuilder, depth: int): NodeKey
|
proc accountStorageLeafNode(t: var TreeBuilder, depth: int): NodeKey
|
||||||
proc hashNode(t: var TreeBuilder): 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)
|
assert(depth < 64)
|
||||||
let nodeType = TrieNodeType(t.readByte)
|
let nodeType = TrieNodeType(t.readByte)
|
||||||
|
|
||||||
|
|
|
@ -244,8 +244,17 @@ proc getBranchRecurseAux(wb: var WitnessBuilder, node: openArray[byte], path: Ni
|
||||||
raise newException(CorruptedTrieDatabase,
|
raise newException(CorruptedTrieDatabase,
|
||||||
"HexaryTrie node with an unexpected number of children")
|
"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)
|
let key = keccak(address)
|
||||||
var node = wb.db.get(wb.root.data)
|
var node = wb.db.get(wb.root.data)
|
||||||
getBranchRecurseAux(wb, node, initNibbleRange(key.data), 0, false)
|
getBranchRecurseAux(wb, node, initNibbleRange(key.data), 0, false)
|
||||||
|
|
||||||
|
# result
|
||||||
result = wb.output.getOutput(seq[byte])
|
result = wb.output.getOutput(seq[byte])
|
||||||
|
|
|
@ -15,9 +15,14 @@ type
|
||||||
wfNoFlag
|
wfNoFlag
|
||||||
wfEIP170 # fork >= Spurious Dragon
|
wfEIP170 # fork >= Spurious Dragon
|
||||||
|
|
||||||
|
MetadataType* = enum
|
||||||
|
MetadataNothing
|
||||||
|
MetadataSomething
|
||||||
|
|
||||||
WitnessFlags* = set[WitnessFlag]
|
WitnessFlags* = set[WitnessFlag]
|
||||||
|
|
||||||
ContractCodeError* = object of ValueError
|
ContractCodeError* = object of ValueError
|
||||||
|
ParsingError* = object of ValueError
|
||||||
|
|
||||||
const
|
const
|
||||||
StorageLeafNodeType* = AccountNodeType
|
StorageLeafNodeType* = AccountNodeType
|
||||||
|
@ -33,6 +38,5 @@ func branchMaskBitIsSet*(x: uint, i: int): bool {.inline.} =
|
||||||
|
|
||||||
func constructBranchMask*(b1, b2: byte): uint {.inline.} =
|
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:
|
if countOnes(result) < 2 or ((result and (not 0x1FFFF'u)) != 0):
|
||||||
debugEcho "MASK: ", result
|
raise newException(ParsingError, "Invalid branch mask pattern")
|
||||||
assert(countOnes(result) > 1)
|
|
||||||
|
|
Loading…
Reference in New Issue