コード例 #1
0
def test_new_view_message_is_not_sent_by_non_primary_when_view_change_certificate_is_reached(
        internal_bus, external_bus, validators, primary,
        view_change_service_builder, initial_view_no, some_item, is_master):
    # TODO: Need to decide on how we handle this case
    if not is_master:
        return

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

    # start view change
    internal_bus.send(NeedViewChange())
    external_bus.sent_messages.clear()

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    vc = create_view_change(initial_view_no)
    for vc_frm in non_primaries:
        external_bus.process_incoming(
            vc, generateName(vc_frm, service._data.inst_id))
        for ack, ack_frm in create_view_change_acks(vc, vc_frm, non_primaries):
            external_bus.process_incoming(
                ack, generateName(ack_frm, service._data.inst_id))

    # check that NewView hasn't been sent
    assert all(not isinstance(msg, NewView)
               for msg in external_bus.sent_messages)
コード例 #2
0
def test_new_view_message_is_sent_by_primary_when_view_change_certificate_is_reached(
        internal_bus, external_bus, validators, primary,
        view_change_service_builder, initial_view_no, view_change_acks,
        is_master):
    # TODO: Need to decide on how we handle this case
    if not is_master:
        return

    primary_name = primary(initial_view_no + 1)
    service = view_change_service_builder(primary_name)

    # start view change
    internal_bus.send(NeedViewChange())
    external_bus.sent_messages.clear()

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    vc = create_view_change(initial_view_no)

    for vc_frm in non_primaries:
        external_bus.process_incoming(
            vc, generateName(vc_frm, service._data.inst_id))
        for ack, ack_frm in view_change_acks(vc, vc_frm, primary_name,
                                             len(validators) - 2):
            external_bus.process_incoming(
                ack, generateName(ack_frm, service._data.inst_id))

    # check that NewView has been sent
    assert len(external_bus.sent_messages) == 1
    msg, dst = external_bus.sent_messages[0]
    assert dst is None  # message was broadcast
    assert isinstance(msg, NewView)
    assert msg.viewNo == initial_view_no + 1
コード例 #3
0
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)
コード例 #4
0
def test_new_view_message_is_sent_by_primary_when_view_change_certificate_is_reached(
        internal_bus, validators, primary, view_change_service_builder,
        initial_view_no, view_change_acks):
    primary_name = primary(initial_view_no + 1)
    service = view_change_service_builder(primary_name)

    # start view change
    internal_bus.send(NeedViewChange())
    service._network.sent_messages.clear()

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    vc = create_view_change(initial_view_no)
    for vc_frm in non_primaries:
        service._network.process_incoming(vc, vc_frm)
        for ack, ack_frm in view_change_acks(vc, vc_frm, primary_name,
                                             len(validators) - 2):
            service._network.process_incoming(ack, ack_frm)

    # check that NewView has been sent
    assert len(service._network.sent_messages) == 1
    msg, dst = service._network.sent_messages[0]
    assert dst is None  # message was broadcast
    assert isinstance(msg, NewView)
    assert msg.viewNo == initial_view_no + 1
コード例 #5
0
def test_view_change_finished_is_sent_by_non_primary_once_view_change_certificate_is_reached_and_new_view_from_primary(
        internal_bus, external_bus, validators, primary,
        view_change_service_builder, initial_view_no, some_item, is_master):
    # TODO: Need to decide on how we handle this case
    if not is_master:
        return

    handler = Mock()
    internal_bus.subscribe(NewViewAccepted, handler)

    next_view_no = initial_view_no + 1
    primary_name = primary(next_view_no)
    non_primary_name = some_item(validators, exclude=[primary_name])
    service = view_change_service_builder(non_primary_name)
    vc = create_view_change(initial_view_no)
    service._data.preprepared = vc.preprepared
    service._data.prepared = vc.prepared
    service._data.stable_checkpoint = vc.stableCheckpoint
    service._data.checkpoints = vc.checkpoints
    old_data = copy_shared_data(service._data)

    # start view change
    internal_bus.send(NeedViewChange())
    external_bus.sent_messages.clear()

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    non_primaries = random.sample(non_primaries,
                                  service._data.quorums.view_change.value)
    new_view = create_new_view_from_vc(vc, non_primaries)
    for vc_frm in non_primaries:
        external_bus.process_incoming(
            vc, generateName(vc_frm, service._data.inst_id))
        for ack, ack_frm in create_view_change_acks(vc, vc_frm, non_primaries):
            external_bus.process_incoming(
                ack, generateName(ack_frm, service._data.inst_id))

        # check that NewViewAccepted hasn't been sent if NewView is from non-primary
        external_bus.process_incoming(
            new_view, generateName(non_primary_name, service._data.inst_id))
    handler.assert_not_called()
    assert service._data.view_no == initial_view_no + 1
    assert service._data.waiting_for_new_view

    # check that NewViewAccepted has been sent if NewView is from primary
    external_bus.process_incoming(
        new_view, generateName(primary_name, service._data.inst_id))
    expected_finish_vc = NewViewAccepted(view_no=initial_view_no + 1,
                                         view_changes=new_view.viewChanges,
                                         checkpoint=new_view.checkpoint,
                                         batches=new_view.batches)
    handler.assert_called_with(expected_finish_vc)

    # check that shared data is updated
    new_data = copy_shared_data(service._data)
    check_service_changed_only_owned_fields_in_shared_data(
        ViewChangeService, old_data, new_data)
    assert service._data.view_no == initial_view_no + 1
    assert not service._data.waiting_for_new_view
