def test_handle_delayed_preprepares(looper, txnPoolNodeSet,
                                    sdk_wallet_client, sdk_pool_handle,
                                    teardown):
    """
    Make a node send PREPREPARE again after the slow node has ordered
    """
    slow_node, other_nodes, primary_node, other_non_primary_nodes = \
        split_nodes(txnPoolNodeSet)
    # This node will send PRE-PREPARE again
    orig_method = primary_node.handlers[PREPREPARE].serve

    last_pp = None

    def patched_method(self, msg):
        nonlocal last_pp
        last_pp = orig_method(msg)
        return last_pp

    primary_node.handlers[PREPREPARE].serve = types.MethodType(patched_method,
                                                               primary_node.handlers[
                                                                   PREPREPARE])
    # Delay PRE-PREPAREs by large amount simulating loss
    slow_node.nodeIbStasher.delay(ppDelay(300, 0))

    sdk_send_batches_of_random_and_check(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         num_reqs=10,
                                         num_batches=5)
    waitNodeDataEquality(looper, slow_node, *other_nodes)

    slow_master_replica = slow_node.master_replica
    count_pr_req = get_count(slow_master_replica,
                             slow_master_replica.process_requested_pre_prepare)

    count_pr_tpc = get_count(slow_master_replica,
                             slow_master_replica.processThreePhaseMsg)

    primary_node.sendToNodes(MessageRep(**{
        f.MSG_TYPE.nm: PREPREPARE,
        f.PARAMS.nm: {
            f.INST_ID.nm: last_pp.instId,
            f.VIEW_NO.nm: last_pp.viewNo,
            f.PP_SEQ_NO.nm: last_pp.ppSeqNo
        },
        f.MSG.nm: last_pp
    }), names=[slow_node.name, ])

    def chk():
        # `process_requested_pre_prepare` is called but
        # `processThreePhaseMsg` is not called
        assert get_count(
            slow_master_replica,
            slow_master_replica.process_requested_pre_prepare) > count_pr_req
        assert get_count(
            slow_master_replica,
            slow_master_replica.processThreePhaseMsg) == count_pr_tpc

    looper.run(eventually(chk, retryWait=1))
示例#2
0
def test_no_preprepare_requested(looper, txnPoolNodeSet, client1,
                                 wallet1, client1Connected, teardown):
    """
    Node missing Propagates hence request not finalised, hence stashes
    PRE-PREPARE but does not request PRE-PREPARE on receiving PREPARE
    """
    slow_node, other_nodes, _, _ = split_nodes(txnPoolNodeSet)
    slow_node.nodeIbStasher.delay(ppgDelay(20))
    slow_node.nodeIbStasher.delay(msg_rep_delay(20, [PROPAGATE, ]))

    old_count_resp = count_requested_preprepare_resp(slow_node)
    send_reqs_batches_and_get_suff_replies(looper, wallet1, client1, 4, 2)

    # The slow node is behind
    checkNodeDataForInequality(slow_node, *other_nodes)

    # PRE-PREPARE were not requested
    assert count_requested_preprepare_resp(slow_node) == old_count_resp

    slow_node.nodeIbStasher.reset_delays_and_process_delayeds()

    # The slow node has processed all requests
    waitNodeDataEquality(looper, slow_node, *other_nodes)

    # PRE-PREPARE were not requested
    assert count_requested_preprepare_resp(slow_node) == old_count_resp
def test_no_preprepare_requested(looper, txnPoolNodeSet, sdk_wallet_client,
                                 sdk_pool_handle, teardown):
    """
    Node missing Propagates hence request not finalised, hence stashes
    PRE-PREPARE but does not request PRE-PREPARE on receiving PREPARE
    """
    slow_node, other_nodes, _, _ = split_nodes(txnPoolNodeSet)
    slow_node.nodeIbStasher.delay(ppgDelay())
    slow_node.clientIbStasher.delay(req_delay())
    slow_node.nodeIbStasher.delay(msg_rep_delay(1000, [
        PROPAGATE,
    ]))

    old_count_resp = count_requested_preprepare_resp(slow_node)

    sdk_send_batches_of_random_and_check(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         num_reqs=4,
                                         num_batches=2)

    # The slow node is behind
    checkNodeDataForInequality(slow_node, *other_nodes)

    # PRE-PREPARE were not requested
    assert count_requested_preprepare_resp(slow_node) == old_count_resp

    slow_node.nodeIbStasher.reset_delays_and_process_delayeds()

    # The slow node has processed all requests
    waitNodeDataEquality(looper, slow_node, *other_nodes)

    # PRE-PREPARE were not requested
    assert count_requested_preprepare_resp(slow_node) == old_count_resp
