コード例 #1
0
def test_no_propagate_request_on_different_last_ordered_on_master_before_vc(
        looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client):
    ''' Send random request and do view change then fast_nodes (1, 4 - without
    primary after next view change) are already ordered transaction on master
    and slow_nodes are not. Check ordering on slow_nodes.'''
    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)
    master_instance = txnPoolNodeSet[0].master_replica.instId
    slow_nodes = txnPoolNodeSet[1:3]
    fast_nodes = [n for n in txnPoolNodeSet if n not in slow_nodes]
    nodes_stashers = [n.nodeIbStasher for n in slow_nodes]
    old_last_ordered = txnPoolNodeSet[0].master_replica.last_ordered_3pc
    with delay_rules(nodes_stashers, cDelay()):
        # send one request
        requests = sdk_send_random_requests(looper, sdk_pool_handle,
                                            sdk_wallet_client, 1)
        last_ordered_for_slow = slow_nodes[0].master_replica.last_ordered_3pc
        old_view_no = txnPoolNodeSet[0].viewNo
        looper.run(
            eventually(check_last_ordered, fast_nodes, master_instance,
                       (old_view_no, old_last_ordered[1] + 1)))

        # trigger view change on all nodes
        ensure_view_change(looper, txnPoolNodeSet)
        # wait for view change done on all nodes
        ensureElectionsDone(looper, txnPoolNodeSet)

    replies = sdk_get_replies(looper, requests)
    for reply in replies:
        sdk_check_reply(reply)

    check_last_ordered(slow_nodes, master_instance,
                       (old_view_no, last_ordered_for_slow[1] + 1))
    assert all(0 == node.spylog.count(node.request_propagates)
               for node in txnPoolNodeSet)
コード例 #2
0
def test_view_change_during_unstash(looper, txnPoolNodeSet, sdk_pool_handle,
                                    sdk_wallet_client, tconf):
    slow_node = txnPoolNodeSet[-1]
    other_nodes = txnPoolNodeSet[:-1]

    slow_stasher = slow_node.nodeIbStasher
    other_stashers = [n.nodeIbStasher for n in other_nodes]
    all_stashers = [n.nodeIbStasher for n in txnPoolNodeSet]

    # Preload nodes with some transactions
    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)
    for node in txnPoolNodeSet:
        assert node.master_replica.last_ordered_3pc == (0, 1)

    # Prevent ordering of some requests
    start_delaying(all_stashers, delay_3pc(after=7, msgs=(Prepare, Commit)))

    # Stop ordering on slow node and send requests
    slow_node_after_5 = start_delaying(slow_stasher,
                                       delay_3pc(after=5, msgs=Commit))
    slow_node_until_5 = start_delaying(slow_stasher, delay_3pc(after=0))
    reqs_view_0 = sdk_send_random_requests(looper, sdk_pool_handle,
                                           sdk_wallet_client, 8)

    # Make pool order first 2 batches and pause
    pool_after_3 = start_delaying(other_stashers, delay_3pc(after=3))
    looper.run(eventually(check_nodes_ordered_till, other_nodes, 0, 3))

    # Start catchup, continue ordering everywhere (except two last batches on slow node)
    with delay_rules(slow_stasher, cr_delay()):
        slow_node._do_start_catchup(just_started=False)
        looper.run(eventually(check_catchup_is_started, slow_node))
        stop_delaying_and_process(pool_after_3)
        looper.run(eventually(check_nodes_ordered_till, other_nodes, 0, 7))

    # Finish catchup and continue processing on slow node
    looper.run(eventually(check_catchup_is_finished, slow_node))
    stop_delaying_and_process(slow_node_until_5)
    looper.run(eventually(check_nodes_ordered_till, [slow_node], 0, 5))

    # Start view change and allow slow node to get remaining commits
    with delay_rules(all_stashers, icDelay()):
        for node in txnPoolNodeSet:
            node.view_changer.on_master_degradation()
        looper.runFor(0.1)
    stop_delaying_and_process(slow_node_after_5)

    # Ensure that expected number of requests was ordered
    replies = sdk_get_replies(looper, reqs_view_0)
    for rep in replies[:6]:
        sdk_check_reply(rep)

    # Ensure that everything is ok
    ensureElectionsDone(looper, txnPoolNodeSet)
    ensure_all_nodes_have_same_data(looper, txnPoolNodeSet)
    sdk_ensure_pool_functional(looper, txnPoolNodeSet, sdk_wallet_client,
                               sdk_pool_handle)