コード例 #6
0
def test_view_change_digest_is_256_bit_hexdigest(random):
    digest = view_change_digest(
        create_view_change(initial_view_no=0,
                           stable_cp=random.integer(0, 10000),
                           batches=create_batches(view_no=0)))
    assert isinstance(digest, str)
    assert len(digest) == 64
    assert all(v in string.hexdigits for v in digest)
コード例 #7
0
def test_different_view_change_messages_have_different_digests(random):
    batches = create_batches(view_no=0)
    assert view_change_digest(create_view_change(initial_view_no=0, stable_cp=100, batches=batches)) != \
           view_change_digest(create_view_change(initial_view_no=1, stable_cp=100, batches=batches))
    assert view_change_digest(create_view_change(initial_view_no=1, stable_cp=100, batches=batches)) != \
           view_change_digest(create_view_change(initial_view_no=1, stable_cp=101, batches=batches))
    assert view_change_digest(
        create_view_change(initial_view_no=1, stable_cp=100, batches=create_batches(view_no=0))) != \
           view_change_digest(create_view_change(initial_view_no=1, stable_cp=100, batches=create_batches(view_no=1)))
    assert view_change_digest(create_view_change(initial_view_no=0, stable_cp=100, batches=batches)) == \
           view_change_digest(create_view_change(initial_view_no=0, stable_cp=100, batches=batches))
コード例 #8
0
def test_primary_doesnt_respond_to_view_change_message(
        some_item, validators, primary, view_change_service_builder,
        initial_view_no, view_change_message):
    name = primary(initial_view_no + 1)
    service = view_change_service_builder(name)

    vc = create_view_change(initial_view_no)
    frm = some_item(validators, exclude=[name])
    service._network.process_incoming(vc, frm)

    assert len(service._network.sent_messages) == 0
コード例 #9
0
def test_send_instance_change_on_new_view_with_incorrect_checkpoint(
        internal_bus, external_bus, validators, primary,
        view_change_service_builder, initial_view_no, some_item, is_master):
    # TODO: Need to decide on how we handle this case
    if not is_master:
        return

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

    vc = create_view_change(initial_view_no)
    service._data.preprepared = vc.preprepared
    service._data.prepared = vc.prepared
    service._data.stable_checkpoint = vc.stableCheckpoint
    service._data.checkpoints = vc.checkpoints

    # start view change
    internal_bus.send(NeedViewChange())
    external_bus.sent_messages.clear()

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    non_primaries = random.sample(non_primaries,
                                  service._data.quorums.view_change.value)
    for vc_frm in non_primaries:
        external_bus.process_incoming(
            vc, generateName(vc_frm, service._data.inst_id))
        for ack, ack_frm in create_view_change_acks(vc, vc_frm, non_primaries):
            external_bus.process_incoming(
                ack, generateName(ack_frm, service._data.inst_id))

    cp = Checkpoint(instId=0,
                    viewNo=initial_view_no,
                    seqNoStart=0,
                    seqNoEnd=1000,
                    digest=cp_digest(1000))
    new_view = create_new_view_from_vc(vc, non_primaries, checkpoint=cp)

    # send NewView by Primary
    init_network_msg_count = len(external_bus.sent_messages)
    external_bus.process_incoming(
        new_view, generateName(primary_name, service._data.inst_id))

    # we don't go to new view, just send Instance Change
    assert service._data.view_no == initial_view_no + 1
    assert init_network_msg_count + 1 == len(external_bus.sent_messages)
    msg, dst = external_bus.sent_messages[-1]
    assert dst is None  # broadcast
    assert isinstance(msg, InstanceChange)
    assert msg.viewNo == initial_view_no + 2
    assert msg.reason == Suspicions.NEW_VIEW_INVALID_CHECKPOINTS.code