def test_no_preprepare_requested(looper, txnPoolNodeSet,
                                 sdk_wallet_client, sdk_pool_handle,
                                 teardown):
    """
    Node missing Propagates hence request not finalised, hence stashes
    PRE-PREPARE but does not request PRE-PREPARE on receiving PREPARE
    """
    slow_node, other_nodes, _, _ = split_nodes(txnPoolNodeSet)
    slow_node.nodeIbStasher.delay(ppgDelay(20))
    slow_node.nodeIbStasher.delay(msg_rep_delay(20, [PROPAGATE, ]))

    old_count_resp = count_requested_preprepare_resp(slow_node)

    sdk_send_batches_of_random_and_check(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         num_reqs=4,
                                         num_batches=2)

    # The slow node is behind
    checkNodeDataForInequality(slow_node, *other_nodes)

    # PRE-PREPARE were not requested
    assert count_requested_preprepare_resp(slow_node) == old_count_resp

    slow_node.nodeIbStasher.reset_delays_and_process_delayeds()

    # The slow node has processed all requests
    waitNodeDataEquality(looper, slow_node, *other_nodes)

    # PRE-PREPARE were not requested
    assert count_requested_preprepare_resp(slow_node) == old_count_resp
def test_handle_delayed_preprepares(looper, txnPoolNodeSet, sdk_wallet_client,
                                    sdk_pool_handle, teardown, monkeypatch):
    """
    Make a node send PREPREPARE again after the slow node has ordered
    """
    slow_node, other_nodes, primary_node, other_non_primary_nodes = \
        split_nodes(txnPoolNodeSet)
    # This node will send PRE-PREPARE again
    orig_method = primary_node.master_replica._message_req_service.handlers[
        PREPREPARE].process_message_req
    handler = primary_node.master_replica._message_req_service.handlers[
        PREPREPARE]
    last_pp = None

    def patched_method(self, msg):
        nonlocal last_pp
        last_pp = orig_method(msg)
        return last_pp

    handler.process_message_req = types.MethodType(patched_method, handler)

    # Delay PRE-PREPAREs by large amount simulating loss
    slow_node.nodeIbStasher.delay(ppDelay(300, 0))

    sdk_send_batches_of_random_and_check(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         num_reqs=10,
                                         num_batches=5)
    waitNodeDataEquality(looper, slow_node, *other_nodes)

    slow_master_replica = slow_node.master_replica
    count_pr_req = get_count(
        slow_master_replica._message_req_service,
        slow_master_replica._message_req_service.process_message_rep)

    primary_node.sendToNodes(MessageRep(
        **{
            f.MSG_TYPE.nm: PREPREPARE,
            f.PARAMS.nm: {
                f.INST_ID.nm: last_pp.instId,
                f.VIEW_NO.nm: last_pp.viewNo,
                f.PP_SEQ_NO.nm: last_pp.ppSeqNo
            },
            f.MSG.nm: last_pp
        }),
                             names=[
                                 slow_node.name,
                             ])

    def chk():
        assert get_count(
            slow_master_replica._message_req_service, slow_master_replica.
            _message_req_service.process_message_rep) > count_pr_req
        assert slow_master_replica._ordering_service.spylog.getLast(
            "_validate").result[0] == -1

    looper.run(eventually(chk, retryWait=1))
