def verifyMerkleProof(*replies: Tuple[Reply]) -> bool: """ Verifies the correctness of the merkle proof provided in the reply from the node. Returns True if verified to be correct, throws an exception otherwise. :param replies: One or more replies for which Merkle Proofs have to be verified :raises ProofError: The proof is invalid :return: True """ verifier = MerkleVerifier() serializer = ledger_txn_serializer ignored = {F.auditPath.name, F.seqNo.name, F.rootHash.name} for r in replies: seqNo = r[f.RESULT.nm][F.seqNo.name] rootHash = Ledger.strToHash( r[f.RESULT.nm][F.rootHash.name]) auditPath = [Ledger.strToHash(a) for a in r[f.RESULT.nm][F.auditPath.name]] filtered = dict((k, v) for (k, v) in r[f.RESULT.nm].items() if k not in ignored) result = serializer.serialize(filtered) verifier.verify_leaf_inclusion(result, seqNo - 1, auditPath, STH(tree_size=seqNo, sha256_root_hash=rootHash)) return True
def verifyMerkleProof(*replies: Tuple[Reply]) -> bool: """ Verifies the correctness of the merkle proof provided in the reply from the node. Returns True if verified to be correct, throws an exception otherwise. :param replies: One or more replies for which Merkle Proofs have to be verified :raises ProofError: The proof is invalid :return: True """ verifier = MerkleVerifier() fields = getTxnOrderedFields() serializer = CompactSerializer(fields=fields) for r in replies: seqNo = r[f.RESULT.nm][F.seqNo.name] rootHash = base64.b64decode( r[f.RESULT.nm][F.rootHash.name].encode()) auditPath = [ base64.b64decode(a.encode()) for a in r[f.RESULT.nm][F.auditPath.name] ] filtered = ( (k, v) for (k, v) in r[f.RESULT.nm].iteritems() if k not in [F.auditPath.name, F.seqNo.name, F.rootHash.name]) result = serializer.serialize(dict(filtered)) verifier.verify_leaf_inclusion( result, seqNo - 1, auditPath, STH(tree_size=seqNo, sha256_root_hash=rootHash)) return True
def testCompactMerkleTree(hasherAndTree, verifier): h, m = hasherAndTree printEvery = 1000 count = TXN_COUNT for d in range(count): data = str(d + 1).encode() data_hex = hexlify(data) audit_path = m.append(data) audit_path_hex = [hexlify(h) for h in audit_path] incl_proof = m.inclusion_proof(d, d + 1) assert audit_path == incl_proof assert m.nodeCount == m.get_expected_node_count(m.leafCount) assert m.hashStore.is_consistent if d % printEvery == 0: show(h, m, data_hex) print("audit path is {}".format(audit_path_hex)) print("audit path length is {}".format( verifier.audit_path_length(d, d + 1))) print("audit path calculated length is {}".format(len(audit_path))) calculated_root_hash = verifier._calculate_root_hash_from_audit_path( h.hash_leaf(data), d, audit_path[:], d + 1) if d % printEvery == 0: print("calculated root hash is {}".format(calculated_root_hash)) sth = STH(d + 1, m.root_hash) verifier.verify_leaf_inclusion(data, d, audit_path, sth) checkConsistency(m, verifier=verifier) for d in range(1, count): verifier.verify_tree_consistency(d, d + 1, m.merkle_tree_hash(0, d), m.merkle_tree_hash(0, d + 1), m.consistency_proof(d, d + 1)) newTree = CompactMerkleTree(hasher=h) m.save(newTree) assert m.root_hash == newTree.root_hash assert m.hashes == newTree.hashes newTree = CompactMerkleTree(hasher=h) newTree.load(m) assert m.root_hash == newTree.root_hash assert m.hashes == newTree.hashes newTree = copy(m) assert m.root_hash == newTree.root_hash assert m.hashes == newTree.hashes
def checkLeafInclusion(verifier, leafData, leafIndex, proof, treeHead): assert verifier.verify_leaf_inclusion(leaf=leafData, leaf_index=leafIndex, proof=proof, sth=STH(**treeHead))
def testLocate(hasherAndTree, addTxns, storeHashes): h, m = hasherAndTree mhs = storeHashes txnCount, auditPaths = addTxns verifier = MerkleVerifier() startingTime = time.perf_counter() for d in range(50): print() pos = d + 1 print("Audit Path for Serial No: {}".format(pos)) leafs, nodes = mhs.getPath(pos) calculatedAuditPath = [] for i, leaf_pos in enumerate(leafs): hexLeafData = hexlify(mhs.readLeaf(leaf_pos)) print("leaf: {}".format(hexLeafData)) calculatedAuditPath.append(hexLeafData) for node_pos in nodes: node = mhs.readNode(node_pos) hexNodeData = hexlify(node) print("node: {}".format(hexNodeData)) calculatedAuditPath.append(hexNodeData) print("{} -> leafs: {}, nodes: {}".format(pos, leafs, nodes)) print("Audit path built using formula {}".format(calculatedAuditPath)) print("Audit path received while appending leaf {}".format( auditPaths[d])) # Testing equality of audit path calculated using formula and audit path # received while inserting leaf into the tree assert calculatedAuditPath == auditPaths[d] auditPathLength = verifier.audit_path_length(d, d + 1) assert auditPathLength == len(calculatedAuditPath) # Testing root hash generation leafHash = storeHashes.readLeaf(d + 1) rootHashFrmCalc = hexlify( verifier._calculate_root_hash_from_audit_path( leafHash, d, [unhexlify(h) for h in calculatedAuditPath], d + 1)) rootHash = hexlify( verifier._calculate_root_hash_from_audit_path( leafHash, d, [unhexlify(h) for h in auditPaths[d]], d + 1)) assert rootHash == rootHashFrmCalc print("Root hash from audit path built using formula {}".format( calculatedAuditPath)) print("Root hash from audit path received while appending leaf {}". format(auditPaths[d])) print("Leaf hash length is {}".format(len(leafHash))) print("Root hash length is {}".format(len(rootHash))) # Testing verification, do not need `assert` since # `verify_leaf_hash_inclusion` will throw an exception sthFrmCalc = STH(d + 1, unhexlify(rootHashFrmCalc)) verifier.verify_leaf_hash_inclusion( leafHash, d, [unhexlify(h) for h in calculatedAuditPath], sthFrmCalc) sth = STH(d + 1, unhexlify(rootHash)) verifier.verify_leaf_hash_inclusion( leafHash, d, [unhexlify(h) for h in auditPaths[d]], sth) print(time.perf_counter() - startingTime)