예제 #1
0
    def _try_asking_for_cons_proofs_without_timeout(self):
        if self._already_asked_for_cons_proofs_without_timeout:
            return

        if len(self._cons_proofs) < self._quorum.n - self._quorum.f - 1:
            return

        sizes = [
            proof.seqNoEnd if proof else self._ledger.size
            for proof in self._cons_proofs.values()
        ]
        sizes.sort(reverse=True)

        start = self._ledger.size
        end = sizes[self._quorum.f]  # This is actually f+1's reply
        if start >= end:
            logger.info(
                "{} not asking for equal cons proofs because "
                "it appears that less than f+1 nodes have more transactions".
                format(self))
            return

        logger.info("{} asking for consistency proof request: {}".format(
            self, self._ledger_id, start, end))
        cons_proof_req = MessageReq(
            CONSISTENCY_PROOF, {
                f.LEDGER_ID.nm: self._ledger_id,
                f.SEQ_NO_START.nm: start,
                f.SEQ_NO_END.nm: end
            })
        self._provider.send_to_nodes(cons_proof_req,
                                     nodes=self._provider.eligible_nodes())
        self._already_asked_for_cons_proofs_without_timeout = True
def test_process_message_req_new_view_by_non_primary(message_req_service: MessageReqService,
                                                     external_bus, data: ConsensusSharedData,
                                                     new_view_message: NewView):
    frm = "frm"
    data.primary_name = "a" + data.name
    data.new_view_votes.add_new_view(new_view_message, data.primary_name)
    message_req = MessageReq(**{
        f.MSG_TYPE.nm: NEW_VIEW,
        f.PARAMS.nm: {f.INST_ID.nm: data.inst_id,
                      f.VIEW_NO.nm: data.view_no},
    })
    external_bus.process_incoming(message_req, frm)
    assert len(external_bus.sent_messages) == 1
def test_process_message_req_preprepare_without_preprepare(message_req_service: MessageReqService,
                                                           external_bus, data, pp):
    key = (pp.viewNo, pp.ppSeqNo)
    data.sent_preprepares.pop(key)
    message_req = MessageReq(**{
        f.MSG_TYPE.nm: PREPREPARE,
        f.PARAMS.nm: {f.INST_ID.nm: data.inst_id,
                      f.VIEW_NO.nm: key[0],
                      f.PP_SEQ_NO.nm: key[1]},
    })
    frm = "frm"
    message_req_service.process_message_req(message_req, frm)
    assert len(external_bus.sent_messages) == 0
def test_process_message_req_incorrect_inst_id(
        message_req_service: MessageReqService, external_bus, data):
    key = (data.view_no, 1)
    message_req = MessageReq(
        **{
            f.MSG_TYPE.nm: PREPREPARE,
            f.PARAMS.nm: {
                f.INST_ID.nm: data.inst_id + 1,
                f.VIEW_NO.nm: key[0],
                f.PP_SEQ_NO.nm: key[1]
            },
        })
    message_req_service.process_message_req(message_req, "frm")
    assert len(external_bus.sent_messages) == 0
예제 #5
0
def test_process_message_req_commit(message_req_service: MessageReqService, external_bus, data, commit):
    key = (commit.viewNo, commit.ppSeqNo)
    message_req = MessageReq(**{
        f.MSG_TYPE.nm: COMMIT,
        f.PARAMS.nm: {f.INST_ID.nm: data.inst_id,
                      f.VIEW_NO.nm: key[0],
                      f.PP_SEQ_NO.nm: key[1]},
    })
    frm = "frm"
    message_req_service.process_message_req(message_req, frm)
    assert len(external_bus.sent_messages) == 1
    assert external_bus.sent_messages[0] == (MessageRep(message_req.msg_type,
                                                        message_req.params,
                                                        data.commits[key].msg),
                                             [frm])
def test_process_missing_message_new_view(message_req_service: MessageReqService, external_bus, data,
                                          internal_bus, new_view_message: NewView):
    primary = data.primary_name
    inst_id = data.inst_id
    missing_msg = MissingMessage(msg_type=NEW_VIEW,
                                 key=data.view_no,
                                 inst_id=inst_id,
                                 dst=[primary],
                                 stash_data=None)
    internal_bus.send(missing_msg)
    assert len(external_bus.sent_messages) == 1
    assert external_bus.sent_messages[0] == (MessageReq(NEW_VIEW,
                                                        {f.INST_ID.nm: inst_id,
                                                         f.VIEW_NO.nm: data.view_no}),
                                             [primary])