コード例 #10
0
def test_primary_doesnt_respond_to_view_change_message(
        some_item, validators, primary, external_bus, view_change_service_builder, initial_view_no,
        view_change_message, is_master):
    # TODO: Need to decide on how we handle this case
    if not is_master:
        return

    name = primary(initial_view_no + 1)
    service = view_change_service_builder(name)

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

    assert len(external_bus.sent_messages) == 0
コード例 #11
0
def test_do_not_send_instance_change_on_timeout_when_multiple_view_change_finished_on_time(internal_bus, external_bus,
                                                                                           validators,
                                                                                           primary,
                                                                                           view_change_service_builder,
                                                                                           timer,
                                                                                           initial_view_no,
                                                                                           is_master):
    # TODO: Need to decide on how we handle this case
    if not is_master:
        return

    primary_name = primary(initial_view_no + 2)
    service = view_change_service_builder(primary_name)

    # start first view change
    internal_bus.send(NeedViewChange())

    # start second view change
    internal_bus.send(NeedViewChange())
    external_bus.sent_messages.clear()

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    vc = create_view_change(initial_view_no + 1)
    service._data.checkpoints.append(Checkpoint(instId=0,
                                                viewNo=initial_view_no + 1,
                                                seqNoStart=0,
                                                seqNoEnd=DEFAULT_STABLE_CHKP,
                                                digest=cp_digest(DEFAULT_STABLE_CHKP)))
    for vc_frm in non_primaries:
        external_bus.process_incoming(vc, generateName(vc_frm, service._data.inst_id))
        for ack, ack_frm in create_view_change_acks(vc, vc_frm, non_primaries):
            external_bus.process_incoming(ack, generateName(ack_frm, service._data.inst_id))

    # check that view change is finished
    assert service._data.view_no == initial_view_no + 2
    assert not service._data.waiting_for_new_view
    assert len(external_bus.sent_messages) == 1
    msg, dst = external_bus.sent_messages[0]
    assert isinstance(msg, NewView)

    # make sure view change hasn't been started again
    timer.sleep(service._config.NEW_VIEW_TIMEOUT + 1)
    assert service._data.view_no == initial_view_no + 2
    assert len(external_bus.sent_messages) == 1
    msg, dst = external_bus.sent_messages[0]
    assert isinstance(msg, NewView)
コード例 #12
0
def test_new_view_incorrect_checkpoint(internal_bus, validators, primary,
                                       view_change_service_builder,
                                       initial_view_no, some_item):
    next_view_no = initial_view_no + 1
    primary_name = primary(next_view_no)
    non_primary_name = some_item(validators, exclude=[primary_name])
    service = view_change_service_builder(non_primary_name)

    vc = create_view_change(initial_view_no)
    service._data.preprepared = vc.preprepared
    service._data.prepared = vc.prepared
    service._data.stable_checkpoint = vc.stableCheckpoint
    service._data.checkpoints = vc.checkpoints

    # start view change
    internal_bus.send(NeedViewChange())
    service._network.sent_messages.clear()

    handler = Mock()
    internal_bus.subscribe(NeedViewChange, handler)

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    non_primaries = random.sample(non_primaries,
                                  service._data.quorums.view_change.value)
    for vc_frm in non_primaries:
        service._network.process_incoming(vc, vc_frm)
        for ack, ack_frm in create_view_change_acks(vc, vc_frm, non_primaries):
            service._network.process_incoming(ack, ack_frm)

    cp = Checkpoint(instId=0,
                    viewNo=initial_view_no,
                    seqNoStart=0,
                    seqNoEnd=1000,
                    digest=cp_digest(1000))
    new_view = create_new_view_from_vc(vc, non_primaries, checkpoint=cp)

    # send NewView by Primary
    service._network.process_incoming(new_view, primary_name)

    # make sure that NeedViewChange is called
    handler.assert_called_with(NeedViewChange())

    # make sure that we get to the next view
    assert service._data.view_no == initial_view_no + 2
    assert service._data.waiting_for_new_view
コード例 #13
0
def test_non_primary_responds_to_view_change_message_with_view_change_ack_to_new_primary(
        internal_bus, some_item, other_item, validators, primary,
        view_change_service_builder, initial_view_no):
    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())
    service._network.sent_messages.clear()

    vc = create_view_change(initial_view_no)
    frm = other_item(validators, exclude=[non_primary_name])
    service._network.process_incoming(vc, frm)

    assert len(service._network.sent_messages) == 1
    msg, dst = service._network.sent_messages[0]
    assert dst == service._data.primary_name
    assert isinstance(msg, ViewChangeAck)
    assert msg.viewNo == vc.viewNo
    assert msg.name == frm
    assert msg.digest == view_change_digest(vc)