示例#6
0
def test_node_request_preprepare(looper, txnPoolNodeSet, client1,
                                 wallet1, client1Connected, teardown):
    """
    Node requests PRE-PREPARE only once after getting PREPAREs.
    """
    slow_node, other_nodes, primary_node, \
        other_primary_nodes = split_nodes(txnPoolNodeSet)
    # Drop PrePrepares and Prepares
    slow_node.nodeIbStasher.delay(ppDelay(300, 0))
    slow_node.nodeIbStasher.delay(pDelay(300, 0))

    send_reqs_batches_and_get_suff_replies(looper, wallet1, client1, 10, 5)
    slow_node.nodeIbStasher.drop_delayeds()
    slow_node.nodeIbStasher.resetDelays()

    old_count_req = count_requested_preprepare_req(slow_node)
    old_count_resp = count_requested_preprepare_resp(slow_node)

    def chk(increase=True):
        # Method is called
        assert count_requested_preprepare_req(slow_node) > old_count_req
        # Requesting Preprepare
        assert count_requested_preprepare_resp(
            slow_node) - old_count_resp == (1 if increase else 0)

    for pp in primary_node.master_replica.sentPrePrepares.values():
        for rep in [n.master_replica for n in other_primary_nodes]:
            prepare = Prepare(rep.instId,
                              pp.viewNo,
                              pp.ppSeqNo,
                              pp.ppTime,
                              pp.digest,
                              pp.stateRootHash,
                              pp.txnRootHash
                              )
            rep.send(prepare)

        looper.run(eventually(chk, True, retryWait=1))

        old_count_resp = count_requested_preprepare_resp(slow_node)

        prepare = Prepare(rep.instId,
                          pp.viewNo,
                          pp.ppSeqNo,
                          pp.ppTime,
                          pp.digest,
                          pp.stateRootHash,
                          pp.txnRootHash
                          )
        rep.send(prepare)

        looper.run(eventually(chk, False, retryWait=1))

        old_count_req = count_requested_preprepare_req(slow_node)

        old_count_resp = count_requested_preprepare_resp(slow_node)
def test_node_requests_missing_preprepare(looper, txnPoolNodeSet,
                                          sdk_wallet_client, sdk_pool_handle,
                                          teardown):
    """
    A node has bad network with primary and thus loses PRE-PREPARE,
    it requests PRE-PREPARE from primary once it has sufficient PREPAREs
    """
    slow_node, other_nodes, primary_node, other_non_primary_nodes = split_nodes(
        txnPoolNodeSet)

    # Delay PRE-PREPAREs by large amount simulating loss
    slow_node.nodeIbStasher.delay(ppDelay(300, 0))
    old_count_pp = get_count(
        slow_node.master_replica,
        slow_node.master_replica._ordering_service.process_preprepare)
    old_count_mrq = {
        n.name: get_count(n, n.process_message_req)
        for n in other_nodes
    }
    old_count_mrp = get_count(slow_node, slow_node.process_message_rep)

    sdk_send_batches_of_random_and_check(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         num_reqs=15,
                                         num_batches=5)

    waitNodeDataEquality(looper, slow_node, *other_nodes)

    assert not slow_node.master_replica.requested_pre_prepares

    # `slow_node` processed PRE-PREPARE
    # assert get_count(slow_node.master_replica,
    #                  slow_node.master_replica._ordering_service.process_preprepare) > old_count_pp

    # `slow_node` did receive `MessageRep`
    assert get_count(slow_node, slow_node.process_message_rep) > old_count_mrp

    # Primary node should received `MessageReq` and other nodes shouldn't
    recv_reqs = set()
    for n in other_non_primary_nodes:
        if get_count(n, n.process_message_req) > old_count_mrq[n.name]:
            recv_reqs.add(n.name)

    assert get_count(primary_node, primary_node.process_message_req) > \
           old_count_mrq[primary_node.name]
    assert len(recv_reqs) == 0

    # All nodes including the `slow_node` ordered the same requests
    assert check_if_all_equal_in_list(
        [n.master_replica._ordering_service.ordered for n in txnPoolNodeSet])
def test_node_requests_missing_preprepare(looper, txnPoolNodeSet,
                                          sdk_wallet_client, sdk_pool_handle,
                                          teardown):
    """
    A node has bad network with primary and thus loses PRE-PREPARE,
    it requests PRE-PREPARE from primary once it has sufficient PREPAREs
    """
    slow_node, other_nodes, primary_node, other_non_primary_nodes = split_nodes(
        txnPoolNodeSet)

    # Delay PRE-PREPAREs by large amount simulating loss
    slow_node.nodeIbStasher.delay(ppDelay(300, 0))
    old_count_pp = get_count(slow_node.master_replica,
                             slow_node.master_replica.processPrePrepare)
    old_count_mrq = {n.name: get_count(n, n.process_message_req)
                     for n in other_nodes}
    old_count_mrp = get_count(slow_node, slow_node.process_message_rep)

    sdk_send_batches_of_random_and_check(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         num_reqs=15,
                                         num_batches=5)

    waitNodeDataEquality(looper, slow_node, *other_nodes)

    assert not slow_node.master_replica.requested_pre_prepares

    # `slow_node` processed PRE-PREPARE
    assert get_count(slow_node.master_replica,
                     slow_node.master_replica.processPrePrepare) > old_count_pp

    # `slow_node` did receive `MessageRep`
    assert get_count(slow_node, slow_node.process_message_rep) > old_count_mrp

    # Primary node should received `MessageReq` and other nodes shouldn't
    recv_reqs = set()
    for n in other_non_primary_nodes:
        if get_count(n, n.process_message_req) > old_count_mrq[n.name]:
            recv_reqs.add(n.name)

    assert get_count(primary_node, primary_node.process_message_req) > \
           old_count_mrq[primary_node.name]
    assert len(recv_reqs) == 0

    # All nodes including the `slow_node` ordered the same requests
    assert check_if_all_equal_in_list([n.master_replica.ordered
                                       for n in txnPoolNodeSet])
