def _finish(self, cons_proof: Optional[ConsistencyProof] = None):
        logger.info("{} finished with consistency proof {}".format(
            self, cons_proof))

        till = CatchupTill(
            start_size=cons_proof.seqNoStart,
            final_size=cons_proof.seqNoEnd,
            final_hash=cons_proof.newMerkleRoot) if cons_proof else None

        nodes_ledger_sizes = {
            frm: proof.seqNoEnd
            for frm, proof in self._cons_proofs.items() if proof is not None
        }

        # Stop requesting last consistency proofs and ledger statuses.
        self._is_working = False
        self._same_ledger_status = set()
        self._cons_proofs = {}

        self._cancel_reask()

        self._output.put_nowait(
            LedgerCatchupStart(ledger_id=self._ledger_id,
                               catchup_till=till,
                               nodes_ledger_sizes=nodes_ledger_sizes))
def _add_txns_to_ledger(node, looper, sdk_wallet_client, num_txns_in_reply, reply_count):
    '''
    Add txn_count transactions to node's ledger and return
    ConsistencyProof for all new transactions and list of CatchupReplies
    :return: ConsistencyProof, list of CatchupReplies
    '''
    txn_count = num_txns_in_reply * reply_count
    ledger_manager = node.ledgerManager
    ledger = ledger_manager.ledgerRegistry[ledger_id].ledger
    catchup_rep_service = ledger_manager._node_leecher._leechers[ledger_id]._catchup_rep_service
    reqs = sdk_signed_random_requests(looper, sdk_wallet_client, txn_count)
    # add transactions to ledger
    for req in reqs:
        txn = append_txn_metadata(reqToTxn(req), txn_time=12345678)
        catchup_rep_service._add_txn(txn)
    # generate CatchupReps
    replies = []
    for i in range(ledger.seqNo - txn_count + 1, ledger.seqNo + 1, num_txns_in_reply):
        start = i
        end = i + num_txns_in_reply - 1
        cons_proof = ledger_manager._node_seeder._make_consistency_proof(ledger, end, ledger.size)
        txns = {}
        for seq_no, txn in ledger.getAllTxn(start, end):
            txns[str(seq_no)] = ledger_manager.owner.update_txn_with_extra_data(txn)
        replies.append(CatchupRep(ledger_id,
                                  SortedDict(txns),
                                  cons_proof))

    three_pc_key = node.three_phase_key_for_txn_seq_no(ledger_id, ledger.seqNo)
    view_no, pp_seq_no = three_pc_key if three_pc_key else (0, 0)
    return CatchupTill(start_size=ledger.seqNo - txn_count,
                       final_size=ledger.seqNo,
                       final_hash=Ledger.hashToStr(ledger.tree.merkle_tree_hash(0, ledger.seqNo)),
                       view_no=view_no,
                       pp_seq_no=pp_seq_no), replies
Exemple #3
0
def test_missing_txn_request(ledger_no_genesis):
    """
    Testing LedgerManager's `_missing_txns`
    """
    ledger = ledger_no_genesis
    for i in range(20):
        txn = random_txn(i)
        ledger.add(txn)

    service = create_fake_catchup_rep_service(ledger)
    assert service._num_missing_txns() == 0

    # Ledger is already ahead
    ct = CatchupTill(start_size=1,
                     final_size=10,
                     final_hash='Gv9AdSeib9EnBakfpgkU79dPMtjcnFWXvXeiCX4QAgAC',
                     view_no=0,
                     pp_seq_no=0)
    service._catchup_till = ct
    service._received_catchup_txns = [(i, {}) for i in range(1, 15)]
    assert service._num_missing_txns() == 0

    # Ledger is behind but catchup replies present
    ct = CatchupTill(start_size=1,
                     final_size=30,
                     final_hash='EEUnqHf2GWEpvmibiXDCZbNDSpuRgqdvCpJjgp3KFbNC',
                     view_no=0,
                     pp_seq_no=0)
    service._catchup_till = ct
    service._received_catchup_txns = [(i, {}) for i in range(21, 31)]
    assert service._num_missing_txns() == 0
    service._received_catchup_txns = [(i, {}) for i in range(21, 35)]
    assert service._num_missing_txns() == 0

    # Ledger is behind
    ct = CatchupTill(start_size=1,
                     final_size=30,
                     final_hash='EEUnqHf2GWEpvmibiXDCZbNDSpuRgqdvCpJjgp3KFbNC',
                     view_no=0,
                     pp_seq_no=0)
    service._catchup_till = ct
    service._received_catchup_txns = [(i, {}) for i in range(21, 26)]
    assert service._num_missing_txns() == 5

    service._received_catchup_txns = [(i, {}) for i in range(26, 31)]
    assert service._num_missing_txns() == 5
