mirror of https://github.com/status-im/nim-eth.git
parent
c482b4c5b6
commit
0addffcc6c
|
@ -1,6 +1,5 @@
|
||||||
import
|
import
|
||||||
./trie/[hexary, sparse_binary]
|
./trie/[hexary, trie_defs]
|
||||||
|
|
||||||
export
|
export
|
||||||
hexary, sparse_binary
|
hexary, trie_defs
|
||||||
|
|
||||||
|
|
|
@ -1,177 +0,0 @@
|
||||||
import
|
|
||||||
"."/[trie_bitseq, trie_defs, trie_utils, db, sparse_proofs]
|
|
||||||
|
|
||||||
export
|
|
||||||
trie_utils, trie_bitseq,
|
|
||||||
sparse_proofs.verifyProof
|
|
||||||
|
|
||||||
type
|
|
||||||
DB = TrieDatabaseRef
|
|
||||||
|
|
||||||
SparseBinaryTrie* = object
|
|
||||||
db: DB
|
|
||||||
rootHash: seq[byte]
|
|
||||||
|
|
||||||
type
|
|
||||||
# 256 * 2 div 8
|
|
||||||
DoubleHash = array[64, byte]
|
|
||||||
|
|
||||||
proc initDoubleHash(a, b: openArray[byte]): DoubleHash =
|
|
||||||
doAssert(a.len == 32, $a.len)
|
|
||||||
doAssert(b.len == 32, $b.len)
|
|
||||||
result[0..31] = a
|
|
||||||
result[32..^1] = b
|
|
||||||
|
|
||||||
proc initDoubleHash(x: openArray[byte]): DoubleHash =
|
|
||||||
initDoubleHash(x, x)
|
|
||||||
|
|
||||||
proc init*(x: typedesc[SparseBinaryTrie], db: DB): SparseBinaryTrie =
|
|
||||||
result.db = db
|
|
||||||
# Initialize an empty tree with one branch
|
|
||||||
var value = initDoubleHash(emptyNodeHashes[0].data)
|
|
||||||
result.rootHash = @(keccakHash(value).data)
|
|
||||||
result.db.put(result.rootHash, value)
|
|
||||||
|
|
||||||
for i in 0..<treeHeight - 1:
|
|
||||||
value = initDoubleHash(emptyNodeHashes[i+1].data)
|
|
||||||
result.db.put(emptyNodeHashes[i].data, value)
|
|
||||||
|
|
||||||
result.db.put(emptyLeafNodeHash.data, [])
|
|
||||||
|
|
||||||
proc initSparseBinaryTrie*(db: DB): SparseBinaryTrie =
|
|
||||||
init(SparseBinaryTrie, db)
|
|
||||||
|
|
||||||
proc init*(x: typedesc[SparseBinaryTrie], db: DB,
|
|
||||||
rootHash: openArray[byte]): SparseBinaryTrie =
|
|
||||||
checkValidHashZ(rootHash)
|
|
||||||
result.db = db
|
|
||||||
result.rootHash = @rootHash
|
|
||||||
|
|
||||||
proc initSparseBinaryTrie*(db: DB, rootHash: openArray[byte]): SparseBinaryTrie =
|
|
||||||
init(SparseBinaryTrie, db, rootHash)
|
|
||||||
|
|
||||||
proc getDB*(t: SparseBinaryTrie): auto = t.db
|
|
||||||
|
|
||||||
proc getRootHash*(self: SparseBinaryTrie): seq[byte] {.inline.} =
|
|
||||||
self.rootHash
|
|
||||||
|
|
||||||
proc getAux(self: SparseBinaryTrie, path: TrieBitSeq, rootHash: openArray[byte]): seq[byte] =
|
|
||||||
var nodeHash = @rootHash
|
|
||||||
for targetBit in path:
|
|
||||||
let value = self.db.get(nodeHash)
|
|
||||||
if value.len == 0: return
|
|
||||||
if targetBit: nodeHash = value[32..^1]
|
|
||||||
else: nodeHash = value[0..31]
|
|
||||||
|
|
||||||
if nodeHash == emptyLeafNodeHash.data:
|
|
||||||
result = @[]
|
|
||||||
else:
|
|
||||||
result = self.db.get(nodeHash)
|
|
||||||
|
|
||||||
proc get*(self: SparseBinaryTrie, key: openArray[byte]): seq[byte] =
|
|
||||||
## gets a key from the tree.
|
|
||||||
doAssert(key.len == pathByteLen)
|
|
||||||
let path = bits key
|
|
||||||
self.getAux(path, self.rootHash)
|
|
||||||
|
|
||||||
proc get*(self: SparseBinaryTrie, key, rootHash: openArray[byte]): seq[byte] =
|
|
||||||
## gets a key from the tree at a specific root.
|
|
||||||
doAssert(key.len == pathByteLen)
|
|
||||||
let path = bits key
|
|
||||||
self.getAux(path, rootHash)
|
|
||||||
|
|
||||||
proc hashAndSave*(self: SparseBinaryTrie, node: openArray[byte]): seq[byte] =
|
|
||||||
result = @(keccakHash(node).data)
|
|
||||||
self.db.put(result, node)
|
|
||||||
|
|
||||||
proc hashAndSave*(self: SparseBinaryTrie, a, b: openArray[byte]): seq[byte] =
|
|
||||||
let value = initDoubleHash(a, b)
|
|
||||||
result = @(keccakHash(value).data)
|
|
||||||
self.db.put(result, value)
|
|
||||||
|
|
||||||
proc setAux(self: var SparseBinaryTrie, value: openArray[byte],
|
|
||||||
path: TrieBitSeq, depth: int, nodeHash: openArray[byte]): seq[byte] =
|
|
||||||
if depth == treeHeight:
|
|
||||||
result = self.hashAndSave(value)
|
|
||||||
else:
|
|
||||||
let
|
|
||||||
node = self.db.get(nodeHash)
|
|
||||||
leftNode = node[0..31]
|
|
||||||
rightNode = node[32..^1]
|
|
||||||
if path[depth]:
|
|
||||||
result = self.hashAndSave(leftNode, self.setAux(value, path, depth+1, rightNode))
|
|
||||||
else:
|
|
||||||
result = self.hashAndSave(self.setAux(value, path, depth+1, leftNode), rightNode)
|
|
||||||
|
|
||||||
proc set*(self: var SparseBinaryTrie, key, value: openArray[byte]) =
|
|
||||||
## sets a new value for a key in the tree, returns the new root,
|
|
||||||
## and sets the new current root of the tree.
|
|
||||||
doAssert(key.len == pathByteLen)
|
|
||||||
let path = bits key
|
|
||||||
self.rootHash = self.setAux(value, path, 0, self.rootHash)
|
|
||||||
|
|
||||||
proc set*(self: var SparseBinaryTrie, key, value, rootHash: openArray[byte]): seq[byte] =
|
|
||||||
## sets a new value for a key in the tree at a specific root,
|
|
||||||
## and returns the new root.
|
|
||||||
doAssert(key.len == pathByteLen)
|
|
||||||
let path = bits key
|
|
||||||
self.setAux(value, path, 0, rootHash)
|
|
||||||
|
|
||||||
template exists*(self: SparseBinaryTrie, key: openArray[byte]): bool =
|
|
||||||
self.get(key) != []
|
|
||||||
|
|
||||||
proc del*(self: var SparseBinaryTrie, key: openArray[byte]) =
|
|
||||||
## Equals to setting the value to zeroBytesRange
|
|
||||||
doAssert(key.len == pathByteLen)
|
|
||||||
self.set(key, [])
|
|
||||||
|
|
||||||
# Dictionary API
|
|
||||||
template `[]`*(self: SparseBinaryTrie, key: openArray[byte]): seq[byte] =
|
|
||||||
self.get(key)
|
|
||||||
|
|
||||||
template `[]=`*(self: var SparseBinaryTrie, key, value: openArray[byte]) =
|
|
||||||
self.set(key, value)
|
|
||||||
|
|
||||||
template contains*(self: SparseBinaryTrie, key: openArray[byte]): bool =
|
|
||||||
self.exists(key)
|
|
||||||
|
|
||||||
proc proveAux(self: SparseBinaryTrie, key, rootHash: openArray[byte], output: var seq[seq[byte]]): bool =
|
|
||||||
doAssert(key.len == pathByteLen)
|
|
||||||
var currVal = self.db.get(rootHash)
|
|
||||||
if currVal.len == 0: return false
|
|
||||||
|
|
||||||
let path = bits key
|
|
||||||
for i, bit in path:
|
|
||||||
if bit:
|
|
||||||
# right side
|
|
||||||
output[i] = currVal[0..31]
|
|
||||||
currVal = self.db.get(currVal[32..^1])
|
|
||||||
if currVal.len == 0: return false
|
|
||||||
else:
|
|
||||||
output[i] = currVal[32..^1]
|
|
||||||
currVal = self.db.get(currVal[0..31])
|
|
||||||
if currVal.len == 0: return false
|
|
||||||
|
|
||||||
result = true
|
|
||||||
|
|
||||||
# prove generates a Merkle proof for a key.
|
|
||||||
proc prove*(self: SparseBinaryTrie, key: openArray[byte]): seq[seq[byte]] =
|
|
||||||
result = newSeq[seq[byte]](treeHeight)
|
|
||||||
if not self.proveAux(key, self.rootHash, result):
|
|
||||||
result = @[]
|
|
||||||
|
|
||||||
# prove generates a Merkle proof for a key, at a specific root.
|
|
||||||
proc prove*(self: SparseBinaryTrie, key, rootHash: openArray[byte]): seq[seq[byte]] =
|
|
||||||
result = newSeq[seq[byte]](treeHeight)
|
|
||||||
if not self.proveAux(key, rootHash, result):
|
|
||||||
result = @[]
|
|
||||||
|
|
||||||
# proveCompact generates a compacted Merkle proof for a key.
|
|
||||||
proc proveCompact*(self: SparseBinaryTrie, key: openArray[byte]): seq[seq[byte]] =
|
|
||||||
var temp = self.prove(key)
|
|
||||||
temp.compactProof
|
|
||||||
|
|
||||||
# proveCompact generates a compacted Merkle proof for a key, at a specific root.
|
|
||||||
proc proveCompact*(self: SparseBinaryTrie, key, rootHash: openArray[byte]): seq[seq[byte]] =
|
|
||||||
var temp = self.prove(key, rootHash)
|
|
||||||
temp.compactProof
|
|
|
@ -1,86 +0,0 @@
|
||||||
import
|
|
||||||
"."/[trie_bitseq, trie_defs, trie_utils]
|
|
||||||
|
|
||||||
const
|
|
||||||
treeHeight* = 160
|
|
||||||
pathByteLen* = treeHeight div 8
|
|
||||||
emptyLeafNodeHash* = blankStringHash
|
|
||||||
|
|
||||||
proc makeInitialEmptyTreeHash(H: static[int]): array[H, KeccakHash] =
|
|
||||||
result[^1] = emptyLeafNodeHash
|
|
||||||
for i in countdown(H-1, 1):
|
|
||||||
result[i - 1] = keccakHash(result[i].data, result[i].data)
|
|
||||||
|
|
||||||
# cannot yet turn this into compile time constant
|
|
||||||
let emptyNodeHashes* = makeInitialEmptyTreeHash(treeHeight)
|
|
||||||
|
|
||||||
# VerifyProof verifies a Merkle proof.
|
|
||||||
proc verifyProofAux*(proof: seq[seq[byte]], root, key, value: openArray[byte]): bool =
|
|
||||||
doAssert(root.len == 32)
|
|
||||||
doAssert(key.len == pathByteLen)
|
|
||||||
var
|
|
||||||
path = bits key
|
|
||||||
curHash = keccakHash(value)
|
|
||||||
|
|
||||||
if proof.len != treeHeight: return false
|
|
||||||
|
|
||||||
for i in countdown(treeHeight - 1, 0):
|
|
||||||
var node = proof[i]
|
|
||||||
if node.len != 32: return false
|
|
||||||
if path[i]: # right
|
|
||||||
# reuse curHash without more alloc
|
|
||||||
curHash = keccakHash(node, curHash.data)
|
|
||||||
else:
|
|
||||||
curHash = keccakHash(curHash.data, node)
|
|
||||||
|
|
||||||
result = curHash.data == root
|
|
||||||
|
|
||||||
template verifyProof*(proof: seq[seq[byte]], root, key, value: openArray[byte]): bool =
|
|
||||||
verifyProofAux(proof, root, key, value)
|
|
||||||
|
|
||||||
proc count(b: TrieBitSeq, val: bool): int =
|
|
||||||
for c in b:
|
|
||||||
if c == val: inc result
|
|
||||||
|
|
||||||
# CompactProof compacts a proof, to reduce its size.
|
|
||||||
proc compactProof*(proof: seq[seq[byte]]): seq[seq[byte]] =
|
|
||||||
if proof.len != treeHeight: return
|
|
||||||
|
|
||||||
var
|
|
||||||
data = newSeq[byte](pathByteLen)
|
|
||||||
bits = bits data
|
|
||||||
|
|
||||||
result = @[]
|
|
||||||
result.add @[]
|
|
||||||
for i in 0 ..< treeHeight:
|
|
||||||
var node = proof[i]
|
|
||||||
if node == emptyNodeHashes[i].data:
|
|
||||||
bits[i] = true
|
|
||||||
else:
|
|
||||||
result.add node
|
|
||||||
result[0] = bits.toBytes
|
|
||||||
|
|
||||||
# decompactProof decompacts a proof, so that it can be used for VerifyProof.
|
|
||||||
proc decompactProof*(proof: seq[seq[byte]]): seq[seq[byte]] =
|
|
||||||
if proof.len == 0: return
|
|
||||||
if proof[0].len != pathByteLen: return
|
|
||||||
let bits = bits proof[0]
|
|
||||||
if proof.len != bits.count(false) + 1: return
|
|
||||||
result = newSeq[seq[byte]](treeHeight)
|
|
||||||
|
|
||||||
var pos = 1 # skip bits
|
|
||||||
for i in 0 ..< treeHeight:
|
|
||||||
if bits[i]:
|
|
||||||
result[i] = @(emptyNodeHashes[i].data)
|
|
||||||
else:
|
|
||||||
result[i] = proof[pos]
|
|
||||||
inc pos
|
|
||||||
|
|
||||||
# verifyCompactProof verifies a compacted Merkle proof.
|
|
||||||
proc verifyCompactProofAux*(proof: seq[seq[byte]], root, key, value: openArray[byte]): bool =
|
|
||||||
var decompactedProof = decompactProof(proof)
|
|
||||||
if decompactedProof.len == 0: return false
|
|
||||||
verifyProofAux(decompactedProof, root, key, value)
|
|
||||||
|
|
||||||
template verifyCompactProof*(proof: seq[seq[byte]], root, key, value: openArray[byte]): bool =
|
|
||||||
verifyCompactProofAux(proof, root, key, value)
|
|
|
@ -5,7 +5,6 @@ import
|
||||||
./test_examples,
|
./test_examples,
|
||||||
./test_hexary_trie,
|
./test_hexary_trie,
|
||||||
./test_json_suite,
|
./test_json_suite,
|
||||||
./test_sparse_binary_trie,
|
|
||||||
./test_transaction_db,
|
./test_transaction_db,
|
||||||
./test_trie_bitseq,
|
./test_trie_bitseq,
|
||||||
./test_hexary_proof
|
./test_hexary_proof
|
||||||
|
|
|
@ -1,230 +0,0 @@
|
||||||
{.used.}
|
|
||||||
|
|
||||||
import
|
|
||||||
std/random,
|
|
||||||
unittest2,
|
|
||||||
stew/byteutils,
|
|
||||||
../../eth/trie/[db, sparse_binary, sparse_proofs],
|
|
||||||
./testutils
|
|
||||||
|
|
||||||
suite "sparse binary trie":
|
|
||||||
randomize()
|
|
||||||
var kv_pairs = randKVPair(20)
|
|
||||||
var numbers = randList(int, randGen(1, 99), randGen(50, 100))
|
|
||||||
var db = newMemoryDB()
|
|
||||||
var trie = initSparseBinaryTrie(db)
|
|
||||||
|
|
||||||
test "basic set":
|
|
||||||
for c in kv_pairs:
|
|
||||||
check trie.exists(c.key) == false
|
|
||||||
trie.set(c.key, c.value)
|
|
||||||
|
|
||||||
let prevRoot = trie.getRootHash()
|
|
||||||
test "basic get":
|
|
||||||
for c in kv_pairs:
|
|
||||||
let x = trie.get(c.key)
|
|
||||||
let y = c.value
|
|
||||||
check x == y
|
|
||||||
trie.del(c.key)
|
|
||||||
|
|
||||||
for c in kv_pairs:
|
|
||||||
check trie.exists(c.key) == false
|
|
||||||
|
|
||||||
check trie.getRootHash() == keccakHash(emptyNodeHashes[0].data, emptyNodeHashes[0].data).data
|
|
||||||
|
|
||||||
test "single update set":
|
|
||||||
random.shuffle(kv_pairs)
|
|
||||||
for c in kv_pairs:
|
|
||||||
trie.set(c.key, c.value)
|
|
||||||
|
|
||||||
# Check trie root remains the same even in different insert order
|
|
||||||
check trie.getRootHash() == prevRoot
|
|
||||||
|
|
||||||
let prior_to_update_root = trie.getRootHash()
|
|
||||||
test "single update get":
|
|
||||||
for i in numbers:
|
|
||||||
# If new value is the same as current value, skip the update
|
|
||||||
if toBytes($i) == trie.get(kv_pairs[i].key):
|
|
||||||
continue
|
|
||||||
# Update
|
|
||||||
trie.set(kv_pairs[i].key, toBytes($i))
|
|
||||||
check trie.get(kv_pairs[i].key) == toBytes($i)
|
|
||||||
check trie.getRootHash() != prior_to_update_root
|
|
||||||
|
|
||||||
# Un-update
|
|
||||||
trie.set(kv_pairs[i].key, kv_pairs[i].value)
|
|
||||||
check trie.getRootHash == prior_to_update_root
|
|
||||||
|
|
||||||
test "batch update with different update order":
|
|
||||||
# First batch update
|
|
||||||
for i in numbers:
|
|
||||||
trie.set(kv_pairs[i].key, toBytes($i))
|
|
||||||
|
|
||||||
let batch_updated_root = trie.getRootHash()
|
|
||||||
|
|
||||||
# Un-update
|
|
||||||
random.shuffle(numbers)
|
|
||||||
for i in numbers:
|
|
||||||
trie.set(kv_pairs[i].key, kv_pairs[i].value)
|
|
||||||
|
|
||||||
check trie.getRootHash() == prior_to_update_root
|
|
||||||
|
|
||||||
# Second batch update
|
|
||||||
random.shuffle(numbers)
|
|
||||||
for i in numbers:
|
|
||||||
trie.set(kv_pairs[i].key, toBytes($i))
|
|
||||||
|
|
||||||
check trie.getRootHash() == batch_updated_root
|
|
||||||
|
|
||||||
test "dictionary API":
|
|
||||||
trie[kv_pairs[0].key] = kv_pairs[0].value
|
|
||||||
let x = trie[kv_pairs[0].key]
|
|
||||||
let y = kv_pairs[0].value
|
|
||||||
check x == y
|
|
||||||
check kv_pairs[0].key in trie
|
|
||||||
|
|
||||||
test "get/set for specific root":
|
|
||||||
db = newMemoryDB()
|
|
||||||
trie = initSparseBinaryTrie(db)
|
|
||||||
let
|
|
||||||
testKey = kv_pairs[0].key
|
|
||||||
testValue = kv_pairs[0].value
|
|
||||||
testKey2 = kv_pairs[1].key
|
|
||||||
testValue2 = kv_pairs[1].value
|
|
||||||
|
|
||||||
trie.set(testKey, testValue)
|
|
||||||
var root = trie.getRootHash()
|
|
||||||
var value = trie.get(testKey, root)
|
|
||||||
check value == testValue
|
|
||||||
|
|
||||||
root = trie.set(testKey2, testValue2, root)
|
|
||||||
value = trie.get(testKey2, root)
|
|
||||||
check value == testValue2
|
|
||||||
|
|
||||||
value = trie.get(testKey, root)
|
|
||||||
check value == testValue
|
|
||||||
|
|
||||||
proc makeBadProof(size: int, width = 32): seq[seq[byte]] =
|
|
||||||
let badProofStr = randList(seq[byte], randGen(width, width), randGen(size, size))
|
|
||||||
result = newSeq[seq[byte]](size)
|
|
||||||
for i in 0 ..< result.len:
|
|
||||||
result[i] = badProofStr[i]
|
|
||||||
|
|
||||||
test "proofs":
|
|
||||||
const
|
|
||||||
MaxBadProof = 32 * 8
|
|
||||||
|
|
||||||
let
|
|
||||||
testKey = kv_pairs[0].key
|
|
||||||
badKey = kv_pairs[1].key
|
|
||||||
testValue = "testValue".toBytes
|
|
||||||
testValue2 = "testValue2".toBytes
|
|
||||||
badValue = "badValue".toBytes
|
|
||||||
badProof = makeBadProof(MaxBadProof)
|
|
||||||
|
|
||||||
trie[testKey] = testValue
|
|
||||||
var proof = trie.prove(testKey)
|
|
||||||
check proof.len == treeHeight
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey, testValue) == true
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey, badValue) == false
|
|
||||||
check verifyProof(proof, trie.getRootHash(), badKey, testValue) == false
|
|
||||||
check verifyProof(badProof, trie.getRootHash(), testKey, testValue) == false
|
|
||||||
|
|
||||||
let
|
|
||||||
testKey2 = kv_pairs[2].key
|
|
||||||
testKey3 = kv_pairs[3].key
|
|
||||||
defaultValue = default(seq[byte])
|
|
||||||
|
|
||||||
trie.set(testKey2, testValue)
|
|
||||||
proof = trie.prove(testKey)
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey, testValue) == true
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey, badValue) == false
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey2, testValue) == false
|
|
||||||
check verifyProof(badProof, trie.getRootHash(), testKey, testValue) == false
|
|
||||||
|
|
||||||
proof = trie.prove(testKey2)
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey2, testValue) == true
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey2, badValue) == false
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey3, testValue) == false
|
|
||||||
check verifyProof(badProof, trie.getRootHash(), testKey, testValue) == false
|
|
||||||
|
|
||||||
var compactProof = compactProof(proof)
|
|
||||||
var decompactedProof = decompactProof(compactProof)
|
|
||||||
|
|
||||||
check decompactedProof.len == proof.len
|
|
||||||
for i, c in proof:
|
|
||||||
check decompactedProof[i] == c
|
|
||||||
|
|
||||||
let
|
|
||||||
badProof2 = makeBadProof(MaxBadProof + 1)
|
|
||||||
badProof3 = makeBadProof(MaxBadProof - 1)
|
|
||||||
badProof4 = makeBadProof(MaxBadProof, 31)
|
|
||||||
badProof5 = makeBadProof(MaxBadProof, 33)
|
|
||||||
badProof6 = makeBadProof(MaxBadProof, 1)
|
|
||||||
|
|
||||||
check verifyProof(badProof2, trie.getRootHash(), testKey3, defaultValue) == false
|
|
||||||
check verifyProof(badProof3, trie.getRootHash(), testKey3, defaultValue) == false
|
|
||||||
check verifyProof(badProof4, trie.getRootHash(), testKey3, defaultValue) == false
|
|
||||||
check verifyProof(badProof5, trie.getRootHash(), testKey3, defaultValue) == false
|
|
||||||
check verifyProof(badProof6, trie.getRootHash(), testKey3, defaultValue) == false
|
|
||||||
|
|
||||||
check compactProof(badProof2).len == 0
|
|
||||||
check compactProof(badProof3).len == 0
|
|
||||||
check decompactProof(badProof3).len == 0
|
|
||||||
var zeroProof: seq[seq[byte]]
|
|
||||||
check decompactProof(zeroProof).len == 0
|
|
||||||
|
|
||||||
proof = trie.proveCompact(testKey2)
|
|
||||||
check verifyCompactProof(proof, trie.getRootHash(), testKey2, testValue) == true
|
|
||||||
check verifyCompactProof(proof, trie.getRootHash(), testKey2, badValue) == false
|
|
||||||
check verifyCompactProof(proof, trie.getRootHash(), testKey3, testValue) == false
|
|
||||||
check verifyCompactProof(badProof, trie.getRootHash(), testKey, testValue) == false
|
|
||||||
|
|
||||||
var root = trie.getRootHash()
|
|
||||||
trie.set(testKey2, testValue2)
|
|
||||||
|
|
||||||
proof = trie.proveCompact(testKey2, root)
|
|
||||||
check verifyCompactProof(proof, root, testKey2, testValue) == true
|
|
||||||
check verifyCompactProof(proof, root, testKey2, badValue) == false
|
|
||||||
check verifyCompactProof(proof, root, testKey3, testValue) == false
|
|
||||||
check verifyCompactProof(badProof, root, testKey, testValue) == false
|
|
||||||
|
|
||||||
proof = trie.prove(testKey2, root)
|
|
||||||
check verifyProof(proof, root, testKey2, testValue) == true
|
|
||||||
check verifyProof(proof, root, testKey2, badValue) == false
|
|
||||||
check verifyProof(proof, root, testKey3, testValue) == false
|
|
||||||
check verifyProof(badProof, root, testKey, testValue) == false
|
|
||||||
|
|
||||||
proof = trie.prove(testKey3)
|
|
||||||
check proof.len == 0
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey3, defaultValue) == false
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey3, badValue) == false
|
|
||||||
check verifyProof(proof, trie.getRootHash(), testKey2, defaultValue) == false
|
|
||||||
check verifyProof(badProof, trie.getRootHash(), testKey, testValue) == false
|
|
||||||
|
|
||||||
test "examples":
|
|
||||||
let
|
|
||||||
key1 = "01234567890123456789".toBytes
|
|
||||||
key2 = "abcdefghijklmnopqrst".toBytes
|
|
||||||
|
|
||||||
trie.set(key1, "value1".toBytes)
|
|
||||||
trie.set(key2, "value2".toBytes)
|
|
||||||
check trie.get(key1) == "value1".toBytes
|
|
||||||
check trie.get(key2) == "value2".toBytes
|
|
||||||
|
|
||||||
trie.del(key1)
|
|
||||||
check trie.get(key1) == []
|
|
||||||
|
|
||||||
trie.del(key2)
|
|
||||||
check trie[key2] == []
|
|
||||||
|
|
||||||
let
|
|
||||||
value1 = "hello world".toBytes
|
|
||||||
badValue = "bad value".toBytes
|
|
||||||
|
|
||||||
trie[key1] = value1
|
|
||||||
var proof = trie.prove(key1)
|
|
||||||
|
|
||||||
check verifyProof(proof, trie.getRootHash(), key1, value1) == true
|
|
||||||
check verifyProof(proof, trie.getRootHash(), key1, badValue) == false
|
|
||||||
check verifyProof(proof, trie.getRootHash(), key2, value1) == false
|
|
Loading…
Reference in New Issue