コード例 #3
0
def sdk_get_and_check_multiply_replies(looper, request_couple):
    rets = []
    for req_res in sdk_get_replies(looper, [
            request_couple,
    ]):
        req, responses = req_res
        if not isinstance(responses, ErrorCode) and "op" not in responses:
            for node_resp in responses.values():
                sdk_check_reply((req, json.loads(node_resp)))
        else:
            sdk_check_reply(req_res)
        rets.append(req_res)
    return rets[0]
def test_no_propagate_request_on_different_last_ordered_on_master_before_vc(
        looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client):
    ''' Send random request and do view change then fast_nodes (1, 4 - without
    primary after next view change) are already ordered transaction on master
    and slow_nodes are not. Check ordering on slow_nodes.'''
    global batches_count
    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)
    batches_count += 1
    master_instance = txnPoolNodeSet[0].master_replica.instId
    slow_nodes = txnPoolNodeSet[1:3]
    fast_nodes = [n for n in txnPoolNodeSet if n not in slow_nodes]
    nodes_stashers = [n.nodeIbStasher for n in slow_nodes]
    old_last_ordered = txnPoolNodeSet[0].master_replica.last_ordered_3pc
    assert batches_count == old_last_ordered[1]
    with delay_rules(nodes_stashers, cDelay()):
        # send one request
        requests = sdk_send_random_requests(looper, sdk_pool_handle,
                                            sdk_wallet_client, 1)
        batches_count += 1
        last_ordered_for_slow = slow_nodes[0].master_replica.last_ordered_3pc
        old_view_no = txnPoolNodeSet[0].viewNo
        looper.run(
            eventually(check_last_ordered, fast_nodes, master_instance,
                       (old_view_no, batches_count)))

        # trigger view change on all nodes
        ensure_view_change(looper, txnPoolNodeSet)
        # wait for view change done on all nodes
        ensureElectionsDone(looper, txnPoolNodeSet, customTimeout=60)

        batches_count += 1

    replies = sdk_get_replies(looper, requests)
    for reply in replies:
        sdk_check_reply(reply)

    # a new primary will send a PrePrepare for the new view
    looper.run(
        eventually(check_last_ordered, txnPoolNodeSet, master_instance,
                   (old_view_no + 1, batches_count)))
    ensure_all_nodes_have_same_data(looper, txnPoolNodeSet)
    assert all(0 == node.spylog.count(node.request_propagates)
               for node in txnPoolNodeSet)
コード例 #5
0
def testOnlyAStewardCanAddAnotherSteward(looper,
                                         txnPoolNodeSet,
                                         sdk_pool_handle,
                                         sdk_wallet_steward,
                                         sdk_wallet_client):
    sdk_add_new_nym(looper, sdk_pool_handle, sdk_wallet_steward,
                    alias='testSteward' + randomString(3), role=STEWARD_STRING)

    seed = randomString(32)
    wh, _ = sdk_wallet_client

    nym_request, steward_did = looper.loop.run_until_complete(
        prepare_nym_request(sdk_wallet_client, seed,
                            'testSteward2', 'STEWARD'))

    request_couple = sdk_sign_and_send_prepared_request(looper, sdk_wallet_client,
                                                        sdk_pool_handle, nym_request)
    total_timeout = sdk_eval_timeout(1, len(txnPoolNodeSet))
    request_couple = sdk_get_replies(looper, [request_couple], total_timeout)[0]
    with pytest.raises(RequestRejectedException) as e:
        sdk_check_reply(request_couple)
    assert 'Only Steward is allowed to do these transactions' in e._excinfo[1].args[0]