Exemple #4
0
    def _calc_catchup_till(self) -> Dict[int, CatchupTill]:
        audit_ledger = self._provider.ledger(AUDIT_LEDGER_ID)
        last_audit_txn = audit_ledger.get_last_committed_txn()
        if last_audit_txn is None:
            return {}

        catchup_till = {}
        last_audit_txn = get_payload_data(last_audit_txn)
        for ledger_id, final_size in last_audit_txn[
                AUDIT_TXN_LEDGERS_SIZE].items():
            ledger = self._provider.ledger(ledger_id)
            if ledger is None:
                logger.debug(
                    "{} has audit ledger with references to nonexistent "
                    "ledger with ID {}. Maybe it was frozen.".format(
                        self, ledger_id))
                continue
            start_size = ledger.size

            final_hash = last_audit_txn[AUDIT_TXN_LEDGER_ROOT].get(ledger_id)
            if final_hash is None:
                if final_size != ledger.size:
                    logger.error(
                        "{} has corrupted audit ledger: "
                        "it indicates that ledger {} has new transactions but doesn't have new txn root"
                        .format(self, ledger_id))
                    return {}
                final_hash = Ledger.hashToStr(
                    ledger.tree.root_hash) if final_size > 0 else None

            if isinstance(final_hash, int):
                audit_txn = audit_ledger.getBySeqNo(audit_ledger.size -
                                                    final_hash)
                if audit_txn is None:
                    logger.error(
                        "{} has corrupted audit ledger: "
                        "its txn root for ledger {} references nonexistent txn with seq_no {} - {} = {}"
                        .format(self, ledger_id, audit_ledger.size, final_hash,
                                audit_ledger.size - final_hash))
                    return {}

                audit_txn = get_payload_data(audit_txn)
                final_hash = audit_txn[AUDIT_TXN_LEDGER_ROOT].get(ledger_id)
                if not isinstance(final_hash, str):
                    logger.error(
                        "{} has corrupted audit ledger: "
                        "its txn root for ledger {} references txn with seq_no {} - {} = {} "
                        "which doesn't contain txn root".format(
                            self, ledger_id, audit_ledger.size, final_hash,
                            audit_ledger.size - final_hash))
                    return {}

            catchup_till[ledger_id] = CatchupTill(start_size=start_size,
                                                  final_size=final_size,
                                                  final_hash=final_hash)

        return catchup_till
    def stop(self, cons_proof: Optional[ConsistencyProof] = None):
        # Stop requesting last consistency proofs and ledger statuses.
        self._is_working = False
        self._same_ledger_status = set()
        self._cons_proofs = {}
        self._requested_consistency_proof = set()

        self._cancel_reask()

        till = CatchupTill(
            start_size=cons_proof.seqNoStart,
            final_size=cons_proof.seqNoEnd,
            final_hash=cons_proof.newMerkleRoot,
            view_no=cons_proof.viewNo,
            pp_seq_no=cons_proof.ppSeqNo) if cons_proof else None
        self._output.put_nowait(
            LedgerCatchupStart(ledger_id=self._ledger_id, catchup_till=till))