def test_node_requests_missing_preprepare(looper, txnPoolNodeSet, client1,
                                          wallet1, client1Connected, teardown):
    """
    A node has bad network with primary and thus loses PRE-PREPARE,
    it requests PRE-PREPARE from non-primaries once it has sufficient PREPAREs
    """
    slow_node, other_nodes, _, _ = split_nodes(txnPoolNodeSet)

    # Delay PRE-PREPAREs by large amount simulating loss
    slow_node.nodeIbStasher.delay(ppDelay(300, 0))
    old_count_pp = get_count(slow_node.master_replica,
                             slow_node.master_replica.processPrePrepare)
    old_count_mrq = {
        n.name: get_count(n, n.process_message_req)
        for n in other_nodes
    }
    old_count_mrp = get_count(slow_node, slow_node.process_message_rep)

    send_reqs_batches_and_get_suff_replies(looper, wallet1, client1, 15, 5)

    waitNodeDataEquality(looper, slow_node, *other_nodes)

    assert not slow_node.master_replica.requested_pre_prepares

    # `slow_node` processed PRE-PREPARE
    assert get_count(slow_node.master_replica,
                     slow_node.master_replica.processPrePrepare) > old_count_pp

    # `slow_node` did receive `MessageRep`
    assert get_count(slow_node, slow_node.process_message_rep) > old_count_mrp

    # More than `f` nodes received `MessageReq`
    recv_reqs = set()
    for n in other_nodes:
        if get_count(n, n.process_message_req) > old_count_mrq[n.name]:
            recv_reqs.add(n.name)

    assert len(recv_reqs) > slow_node.f

    # All nodes including the `slow_node` ordered the same requests
    assert check_if_all_equal_in_list(
        [n.master_replica.ordered for n in txnPoolNodeSet])
def test_node_request_preprepare(looper, txnPoolNodeSet,
                                 sdk_wallet_client, sdk_pool_handle,
                                 teardown):
    """
    Node requests PRE-PREPARE only once after getting PREPAREs.
    """
    slow_node, other_nodes, primary_node, \
    other_primary_nodes = split_nodes(txnPoolNodeSet)
    # Drop PrePrepares and Prepares
    slow_node.nodeIbStasher.delay(ppDelay(300, 0))
    slow_node.nodeIbStasher.delay(pDelay(300, 0))

    sdk_send_batches_of_random_and_check(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         num_reqs=10,
                                         num_batches=5)
    slow_node.nodeIbStasher.drop_delayeds()
    slow_node.nodeIbStasher.resetDelays()

    old_count_req = count_requested_preprepare_req(slow_node)
    old_count_resp = count_requested_preprepare_resp(slow_node)

    def chk(increase=True):
        # Method is called
        assert count_requested_preprepare_req(slow_node) > old_count_req
        # Requesting Preprepare
        assert count_requested_preprepare_resp(
            slow_node) - old_count_resp == (1 if increase else 0)

    for pp in primary_node.master_replica.sentPrePrepares.values():
        for rep in [n.master_replica for n in other_primary_nodes]:
            prepare = Prepare(rep.instId,
                              pp.viewNo,
                              pp.ppSeqNo,
                              pp.ppTime,
                              pp.digest,
                              pp.stateRootHash,
                              pp.txnRootHash
                              )
            rep.send(prepare)

        looper.run(eventually(chk, True, retryWait=1))

        old_count_resp = count_requested_preprepare_resp(slow_node)

        prepare = Prepare(rep.instId,
                          pp.viewNo,
                          pp.ppSeqNo,
                          pp.ppTime,
                          pp.digest,
                          pp.stateRootHash,
                          pp.txnRootHash
                          )
        rep.send(prepare)

        looper.run(eventually(chk, False, retryWait=1))

        old_count_req = count_requested_preprepare_req(slow_node)

        old_count_resp = count_requested_preprepare_resp(slow_node)