def test_no_propagate_request_on_different_last_ordered_on_master_before_vc(looper, txnPoolNodeSet,
                                                  sdk_pool_handle, sdk_wallet_client):
    ''' Send random request and do view change then fast_nodes (1, 4 - without
    primary after next view change) are already ordered transaction on master
    and slow_nodes are not. Check ordering on slow_nodes.'''
    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)
    master_instance = txnPoolNodeSet[0].master_replica.instId
    slow_nodes = txnPoolNodeSet[1:3]
    fast_nodes = [n for n in txnPoolNodeSet if n not in slow_nodes]
    nodes_stashers = [n.nodeIbStasher for n in slow_nodes]
    old_last_ordered = txnPoolNodeSet[0].master_replica.last_ordered_3pc
    with delay_rules(nodes_stashers, cDelay()):
        # send one request
        requests = sdk_send_random_requests(looper, sdk_pool_handle,
                                            sdk_wallet_client, 1)
        last_ordered_for_slow = slow_nodes[0].master_replica.last_ordered_3pc
        old_view_no = txnPoolNodeSet[0].viewNo
        looper.run(
            eventually(check_last_ordered,
                       fast_nodes,
                       master_instance,
                       (old_view_no, old_last_ordered[1] + 1)))

        # trigger view change on all nodes
        ensure_view_change(looper, txnPoolNodeSet)
        # wait for view change done on all nodes
        ensureElectionsDone(looper, txnPoolNodeSet)

    replies = sdk_get_replies(looper, requests)
    for reply in replies:
        sdk_check_reply(reply)

    check_last_ordered(slow_nodes,
                       master_instance,
                       (old_view_no, last_ordered_for_slow[1] + 1))
    assert all(0 == node.spylog.count(node.request_propagates)
               for node in txnPoolNodeSet)
def test_quorum_after_f_plus_2_nodes_including_primary_turned_off_and_later_on(
        looper, allPluginsPath, tdir, tconf, txnPoolNodeSet, sdk_pool_handle,
        sdk_wallet_client):
    timeout = sdk_eval_timeout(1, len(txnPoolNodeSet))
    nodes = txnPoolNodeSet

    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)

    stop_node(nodes[0], looper, nodes)
    waitForViewChange(looper, nodes[1:], expectedViewNo=1)
    ensureElectionsDone(looper,
                        nodes[1:],
                        numInstances=getRequiredInstances(nodeCount))

    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)

    stop_node(nodes[1], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[2:], expectedViewNo=1)

    sdk_reqs3 = sdk_send_random_requests(looper, sdk_pool_handle,
                                         sdk_wallet_client, 1)
    with pytest.raises(TimeoutError):
        req_res = sdk_get_replies(looper, sdk_reqs3, timeout=timeout)
        sdk_check_reply(req_res[0])

    stop_node(nodes[2], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[3:], expectedViewNo=1)

    sdk_reqs4 = sdk_send_random_requests(looper, sdk_pool_handle,
                                         sdk_wallet_client, 1)
    with pytest.raises(TimeoutError):
        req_res = sdk_get_replies(looper, sdk_reqs4, timeout=timeout)
        sdk_check_reply(req_res[0])

    nodes[2] = start_stopped_node(nodes[2], looper, tconf, tdir,
                                  allPluginsPath)
    looper.runFor(waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[3:], expectedViewNo=1)

    sdk_reqs5 = sdk_send_random_requests(looper, sdk_pool_handle,
                                         sdk_wallet_client, 1)
    with pytest.raises(TimeoutError):
        req_res = sdk_get_replies(looper, sdk_reqs5, timeout=timeout)
        sdk_check_reply(req_res[0])

    nodes[1] = start_stopped_node(nodes[1], looper, tconf, tdir,
                                  allPluginsPath)
    ensureElectionsDone(looper,
                        nodes[1:],
                        numInstances=getRequiredInstances(nodeCount))
    checkViewNoForNodes(nodes[1:], expectedViewNo=1)

    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)

    nodes[0] = start_stopped_node(nodes[0], looper, tconf, tdir,
                                  allPluginsPath)
    ensureElectionsDone(looper,
                        nodes,
                        numInstances=getRequiredInstances(nodeCount))
    checkViewNoForNodes(nodes, expectedViewNo=1)

    sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
                              sdk_wallet_client, 1)