def test_process_message_req_preprepare(message_req_service: MessageReqService, external_bus, data, pp):
    key = (pp.viewNo, pp.ppSeqNo)
    message_req = MessageReq(**{
        f.MSG_TYPE.nm: PREPREPARE,
        f.PARAMS.nm: {f.INST_ID.nm: data.inst_id,
                      f.VIEW_NO.nm: key[0],
                      f.PP_SEQ_NO.nm: key[1]},
    })
    frm = "frm"
    message_req_service.process_message_req(message_req, frm)
    assert len(external_bus.sent_messages) == 1
    assert external_bus.sent_messages[0] == (MessageRep(message_req.msg_type,
                                                        message_req.params,
                                                        data.sent_preprepares[key]),
                                             [frm])
def test_process_message_req_with_incorrect_type(
        message_req_service: MessageReqService, external_bus, data, pp):
    msg_type = LEDGER_STATUS
    key = (data.view_no, 1)
    message_req = MessageReq(
        **{
            f.MSG_TYPE.nm: msg_type,
            f.PARAMS.nm: {
                f.INST_ID.nm: data.inst_id,
                f.VIEW_NO.nm: key[0],
                f.PP_SEQ_NO.nm: key[1]
            },
        })
    message_req_service.process_message_req(message_req, "frm")
    assert len(external_bus.sent_messages) == 0
예제 #9
0
def test_process_missing_message_commit(message_req_service: MessageReqService, external_bus, data):
    frm = "frm"
    view_no = data.view_no
    pp_seq_no = data.last_ordered_3pc[1] + 1
    missing_msg = MissingMessage(msg_type=COMMIT,
                                    key=(view_no, pp_seq_no),
                                    inst_id=data.inst_id,
                                    dst=[frm],
                                    stash_data=None)
    message_req_service.process_missing_message(missing_msg)
    assert len(external_bus.sent_messages) == 1
    assert external_bus.sent_messages[0] == (MessageReq(COMMIT,
                                                        {f.INST_ID.nm: data.inst_id,
                                                         f.VIEW_NO.nm: view_no,
                                                         f.PP_SEQ_NO.nm: pp_seq_no}),
                                             [frm])
예제 #10
0
def test_process_message_req_commit_without_commit(message_req_service: MessageReqService, external_bus, data, commit):
    key = (commit.viewNo, commit.ppSeqNo)
    other_node_name = "other_node"
    data.commits.clear()
    data.commits.addVote(commit, other_node_name)
    assert not data.commits.hasCommitFrom(commit, data.name)
    assert data.commits.hasCommitFrom(commit, other_node_name)

    message_req = MessageReq(**{
        f.MSG_TYPE.nm: COMMIT,
        f.PARAMS.nm: {f.INST_ID.nm: data.inst_id,
                      f.VIEW_NO.nm: key[0],
                      f.PP_SEQ_NO.nm: key[1]},
    })
    frm = "frm"
    message_req_service.process_message_req(message_req, frm)
    assert len(external_bus.sent_messages) == 0
def test_process_message_req_handler_raise_ex(
        message_req_service: MessageReqService, external_bus, data):
    msg_type = PREPREPARE
    key = (data.view_no, 1)
    message_req = MessageReq(
        **{
            f.MSG_TYPE.nm: msg_type,
            f.PARAMS.nm: {
                f.INST_ID.nm: data.inst_id,
                f.VIEW_NO.nm: key[0],
                f.PP_SEQ_NO.nm: key[1]
            },
        })

    message_req_service.handlers[
        msg_type].process_message_req = lambda msg: raise_ex()
    message_req_service.process_message_req(message_req, "frm")
    assert len(external_bus.sent_messages) == 0
def test_process_missing_message_view_change(message_req_service: MessageReqService, external_bus, data,
                                             internal_bus, view_change_message: ViewChange):
    frm = "frm"
    confused_node = "confused_node"
    inst_id = data.inst_id
    digest = view_change_digest(view_change_message)
    missing_msg = MissingMessage(msg_type=VIEW_CHANGE,
                                 key=(frm, digest),
                                 inst_id=inst_id,
                                 dst=[confused_node],
                                 stash_data=None)
    internal_bus.send(missing_msg)
    assert len(external_bus.sent_messages) == 1
    assert external_bus.sent_messages[0] == (MessageReq(VIEW_CHANGE,
                                                        {f.INST_ID.nm: inst_id,
                                                         f.DIGEST.nm: digest,
                                                         f.NAME.nm: frm}),
                                             [confused_node])
def test_process_message_req_new_view(message_req_service: MessageReqService,
                                      external_bus, data: ConsensusSharedData,
                                      new_view_message: NewView):
    frm = "frm"
    data.primary_name = data.name
    data.new_view_votes.add_new_view(new_view_message, data.primary_name)
    message_req = MessageReq(**{
        f.MSG_TYPE.nm: NEW_VIEW,
        f.PARAMS.nm: {f.INST_ID.nm: data.inst_id,
                      f.VIEW_NO.nm: data.view_no},
    })
    external_bus.process_incoming(message_req, frm)
    assert len(external_bus.sent_messages) == 1

    assert external_bus.sent_messages[0] == (MessageRep(message_req.msg_type,
                                                        message_req.params,
                                                        new_view_message._asdict()),
                                             [frm])
