Ejemplo n.º 1
0
    def process_view_change_message(self, msg: ViewChange, frm: str):
        result = self._validate(msg, frm)
        if result == STASH_WAITING_VIEW_CHANGE:
            self._stashed_vc_msgs.setdefault(msg.viewNo, 0)
            self._stashed_vc_msgs[msg.viewNo] += 1
            if self._data.quorums.view_change.is_reached(self._stashed_vc_msgs[msg.viewNo]) and \
                    not self._data.waiting_for_new_view:
                self._bus.send(StartViewChange(msg.viewNo))
        if result != PROCESS:
            return result, None

        self._logger.info("{} processing {} from {}".format(self, msg, frm))

        self.view_change_votes.add_view_change(msg, frm)

        vca = ViewChangeAck(viewNo=msg.viewNo,
                            name=getNodeName(frm),
                            digest=view_change_digest(msg))
        self.view_change_votes.add_view_change_ack(
            vca, getNodeName(self._data.name))

        if self._data.is_primary:
            self._send_new_view_if_needed()
            return PROCESS, None

        primary_node_name = getNodeName(self._data.primary_name)
        self._logger.info("{} sending {}".format(self, vca))
        self._network.send(vca, [primary_node_name])

        self._finish_view_change_if_needed()
        return PROCESS, None
Ejemplo n.º 2
0
    def process_view_change_message(self, msg: ViewChange, frm: str):
        result = self._validate(msg, frm)
        if result != PROCESS:
            return result, None

        self._logger.info("{} processing {} from {}".format(self, msg, frm))

        self.view_change_votes.add_view_change(msg, frm)

        vca = ViewChangeAck(viewNo=msg.viewNo,
                            name=getNodeName(frm),
                            digest=view_change_digest(msg))
        self.view_change_votes.add_view_change_ack(
            vca, getNodeName(self._data.name))

        if self._data.is_primary:
            self._send_new_view_if_needed()
            return PROCESS, None

        primary_node_name = getNodeName(self._data.primary_name)
        self._logger.info("{} sending {}".format(self, vca))
        self._network.send(vca, [primary_node_name])

        self._finish_view_change_if_needed()
        return PROCESS, None
def test_non_primary_responds_to_view_change_message_with_view_change_ack_to_new_primary(
        internal_bus, external_bus, some_item, other_item, validators, primary,
        view_change_service_builder, initial_view_no, is_master):
    # TODO: Need to decide on how we handle this case
    if not is_master:
        return

    next_view_no = initial_view_no + 1
    non_primary_name = some_item(validators, exclude=[primary(next_view_no)])
    service = view_change_service_builder(non_primary_name)

    internal_bus.send(NeedViewChange())
    external_bus.sent_messages.clear()

    vc = create_view_change(initial_view_no)
    frm = other_item(validators, exclude=[non_primary_name])
    external_bus.process_incoming(vc, generateName(frm, service._data.inst_id))

    assert len(external_bus.sent_messages) == 1
    msg, dst = external_bus.sent_messages[0]
    assert dst == [getNodeName(service._data.primary_name)]
    assert isinstance(msg, ViewChangeAck)
    assert msg.viewNo == vc.viewNo
    assert msg.name == frm
    assert msg.digest == view_change_digest(vc)
Ejemplo n.º 4
0
 def _request_new_view_message(self, view_no):
     self._bus.send(
         MissingMessage(msg_type=NEW_VIEW,
                        key=view_no,
                        inst_id=self._data.inst_id,
                        dst=[getNodeName(self._data.primary_name)],
                        stash_data=None))