def test_quorum_after_f_plus_2_nodes_including_primary_turned_off_and_later_on(
        looper, allPluginsPath, tdir, tconf,
        txnPoolNodeSet,
        sdk_pool_handle,
        sdk_wallet_client):
    timeout = sdk_eval_timeout(1, len(txnPoolNodeSet))
    nodes = txnPoolNodeSet

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)

    stop_node(nodes[0], looper, nodes)
    waitForViewChange(looper, nodes[1:], expectedViewNo=1)
    ensureElectionsDone(looper, nodes[1:],
                        instances_list=range(getRequiredInstances(nodeCount)))

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)

    stop_node(nodes[1], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[2:], expectedViewNo=1)

    sdk_reqs3 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs3, timeout=timeout)
        sdk_check_reply(req_res[0])

    stop_node(nodes[2], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[3:], expectedViewNo=1)

    sdk_reqs4 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs4, timeout=timeout)
        sdk_check_reply(req_res[0])

    nodes[2] = start_stopped_node(nodes[2], looper, tconf, tdir, allPluginsPath)
    looper.runFor(waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[3:], expectedViewNo=1)

    sdk_reqs5 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs5, timeout=timeout)
        sdk_check_reply(req_res[0])

    nodes[1] = start_stopped_node(nodes[1], looper, tconf, tdir, allPluginsPath)
    ensureElectionsDone(looper, nodes[1:],
                        instances_list=range(getRequiredInstances(nodeCount)),
                        customTimeout=60)
    checkViewNoForNodes(nodes[1:], expectedViewNo=1)

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)

    nodes[0] = start_stopped_node(nodes[0], looper, tconf, tdir, allPluginsPath)
    ensureElectionsDone(looper, nodes,
                        instances_list=range(getRequiredInstances(nodeCount)),
                        customTimeout=60)
    checkViewNoForNodes(nodes, expectedViewNo=1)

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)
def test_quorum_after_f_plus_2_nodes_but_not_primary_turned_off_and_later_on(
        looper, allPluginsPath, tdir, tconf,
        txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client):
    nodes = txnPoolNodeSet

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)

    stop_node(nodes[4], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:4], expectedViewNo=0)

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)

    stop_node(nodes[3], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:3], expectedViewNo=0)

    sdk_reqs3 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs3)
        sdk_check_reply(req_res[0])

    stop_node(nodes[2], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:2], expectedViewNo=0)

    sdk_reqs4 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs4)
        sdk_check_reply(req_res[0])

    nodes[4] = start_stopped_node(nodes[4], looper, tconf, tdir, allPluginsPath)
    looper.runFor(waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:2] + nodes[4:], expectedViewNo=0)

    sdk_reqs5 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs5)
        sdk_check_reply(req_res[0])

    nodes[3] = start_stopped_node(nodes[3], looper, tconf, tdir, allPluginsPath)
    ensureElectionsDone(looper, nodes[:2] + nodes[3:],
                        numInstances=getRequiredInstances(nodeCount))
    checkViewNoForNodes(nodes[:2] + nodes[3:], expectedViewNo=0)

    sdk_reqs6 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    sdk_get_replies(looper, [sdk_reqs3[0], sdk_reqs4[0], sdk_reqs5[0], sdk_reqs6[0]])

    nodes[2] = start_stopped_node(nodes[2], looper, tconf, tdir, allPluginsPath)
    ensureElectionsDone(looper, nodes,
                        numInstances=getRequiredInstances(nodeCount))
    checkViewNoForNodes(nodes, expectedViewNo=0)

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)
コード例 #10
0
 def succeeded(req_resp):
     try:
         sdk_check_reply(req_resp)
         return True
     except Exception:
         return False