def test_process_message_req_view_change(message_req_service: MessageReqService,
                                         external_bus, data: ConsensusSharedData,
                                         view_change_message: ViewChange):
    frm = "frm"
    digest = view_change_digest(view_change_message)
    message_req = MessageReq(**{
        f.MSG_TYPE.nm: VIEW_CHANGE,
        f.PARAMS.nm: {f.INST_ID.nm: data.inst_id,
                      f.DIGEST.nm: digest,
                      f.NAME.nm: frm},
    })
    data.view_change_votes.add_view_change(view_change_message, frm)
    external_bus.process_incoming(message_req, frm)
    assert len(external_bus.sent_messages) == 1

    assert external_bus.sent_messages[0] == (MessageRep(message_req.msg_type,
                                                        message_req.params,
                                                        view_change_message._asdict()),
                                             [frm])
예제 #15
0
    def process_missing_message(self, msg: MissingMessage):
        if msg.inst_id != self._data.inst_id:
            return
        # TODO: Using a timer to retry would be a better thing to do
        self._logger.trace('{} requesting {} for {} from {}'.format(
            self, msg.msg_type, msg.key, msg.dst))
        handler = self.handlers[msg.msg_type]

        try:
            params = handler.prepare_msg_to_request(msg.key, msg.stash_data)
        except IncorrectMessageForHandlingException as e:
            self.discard(e.msg, e.reason, e.log_method)
            return
        if params:
            self._network.send(
                MessageReq(**{
                    f.MSG_TYPE.nm: msg.msg_type,
                    f.PARAMS.nm: params
                }),
                dst=msg.dst)
예제 #16
0
def test_process_message_req_prepare_without_prepare(
        message_req_service: MessageReqService, external_bus, data, prepare):
    key = (prepare.viewNo, prepare.ppSeqNo)
    other_node_name = "other_node"
    data.prepares.clear()
    data.prepares.addVote(prepare, other_node_name)
    assert not data.prepares.hasPrepareFrom(prepare, data.name)
    assert data.prepares.hasPrepareFrom(prepare, other_node_name)

    message_req = MessageReq(
        **{
            f.MSG_TYPE.nm: PREPARE,
            f.PARAMS.nm: {
                f.INST_ID.nm: data.inst_id,
                f.VIEW_NO.nm: key[0],
                f.PP_SEQ_NO.nm: key[1]
            },
        })
    frm = "frm"
    message_req_service.process_message_req(message_req, frm)
    assert len(external_bus.sent_messages) == 0
예제 #17
0
    def _request_CPs_if_needed(self):
        if not self._is_working:
            return

        proofs = self._cons_proofs
        # there is no any received ConsistencyProofs
        if not proofs:
            return

        logger.info(
            "{} requesting consistency proofs after timeout".format(self))

        if not self._is_catchup_needed():
            return

        grouped_proofs, null_proofs_count = self._get_group_consistency_proofs(
            proofs)
        if self._quorum.ledger_status.is_reached(null_proofs_count) \
                or len(grouped_proofs) == 0:
            return

        if self._get_latest_reliable_proof(grouped_proofs):
            return

        with self.metrics.measure_time(MetricsName.SEND_MESSAGE_REQ_TIME):
            start, end = self._get_consistency_proof_request_params(
                grouped_proofs)
            logger.info("{} sending consistency proof request: {}".format(
                self, self._ledger_id, start, end))
            cons_proof_req = MessageReq(
                CONSISTENCY_PROOF, {
                    f.LEDGER_ID.nm: self._ledger_id,
                    f.SEQ_NO_START.nm: start,
                    f.SEQ_NO_END.nm: end
                })
            self._provider.send_to_nodes(cons_proof_req,
                                         nodes=self._provider.eligible_nodes())
예제 #18
0
 def request_msg(self, typ, params: Dict, frm: List[str] = None):
     self.sendToNodes(MessageReq(**{
         f.MSG_TYPE.nm: typ,
         f.PARAMS.nm: params
     }), names=frm)
예제 #19
0
 def _request_ledger_status_from_nodes(self, nodes=None):
     logger.info("{} asking for ledger status of ledger {}".format(
         self, self._ledger_id))
     ledger_status_req = MessageReq(LEDGER_STATUS,
                                    {f.LEDGER_ID.nm: self._ledger_id})
     self._provider.send_to_nodes(ledger_status_req, nodes=nodes)