示例#1
0
    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
示例#2
0
    def _has_valid_catchup_replies(
            self, seq_no: int,
            txns_to_process: List[Tuple[int, Any]]) -> Tuple[bool, str, int]:
        """
        Transforms transactions for ledger!

        Returns:
            Whether catchup reply corresponding to seq_no
            Name of node from which txns came
            Number of transactions ready to be processed
        """

        # TODO: Remove after stop passing seqNo here
        assert seq_no == txns_to_process[0][0]

        # Here seqNo has to be the seqNo of first transaction of
        # `catchupReplies`

        # Get the transactions in the catchup reply which has sequence
        # number `seqNo`
        node_name, catchup_rep = self._find_catchup_reply_for_seq_no(seq_no)
        txns = catchup_rep.txns

        # Add only those transaction in the temporary tree from the above
        # batch which are not present in the ledger
        # Integer keys being converted to strings when marshaled to JSON
        txns = [
            self._provider.transform_txn_for_ledger(txn)
            for s, txn in txns_to_process[:len(txns)] if str(s) in txns
        ]

        # Creating a temporary tree which will be used to verify consistency
        # proof, by inserting transactions. Duplicating a merkle tree is not
        # expensive since we are using a compact merkle tree.
        temp_tree = self._ledger.treeWithAppliedTxns(txns)

        proof = catchup_rep.consProof
        final_size = self._catchup_till.seqNoEnd
        final_hash = self._catchup_till.newMerkleRoot
        try:
            logger.info("{} verifying proof for {}, {}, {}, {}, {}".format(
                self, temp_tree.tree_size, final_size, temp_tree.root_hash,
                Ledger.strToHash(final_hash),
                [Ledger.strToHash(p) for p in proof]))
            verified = self._provider.verifier(
                self._ledger_id).verify_tree_consistency(
                    temp_tree.tree_size, final_size, temp_tree.root_hash,
                    Ledger.strToHash(final_hash),
                    [Ledger.strToHash(p) for p in proof])

        except Exception as ex:
            logger.info("{} could not verify catchup reply {} since {}".format(
                self, catchup_rep, ex))
            verified = False
        return bool(verified), node_name, len(txns)
示例#3
0
 def from_ordered(ordered):
     return ThreePcBatch(ledger_id=ordered.ledgerId,
                         inst_id=ordered.instId,
                         view_no=ordered.viewNo,
                         pp_seq_no=ordered.ppSeqNo,
                         pp_time=ordered.ppTime,
                         valid_txn_count=len(ordered.valid_reqIdr),
                         state_root=Ledger.strToHash(ordered.stateRootHash),
                         txn_root=Ledger.strToHash(ordered.txnRootHash),
                         has_audit_txn=f.AUDIT_TXN_ROOT_HASH.nm in ordered
                         and ordered.auditTxnRootHash is not None)
示例#4
0
 def from_ordered(ordered):
     return ThreePcBatch(ledger_id=ordered.ledgerId,
                         inst_id=ordered.instId,
                         view_no=ordered.viewNo,
                         pp_seq_no=ordered.ppSeqNo,
                         pp_time=ordered.ppTime,
                         state_root=Ledger.strToHash(ordered.stateRootHash),
                         txn_root=Ledger.strToHash(ordered.txnRootHash),
                         primaries=ordered.primaries,
                         valid_digests=ordered.valid_reqIdr,
                         has_audit_txn=f.AUDIT_TXN_ROOT_HASH.nm in ordered
                         and ordered.auditTxnRootHash is not None,
                         original_view_no=ordered.originalViewNo)
示例#5
0
 def from_batch_committed_dict(batch_comitted):
     return ThreePcBatch(
         ledger_id=batch_comitted[f.LEDGER_ID.nm],
         inst_id=batch_comitted[f.INST_ID.nm],
         view_no=batch_comitted[f.VIEW_NO.nm],
         pp_seq_no=batch_comitted[f.PP_SEQ_NO.nm],
         pp_time=batch_comitted[f.PP_TIME.nm],
         valid_txn_count=batch_comitted[f.SEQ_NO_END.nm] -
         batch_comitted[f.SEQ_NO_START.nm] + 1,
         state_root=Ledger.strToHash(batch_comitted[f.STATE_ROOT.nm]),
         txn_root=Ledger.strToHash(batch_comitted[f.TXN_ROOT.nm]),
         has_audit_txn=f.AUDIT_TXN_ROOT_HASH.nm in batch_comitted
         and batch_comitted[f.AUDIT_TXN_ROOT_HASH.nm] is not None)
示例#6
0
 def from_batch_committed_dict(batch_comitted):
     valid_req_keys = [
         Request(**req_dict).key
         for req_dict in batch_comitted[f.REQUESTS.nm]
     ]
     return ThreePcBatch(
         ledger_id=batch_comitted[f.LEDGER_ID.nm],
         inst_id=batch_comitted[f.INST_ID.nm],
         view_no=batch_comitted[f.VIEW_NO.nm],
         pp_seq_no=batch_comitted[f.PP_SEQ_NO.nm],
         pp_time=batch_comitted[f.PP_TIME.nm],
         state_root=Ledger.strToHash(batch_comitted[f.STATE_ROOT.nm]),
         txn_root=Ledger.strToHash(batch_comitted[f.TXN_ROOT.nm]),
         primaries=batch_comitted[f.PRIMARIES.nm],
         valid_digests=valid_req_keys,
         has_audit_txn=f.AUDIT_TXN_ROOT_HASH.nm in batch_comitted
         and batch_comitted[f.AUDIT_TXN_ROOT_HASH.nm] is not None)
示例#7
0
    def hasValidCatchupReplies(self, ledgerId, ledger, seqNo, catchUpReplies):
        # Here seqNo has to be the seqNo of first transaction of
        # `catchupReplies`

        # Get the batch of transactions in the catchup reply which has sequence
        # number `seqNo`
        nodeName, catchupReply = self._getCatchupReplyForSeqNo(ledgerId, seqNo)

        txns = getattr(catchupReply, f.TXNS.nm)

        # Add only those transaction in the temporary tree from the above
        # batch

        # Integer keys being converted to strings when marshaled to JSON
        txns = [
            self._transform(txn) for s, txn in catchUpReplies[:len(txns)]
            if str(s) in txns
        ]

        # Creating a temporary tree which will be used to verify consistency
        # proof, by inserting transactions. Duplicating a merkle tree is not
        # expensive since we are using a compact merkle tree.
        tempTree = ledger.treeWithAppliedTxns(txns)

        proof = getattr(catchupReply, f.CONS_PROOF.nm)
        ledgerInfo = self.getLedgerInfoByType(ledgerId)
        verifier = ledgerInfo.verifier
        cp = ledgerInfo.catchUpTill
        finalSize = getattr(cp, f.SEQ_NO_END.nm)
        finalMTH = getattr(cp, f.NEW_MERKLE_ROOT.nm)
        try:
            logger.debug("{} verifying proof for {}, {}, {}, {}, {}".format(
                self, tempTree.tree_size, finalSize, tempTree.root_hash,
                Ledger.strToHash(finalMTH),
                [Ledger.strToHash(p) for p in proof]))
            verified = verifier.verify_tree_consistency(
                tempTree.tree_size, finalSize, tempTree.root_hash,
                Ledger.strToHash(finalMTH),
                [Ledger.strToHash(p) for p in proof])
        except Exception as ex:
            logger.info("{} could not verify catchup reply {} since {}".format(
                self, catchupReply, ex))
            verified = False
        return bool(verified), nodeName, len(txns)