コード例 #11
0
def test_already_processed_requests(looper, txnPoolNodeSet, sdk_pool_handle,
                                    sdk_wallet_client):
    """
    Client re-sending request and checking that nodes picked the reply from
    ledger and did not process the request again
    """
    def get_method_call_count(method):
        counts = set()
        for node in txnPoolNodeSet:
            c = node.spylog.count(method)
            counts.add(c)
        assert len(counts) == 1
        return counts.pop()

    def get_getReplyFromLedger_call_count():
        return get_method_call_count(
            next(iter(txnPoolNodeSet)).getReplyFromLedger)

    def get_recordAndPropagate_call_count():
        return get_method_call_count(
            next(iter(txnPoolNodeSet)).recordAndPropagate)

    def get_last_returned_val():
        rvs = []
        for node in txnPoolNodeSet:
            rv = getAllReturnVals(node, node.getReplyFromLedger)
            rvs.append(rv[0])
        # All items are same in the list
        assert rvs.count(rvs[0]) == len(txnPoolNodeSet)
        return rvs[0]

    rlc1 = get_getReplyFromLedger_call_count()
    rpc1 = get_recordAndPropagate_call_count()

    # Request which will be send twice
    reqs = sdk_signed_random_requests(looper, sdk_wallet_client, 1)

    # Send, check and getting reply from first request
    sdk_reqs = sdk_send_signed_requests(sdk_pool_handle, reqs)
    total_timeout = sdk_eval_timeout(len(sdk_reqs), len(txnPoolNodeSet))
    request1 = sdk_get_replies(looper, sdk_reqs, timeout=total_timeout)
    for req_res in request1:
        sdk_check_reply(req_res)
    first_req_id = request1[0][0]['reqId']

    rlc2 = get_getReplyFromLedger_call_count()
    rpc2 = get_recordAndPropagate_call_count()
    assert rlc2 - rlc1 == 1  # getReplyFromLedger was called
    assert rpc2 - rpc1 == 1  # recordAndPropagate was called
    r1 = get_last_returned_val()
    assert r1 is None  # getReplyFromLedger returned None since had not seen request

    # Request which we will send only once
    request2 = sdk_send_random_and_check(looper, txnPoolNodeSet,
                                         sdk_pool_handle, sdk_wallet_client, 1)
    second_req_id = request2[0][0]['reqId']

    assert second_req_id != first_req_id
    rlc3 = get_getReplyFromLedger_call_count()
    rpc3 = get_recordAndPropagate_call_count()
    assert rlc3 - rlc2 == 1  # getReplyFromLedger was called again
    assert rpc3 - rpc2 == 1  # recordAndPropagate was called again
    r2 = get_last_returned_val()
    assert r2 is None  # getReplyFromLedger returned None since had not seen request

    # Reply for the first request, which is going to be sent again
    rep1 = request1[0][1]['result']

    # Client re-sending first request
    request3 = sdk_send_signed_requests(sdk_pool_handle, reqs)
    total_timeout = sdk_eval_timeout(len(request3), len(txnPoolNodeSet))
    request3 = sdk_get_replies(looper, request3, timeout=total_timeout)
    third_req_id = request3[0][0]['reqId']

    assert third_req_id == first_req_id
    rlc4 = get_getReplyFromLedger_call_count()
    rpc4 = get_recordAndPropagate_call_count()
    assert rlc4 - rlc3 == 1  # getReplyFromLedger was called again
    assert rpc4 - rpc3 == 0  # recordAndPropagate was not called
    r3 = get_last_returned_val()
    # getReplyFromLedger did not return None this time since had seen request
    assert r3 is not None
    rep3 = request3[0][1]['result']

    # Since txnTime is not stored in ledger and reading from ledger return
    # all possible fields from transactions
    rep3 = {k: v for k, v in rep3.items() if v is not None}
    rep1 = {k: v for k, v in rep1.items() if k in rep3}

    assert rep3 == rep1  # The reply client got is same as the previous one
def test_quorum_after_f_plus_2_nodes_but_not_primary_turned_off_and_later_on(
        looper, allPluginsPath, tdir, tconf,
        txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client):
    nodes = txnPoolNodeSet

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)

    stop_node(nodes[4], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:4], expectedViewNo=0)

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)

    stop_node(nodes[3], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:3], expectedViewNo=0)

    sdk_reqs3 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs3)
        sdk_check_reply(req_res[0])

    stop_node(nodes[2], looper, nodes)
    looper.runFor(tconf.ToleratePrimaryDisconnection +
                  waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:2], expectedViewNo=0)

    sdk_reqs4 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs4)
        sdk_check_reply(req_res[0])

    nodes[4] = start_stopped_node(nodes[4], looper, tconf, tdir, allPluginsPath)
    looper.runFor(waits.expectedPoolElectionTimeout(len(nodes)))
    checkViewNoForNodes(nodes[:2] + nodes[4:], expectedViewNo=0)

    sdk_reqs5 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    with pytest.raises(PoolLedgerTimeoutException):
        req_res = sdk_get_replies(looper, sdk_reqs5)
        sdk_check_reply(req_res[0])

    nodes[3] = start_stopped_node(nodes[3], looper, tconf, tdir, allPluginsPath)
    ensureElectionsDone(looper, nodes[:2] + nodes[3:],
                        instances_list=range(getRequiredInstances(nodeCount)))
    checkViewNoForNodes(nodes[:2] + nodes[3:], expectedViewNo=0)

    sdk_reqs6 = sdk_send_random_requests(looper,
                                         sdk_pool_handle,
                                         sdk_wallet_client,
                                         1)
    sdk_get_replies(looper, sdk_reqs6)

    nodes[2] = start_stopped_node(nodes[2], looper, tconf, tdir, allPluginsPath)
    ensureElectionsDone(looper, nodes,
                        instances_list=range(getRequiredInstances(nodeCount)))
    checkViewNoForNodes(nodes, expectedViewNo=0)

    sdk_send_random_and_check(looper, txnPoolNodeSet,
                              sdk_pool_handle,
                              sdk_wallet_client,
                              1)