コード例 #14
0
def test_new_view_from_malicious(view_change_service_builder, primary, initial_view_no, validators):
    """
    This test shows situation, when there is quorum of correct NEW_VIEW msgs
    and NEW_VIEW msg from malicious primary.
    In this case, view_change will be completed by quorum of the same NEW_VIEW msgs
    not by NEW_VIEW from malicious
    """

    proposed_view_no = initial_view_no + 1
    primary_name = primary(proposed_view_no)
    without_primary = [v for v in validators if v != primary_name]
    vcs_name = without_primary[0]

    vcs = view_change_service_builder(vcs_name)
    vcs._data.is_master = True
    vcs.process_need_view_change(NeedViewChange(view_no=proposed_view_no))

    vc_not_malicious = vcs.view_change_votes._get_vote(vcs_name).view_change
    not_malicious_nv = create_new_view_from_vc(vc_not_malicious, without_primary, checkpoint=vc_not_malicious.checkpoints[-1])

    vc_from_malicious = create_view_change(initial_view_no, stable_cp=20, batches=[])

    for i in range(0, len(without_primary)):
        vcs.view_change_votes.add_view_change(vc_not_malicious, without_primary[i])
        vcs._data.new_view_votes.add_new_view(not_malicious_nv, without_primary[i])

    vcs.view_change_votes.add_view_change(vc_from_malicious, primary_name)

    malicious_nv = NewView(viewNo=proposed_view_no,
                           viewChanges=[[primary_name, view_change_digest(vc_from_malicious)]],
                           checkpoint=Checkpoint(instId=0,
                                                 viewNo=initial_view_no,
                                                 seqNoStart=10,
                                                 seqNoEnd=20,
                                                 digest=cp_digest(20)),
                           batches=[])

    vcs.process_new_view_message(malicious_nv, "{}:{}".format(primary_name, 0))
    assert not vcs._data.waiting_for_new_view
コード例 #15
0
def test_view_change_finished_is_sent_by_primary_once_view_change_certificate_is_reached(
        internal_bus, validators, primary, view_change_service_builder,
        initial_view_no):
    handler = Mock()
    internal_bus.subscribe(NewViewAccepted, handler)

    primary_name = primary(initial_view_no + 1)
    service = view_change_service_builder(primary_name)

    # start view change
    internal_bus.send(NeedViewChange())
    service._network.sent_messages.clear()
    old_data = copy_shared_data(service._data)

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    non_primaries = random.sample(non_primaries,
                                  service._data.quorums.view_change.value)
    vc = create_view_change(initial_view_no)
    new_view = create_new_view_from_vc(vc, non_primaries)
    for vc_frm in non_primaries:
        service._network.process_incoming(vc, vc_frm)
        for ack, ack_frm in create_view_change_acks(vc, vc_frm, non_primaries):
            service._network.process_incoming(ack, ack_frm)

    # check that NewViewAccepted has been sent
    expected_finish_vc = NewViewAccepted(view_no=initial_view_no + 1,
                                         view_changes=new_view.viewChanges,
                                         checkpoint=new_view.checkpoint,
                                         batches=new_view.batches)
    handler.assert_called_with(expected_finish_vc)

    # check that shared data is updated
    new_data = copy_shared_data(service._data)
    check_service_changed_only_owned_fields_in_shared_data(
        ViewChangeService, old_data, new_data)
    assert service._data.view_no == initial_view_no + 1
    assert not service._data.waiting_for_new_view
コード例 #16
0
def test_new_view_message_is_not_sent_by_non_primary_when_view_change_certificate_is_reached(
        internal_bus, validators, primary, view_change_service_builder,
        initial_view_no, some_item):
    next_view_no = initial_view_no + 1
    primary_name = primary(next_view_no)
    non_primary_name = some_item(validators, exclude=[primary_name])
    service = view_change_service_builder(non_primary_name)

    # start view change
    internal_bus.send(NeedViewChange())
    service._network.sent_messages.clear()

    # receive quorum of ViewChanges and ViewChangeAcks
    non_primaries = [item for item in validators if item != primary_name]
    vc = create_view_change(initial_view_no)
    for vc_frm in non_primaries:
        service._network.process_incoming(vc, vc_frm)

        for ack, ack_frm in create_view_change_acks(vc, vc_frm, non_primaries):
            service._network.process_incoming(ack, ack_frm)

    # check that NewView hasn't been sent
    assert all(not isinstance(msg, NewView)
               for msg in service._network.sent_messages)
コード例 #17
0
def view_change_message(data):
    return create_view_change(data.view_no)