Ejemplo n.º 5
0
    def _send_message(self, frm: str, msg: Any, dst: ExternalBus.Destination):
        if dst is None:
            dst = [name for name in self._peers if name != getNodeName(frm)]
        elif isinstance(dst, str):
            dst = [dst]
        elif isinstance(dst, Iterable):
            assert len(
                dst) > 0, "{} tried to send message {} to no one".format(
                    frm, msg)
        else:
            assert False, "{} tried to send message {} to unsupported destination {}".format(
                frm, msg, dst)

        for name in sorted(dst):
            assert name != frm, "{} tried to send message {} to itself".format(
                frm, msg)

            peer = self._peers.get(name)
            assert peer, "{} tried to send message {} to unknown peer {}".format(
                frm, msg, name)

            msg = self._serialize_deserialize(msg)

            if name in self._filters and type(msg) in self._filters[name]:
                self._logger.debug(
                    "Discard {} for {} because it filtered by SimNetwork".
                    format(msg, name))
                continue

            self._timer.schedule(
                self._random.integer(self._min_latency, self._max_latency),
                partial(peer.process_incoming, msg, frm))
Ejemplo n.º 6
0
def check_view_change_completes_under_normal_conditions(
        random: SimRandom, min_latency, max_latency, filtered_msg_types,
        filter_probability):
    # PREPARE

    # 1. Create random pool with random initial state
    pool, committed = some_pool(random)
    N = pool.size
    F = (N - 1) // 3

    # 2. set latency
    pool.network.set_latency(min_latency, max_latency)

    # 3. set filter
    pool.network.set_filter([getNodeName(pool.nodes[-1].name)],
                            filtered_msg_types, filter_probability)

    # EXECUTE

    # Schedule view change at different time on all nodes
    for node in pool.nodes:
        pool.timer.schedule(
            random.integer(0, 10000),
            partial(node._view_changer.process_need_view_change,
                    NeedViewChange()))

    # CHECK

    # 1. Make sure all nodes complete view change
    pool.timer.wait_for(lambda: all(not node._data.waiting_for_new_view and
                                    node._data.view_no > 0
                                    for node in pool.nodes))

    # 2. check that equal stable checkpoint is set on at least N-F nodes (F nodes may lag behind and will catchup)
    stable_checkpoints = [n._data.stable_checkpoint for n in pool.nodes]
    most_freq_stable_ckeckpoint = Counter(stable_checkpoints).most_common(1)
    stable_checkpoint = most_freq_stable_ckeckpoint[0][0]
    assert most_freq_stable_ckeckpoint[0][1] >= N - F

    # 3. check that equal preprepares is set on all node with the found stable checkpoint
    preprepares = set()
    for n in pool.nodes:
        if n._data.stable_checkpoint >= stable_checkpoint:
            preprepares.add(tuple(n._data.preprepared))
    assert len(preprepares) == 1

    # 4. Make sure all nodes end up in same view
    for node_a, node_b in zip(pool.nodes, pool.nodes[1:]):
        assert node_a._data.view_no == node_b._data.view_no
        assert node_a._data.primary_name == node_b._data.primary_name

    # 5. Make sure that all committed reqs are ordered with the same ppSeqNo in the new view:
    committed_above_cp = [
        c for c in committed if c.pp_seq_no > stable_checkpoint
    ]
    for n in pool.nodes:
        if n._data.stable_checkpoint >= stable_checkpoint:
            assert committed_above_cp == n._data.preprepared[:len(
                committed_above_cp)]
Ejemplo n.º 7
0
def setup_pool(random):
    pool = create_pool(random)

    for node in pool.nodes:
        # TODO: This propagates to global config and sometimes breaks other tests
        node._orderer._config.Max3PCBatchSize = MAX_BATCH_SIZE
        node._orderer._config.CHK_FREQ = 5
        node._orderer._config.LOG_SIZE = 3 * node._orderer._config.CHK_FREQ
        setup_consensus_data(node._data)
        node._orderer._network._connecteds = list(
            set(node._data.validators) - {getNodeName(node._data.name)})

    return pool
Ejemplo n.º 8
0
 def add_view_change_ack(self, msg: ViewChangeAck, frm: str) -> bool:
     """
     Adds view change ack and returns boolean indicating if it found node suspicios
     """
     frm = getNodeName(frm)
     return self._get_vote(msg.name).add_view_change_ack(msg, frm)
Ejemplo n.º 9
0
def set_filter(request, pool_committed):
    pool, committed = pool_committed
    pool.network.set_filter([getNodeName(pool.nodes[-1].name)],
                            request.param[0], request.param[1])