コード例 #13
0
def test_already_processed_requests(looper, txnPoolNodeSet,
                                    sdk_pool_handle, sdk_wallet_client):
    """
    Client re-sending request and checking that nodes picked the reply from
    ledger and did not process the request again
    """

    def get_method_call_count(method):
        counts = set()
        for node in txnPoolNodeSet:
            c = node.spylog.count(method)
            counts.add(c)
        assert len(counts) == 1
        return counts.pop()

    def get_getReplyFromLedgerForRequest_call_count():
        return get_method_call_count(
            next(iter(txnPoolNodeSet)).getReplyFromLedgerForRequest)

    def get_recordAndPropagate_call_count():
        return get_method_call_count(
            next(iter(txnPoolNodeSet)).recordAndPropagate)

    def get_last_returned_val():
        rvs = []
        for node in txnPoolNodeSet:
            rv = getAllReturnVals(node, node.getReplyFromLedgerForRequest)
            rvs.append(rv[0])
        # All items are same in the list
        assert rvs.count(rvs[0]) == len(txnPoolNodeSet)
        return rvs[0]

    rlc1 = get_getReplyFromLedgerForRequest_call_count()
    rpc1 = get_recordAndPropagate_call_count()

    # Request which will be send twice
    reqs = sdk_signed_random_requests(looper, sdk_wallet_client, 1)

    # Send, check and getting reply from first request
    sdk_reqs = sdk_send_signed_requests(sdk_pool_handle, reqs)
    total_timeout = sdk_eval_timeout(len(sdk_reqs), len(txnPoolNodeSet))
    request1 = sdk_get_replies(looper, sdk_reqs, timeout=total_timeout)
    for req_res in request1:
        sdk_check_reply(req_res)
    first_req_id = request1[0][0]['reqId']

    rlc2 = get_getReplyFromLedgerForRequest_call_count()
    rpc2 = get_recordAndPropagate_call_count()
    assert rlc2 - rlc1 == 1  # getReplyFromLedgerForRequest was called
    assert rpc2 - rpc1 == 1  # recordAndPropagate was called
    r1 = get_last_returned_val()
    assert r1 is None  # getReplyFromLedgerForRequest returned None since had not seen request

    # Request which we will send only once
    request2 = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1)
    second_req_id = request2[0][0]['reqId']

    assert second_req_id != first_req_id
    rlc3 = get_getReplyFromLedgerForRequest_call_count()
    rpc3 = get_recordAndPropagate_call_count()
    assert rlc3 - rlc2 == 1  # getReplyFromLedgerForRequest was called again
    assert rpc3 - rpc2 == 1  # recordAndPropagate was called again
    r2 = get_last_returned_val()
    assert r2 is None  # getReplyFromLedgerForRequest returned None since had not seen request

    # Reply for the first request, which is going to be sent again
    rep1 = request1[0][1]['result']

    # Client re-sending first request
    request3 = sdk_send_signed_requests(sdk_pool_handle, reqs)
    total_timeout = sdk_eval_timeout(len(request3), len(txnPoolNodeSet))
    request3 = sdk_get_replies(looper, request3, timeout=total_timeout)
    third_req_id = request3[0][0]['reqId']

    assert third_req_id == first_req_id
    rlc4 = get_getReplyFromLedgerForRequest_call_count()
    rpc4 = get_recordAndPropagate_call_count()
    assert rlc4 - rlc3 == 1  # getReplyFromLedgerForRequest was called again
    assert rpc4 - rpc3 == 0  # recordAndPropagate was not called
    r3 = get_last_returned_val()
    # getReplyFromLedgerForRequest did not return None this time since had seen request
    assert r3 is not None
    rep3 = request3[0][1]['result']

    # Since txnTime is not stored in ledger and reading from ledger return
    # all possible fields from transactions
    rep3 = {k: v for k, v in rep3.items() if v is not None}
    rep1 = {k: v for k, v in rep1.items() if k in rep3}

    assert rep3 == rep1  # The reply client got is same as the previous one