def test_belated_request_not_processed_if_already_in_3pc_process( looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): delta = txnPoolNodeSet[3] initial_ledger_size = delta.domainLedger.size delta.clientIbStasher.delay(req_delay(300)) for node in txnPoolNodeSet: node.nodeIbStasher.delay(cDelay(300)) one_req = sdk_signed_random_requests(looper, sdk_wallet_client, 1) sdk_send_signed_requests(sdk_pool_handle, one_req) looper.runFor( waits.expectedPropagateTime(len(txnPoolNodeSet)) + waits.expectedPrePrepareTime(len(txnPoolNodeSet)) + waits.expectedPrepareTime(len(txnPoolNodeSet)) + waits.expectedCommittedTime(len(txnPoolNodeSet))) delta.clientIbStasher.reset_delays_and_process_delayeds() looper.runFor( waits.expectedPropagateTime(len(txnPoolNodeSet)) + waits.expectedPrePrepareTime(len(txnPoolNodeSet)) + waits.expectedPrepareTime(len(txnPoolNodeSet)) + waits.expectedCommittedTime(len(txnPoolNodeSet))) for node in txnPoolNodeSet: node.nodeIbStasher.reset_delays_and_process_delayeds() looper.runFor(waits.expectedOrderingTime(delta.replicas.num_replicas)) for node in txnPoolNodeSet: assert node.domainLedger.size - initial_ledger_size == 1
def test_belated_request_not_processed_if_already_in_3pc_process( looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): delta = txnPoolNodeSet[3] initial_ledger_size = delta.domainLedger.size delta.clientIbStasher.delay(req_delay(300)) for node in txnPoolNodeSet: node.nodeIbStasher.delay(cDelay(300)) one_req = sdk_signed_random_requests(looper, sdk_wallet_client, 1) sdk_send_signed_requests(sdk_pool_handle, one_req) looper.runFor(waits.expectedPropagateTime(len(txnPoolNodeSet)) + waits.expectedPrePrepareTime(len(txnPoolNodeSet)) + waits.expectedPrepareTime(len(txnPoolNodeSet)) + waits.expectedCommittedTime(len(txnPoolNodeSet))) delta.clientIbStasher.reset_delays_and_process_delayeds() looper.runFor(waits.expectedPropagateTime(len(txnPoolNodeSet)) + waits.expectedPrePrepareTime(len(txnPoolNodeSet)) + waits.expectedPrepareTime(len(txnPoolNodeSet)) + waits.expectedCommittedTime(len(txnPoolNodeSet))) for node in txnPoolNodeSet: node.nodeIbStasher.reset_delays_and_process_delayeds() looper.runFor(waits.expectedOrderingTime(delta.replicas.num_replicas)) for node in txnPoolNodeSet: assert node.domainLedger.size - initial_ledger_size == 1
def testReqExecWhenReturnedByMaster(tdir_for_func, tconf_for_func): with TestNodeSet(tconf_for_func, count=4, tmpdir=tdir_for_func) as nodeSet: with Looper(nodeSet) as looper: client1, wallet1 = setupNodesAndClient(looper, nodeSet, tmpdir=tdir_for_func) req = sendRandomRequest(wallet1, client1) waitForSufficientRepliesForRequests(looper, client1, requests=[req]) async def chk(): for node in nodeSet: entries = node.spylog.getAll(node.processOrdered.__name__) for entry in entries: arg = entry.params['ordered'] result = entry.result if arg.instId == node.instances.masterId: assert result else: assert result is False timeout = waits.expectedOrderingTime( nodeSet.nodes['Alpha'].instances.count) looper.run(eventually(chk, timeout=timeout))
def test_lagged_checkpoint_completion(chkFreqPatched, looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ One node in a pool lags to order the last 3PC-batch in a checkpoint so that when it eventually orders this 3PC-batch and thus completes the checkpoint it has already received and stashed the corresponding checkpoint messages from all the other nodes. The test verifies that the node successfully processes the stashed checkpoint messages and stabilizes the checkpoint. """ slow_node = txnPoolNodeSet[-1] # All the nodes in the pool normally orders all the 3PC-batches in a # checkpoint except the last 3PC-batch. The last 3PC-batch in the # checkpoint is ordered by all the nodes except one slow node because this # node lags to receive Commits. sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 4) slow_node.nodeIbStasher.delay(cDelay()) sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) # All the other nodes complete the checkpoint and send Checkpoint messages # to others. The slow node receives and stashes these messages because it # has not completed the checkpoint. def check(): for replica in slow_node.replicas.values(): assert len(replica.checkpoints) == 1 assert (1, 5) in replica.checkpoints assert replica.checkpoints[(1, 5)].seqNo == 4 assert replica.checkpoints[(1, 5)].digest is None assert replica.checkpoints[(1, 5)].isStable is False assert len(replica.stashedRecvdCheckpoints) == 1 assert 0 in replica.stashedRecvdCheckpoints assert len(replica.stashedRecvdCheckpoints[0]) == 1 assert (1, 5) in replica.stashedRecvdCheckpoints[0] assert len(replica.stashedRecvdCheckpoints[0][(1, 5)]) == \ len(txnPoolNodeSet) - 1 stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.run(eventually(check, timeout=stabilization_timeout)) # Eventually the slow node receives Commits, orders the last 3PC-batch in # the checkpoint and thus completes it, processes the stashed checkpoint # messages and stabilizes the checkpoint. slow_node.nodeIbStasher.reset_delays_and_process_delayeds() looper.runFor(waits.expectedOrderingTime(len(txnPoolNodeSet))) for replica in slow_node.replicas.values(): assert len(replica.checkpoints) == 1 assert (1, 5) in replica.checkpoints assert replica.checkpoints[(1, 5)].seqNo == 5 assert replica.checkpoints[(1, 5)].digest is not None assert replica.checkpoints[(1, 5)].isStable is True assert len(replica.stashedRecvdCheckpoints) == 0
def test_lagged_checkpoint_completion(chkFreqPatched, looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ One node in a pool lags to order the last 3PC-batch in a checkpoint so that when it eventually orders this 3PC-batch and thus completes the checkpoint it has already received and stashed the corresponding checkpoint messages from all the other nodes. The test verifies that the node successfully processes the stashed checkpoint messages and stabilizes the checkpoint. """ slow_node = txnPoolNodeSet[-1] # All the nodes in the pool normally orders all the 3PC-batches in a # checkpoint except the last 3PC-batch. The last 3PC-batch in the # checkpoint is ordered by all the nodes except one slow node because this # node lags to receive Commits. sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 4) slow_node.nodeIbStasher.delay(cDelay()) sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) # All the other nodes complete the checkpoint and send Checkpoint messages # to others. The slow node receives and stashes these messages because it # has not completed the checkpoint. def check(): for replica in slow_node.replicas: assert len(replica.checkpoints) == 1 assert (1, 5) in replica.checkpoints assert replica.checkpoints[(1, 5)].seqNo == 4 assert replica.checkpoints[(1, 5)].digest is None assert replica.checkpoints[(1, 5)].isStable is False assert len(replica.stashedRecvdCheckpoints) == 1 assert 0 in replica.stashedRecvdCheckpoints assert len(replica.stashedRecvdCheckpoints[0]) == 1 assert (1, 5) in replica.stashedRecvdCheckpoints[0] assert len(replica.stashedRecvdCheckpoints[0][(1, 5)]) == \ len(txnPoolNodeSet) - 1 stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.run(eventually(check, timeout=stabilization_timeout)) # Eventually the slow node receives Commits, orders the last 3PC-batch in # the checkpoint and thus completes it, processes the stashed checkpoint # messages and stabilizes the checkpoint. slow_node.nodeIbStasher.reset_delays_and_process_delayeds() looper.runFor(waits.expectedOrderingTime(len(txnPoolNodeSet))) for replica in slow_node.replicas: assert len(replica.checkpoints) == 1 assert (1, 5) in replica.checkpoints assert replica.checkpoints[(1, 5)].seqNo == 5 assert replica.checkpoints[(1, 5)].digest is not None assert replica.checkpoints[(1, 5)].isStable is True assert len(replica.stashedRecvdCheckpoints) == 0
def test_stashed_checkpoint_processing(chkFreqPatched, looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ One node in a pool of 5 nodes lags to order the last 3PC-batch in a checkpoint. By the moment when it eventually orders the 3PC-batch it has already received and stashed Checkpoint message from two node, so it processes these stashed messages on completing the checkpoint. After this it receives Checkpoint messages from two other nodes, processes them and stabilizes the checkpoint. """ epsilon = txnPoolNodeSet[-1] sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 4) epsilon.nodeIbStasher.delay(cDelay()) epsilon.nodeIbStasher.delay(chk_delay(sender_filter='Gamma')) epsilon.nodeIbStasher.delay(chk_delay(sender_filter='Delta')) sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.runFor(stabilization_timeout) for inst_id, replica in epsilon.replicas.items(): check_stable_checkpoint(replica, 0) check_num_unstable_checkpoints(replica, 0) check_num_received_checkpoints(replica, 1) check_received_checkpoint_votes(replica, pp_seq_no=5, num_votes=2) epsilon.nodeIbStasher.reset_delays_and_process_delayeds(COMMIT) def check(): for inst_id, replica in epsilon.replicas.items(): check_stable_checkpoint(replica, 0) check_num_unstable_checkpoints(replica, 1) check_last_checkpoint(replica, 5) check_num_received_checkpoints(replica, 1) check_last_received_checkpoint(replica, 5) looper.run( eventually(check, timeout=waits.expectedOrderingTime(len(txnPoolNodeSet)))) epsilon.nodeIbStasher.reset_delays_and_process_delayeds(CHECKPOINT) stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.runFor(stabilization_timeout) for inst_id, replica in epsilon.replicas.items(): check_stable_checkpoint(replica, 5) check_num_unstable_checkpoints(replica, 0) check_num_received_checkpoints(replica, 0)
def do_view_change_with_propagate_primary_on_one_delayed_node( slow_node, nodes, looper, sdk_pool_handle, sdk_wallet_client): slow_stasher = slow_node.nodeIbStasher fast_nodes = [n for n in nodes if n != slow_node] stashers = [n.nodeIbStasher for n in nodes] # Get last prepared certificate in pool lpc = last_prepared_certificate(nodes) # Get pool current view no view_no = lpc[0] with delay_rules(slow_stasher, icDelay()): with delay_rules(slow_stasher, vcd_delay()): with delay_rules(stashers, cDelay()): # Send request request = sdk_send_random_request(looper, sdk_pool_handle, sdk_wallet_client) # Wait until this request is prepared on N-f nodes looper.run(eventually(check_last_prepared_certificate_on_quorum, nodes, (lpc[0], lpc[1] + 1))) # Trigger view change for n in nodes: n.view_changer.on_master_degradation() # Wait until view change is completed on all nodes except slow one waitForViewChange(looper, fast_nodes, expectedViewNo=view_no + 1, customTimeout=waits.expectedPoolViewChangeStartedTimeout(len(nodes))) wait_for_elections_done_on_given_nodes(looper, fast_nodes, getRequiredInstances(len(nodes)), timeout=waits.expectedPoolElectionTimeout(len(nodes))) # Now all the nodes receive Commits # The slow node will accept Commits and order the 3PC-batch in the old view looper.runFor(waits.expectedOrderingTime(getNoInstances(len(nodes)))) # Now slow node receives ViewChangeDones waitForViewChange(looper, [slow_node], expectedViewNo=view_no + 1, customTimeout=waits.expectedPoolViewChangeStartedTimeout(len(nodes))) wait_for_elections_done_on_given_nodes(looper, [slow_node], getRequiredInstances(len(nodes)), timeout=waits.expectedPoolElectionTimeout(len(nodes))) # Now slow node receives InstanceChanges but discards them because already # started propagate primary to the same view. # Finish request gracefully sdk_get_reply(looper, request)
def testOrderingWhenPrePrepareNotReceived(looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ Send commits but delay pre-prepare and prepares such that enough commits are received, now the request should not be ordered until pre-prepare is received and ordering should just happen once, """ delay = 10 non_prim_reps = getNonPrimaryReplicas(txnPoolNodeSet, 0) slow_rep = non_prim_reps[0] slow_node = slow_rep.node slow_node.nodeIbStasher.delay(ppDelay(delay, 0)) slow_node.nodeIbStasher.delay(pDelay(delay, 0)) stash_pp = [] stash_p = [] orig_pp_method = slow_rep._ordering_service.process_preprepare orig_p_method = slow_rep._ordering_service.process_prepare def patched_pp(self, msg, sender): stash_pp.append((msg, sender)) def patched_p(self, msg, sender): stash_p.append((msg, sender)) slow_rep._ordering_service.process_preprepare = \ types.MethodType(patched_pp, slow_rep) slow_rep._ordering_service.process_prepare = \ types.MethodType(patched_p, slow_rep) def chk1(): assert len(slow_rep._ordering_service.commitsWaitingForPrepare) > 0 sdk_send_random_request(looper, sdk_pool_handle, sdk_wallet_client) timeout = waits.expectedPrePrepareTime(len(txnPoolNodeSet)) + delay looper.run(eventually(chk1, retryWait=1, timeout=timeout)) for m, s in stash_pp: orig_pp_method(m, s) for m, s in stash_p: orig_p_method(m, s) def chk2(): assert len(slow_rep._ordering_service.commitsWaitingForPrepare) == 0 assert slow_rep._ordering_service.spylog.count( slow_rep._ordering_service._do_order.__name__) == 1 timeout = waits.expectedOrderingTime(len(non_prim_reps) + 1) + 2 * delay looper.run(eventually(chk2, retryWait=1, timeout=timeout))
def testOrderingWhenPrePrepareNotReceived(looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ Send commits but delay pre-prepare and prepares such that enough commits are received, now the request should not be ordered until pre-prepare is received and ordering should just happen once, """ delay = 10 non_prim_reps = getNonPrimaryReplicas(txnPoolNodeSet, 0) slow_rep = non_prim_reps[0] slow_node = slow_rep.node slow_node.nodeIbStasher.delay(ppDelay(delay, 0)) slow_node.nodeIbStasher.delay(pDelay(delay, 0)) stash_pp = [] stash_p = [] orig_pp_method = slow_rep.processPrePrepare orig_p_method = slow_rep.processPrepare def patched_pp(self, msg, sender): stash_pp.append((msg, sender)) def patched_p(self, msg, sender): stash_p.append((msg, sender)) slow_rep.processPrePrepare = \ types.MethodType(patched_pp, slow_rep) slow_rep.processPrepare = \ types.MethodType(patched_p, slow_rep) def chk1(): assert len(slow_rep.commitsWaitingForPrepare) > 0 sdk_send_random_request(looper, sdk_pool_handle, sdk_wallet_client) timeout = waits.expectedPrePrepareTime(len(txnPoolNodeSet)) + delay looper.run(eventually(chk1, retryWait=1, timeout=timeout)) for m, s in stash_pp: orig_pp_method(m, s) for m, s in stash_p: orig_p_method(m, s) def chk2(): assert len(slow_rep.commitsWaitingForPrepare) == 0 assert slow_rep.spylog.count(slow_rep.doOrder.__name__) == 1 timeout = waits.expectedOrderingTime(len(non_prim_reps) + 1) + 2 * delay looper.run(eventually(chk2, retryWait=1, timeout=timeout))
def test_lagged_checkpoint_completion(chkFreqPatched, looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ One node in a pool lags to order the last 3PC-batch in a checkpoint so that when it eventually orders this 3PC-batch and thus completes the checkpoint it has already received and stashed the corresponding checkpoint messages from all the other nodes. The test verifies that the node successfully processes the stashed checkpoint messages and stabilizes the checkpoint. """ slow_node = txnPoolNodeSet[-1] # All the nodes in the pool normally orders all the 3PC-batches in a # checkpoint except the last 3PC-batch. The last 3PC-batch in the # checkpoint is ordered by all the nodes except one slow node because this # node lags to receive Commits. sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 4) slow_node.nodeIbStasher.delay(cDelay()) sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) # All the other nodes complete the checkpoint and send Checkpoint messages # to others. The slow node receives and stashes these messages because it # has not completed the checkpoint. def check(): for replica in slow_node.replicas.values(): check_stable_checkpoint(replica, 0) check_num_unstable_checkpoints(replica, 0) check_num_received_checkpoints(replica, 1) check_received_checkpoint_votes(replica, pp_seq_no=5, num_votes=len(txnPoolNodeSet) - 1) stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.run(eventually(check, timeout=stabilization_timeout)) # Eventually the slow node receives Commits, orders the last 3PC-batch in # the checkpoint and thus completes it, processes the stashed checkpoint # messages and stabilizes the checkpoint. slow_node.nodeIbStasher.reset_delays_and_process_delayeds() looper.runFor(waits.expectedOrderingTime(len(txnPoolNodeSet))) for replica in slow_node.replicas.values(): check_stable_checkpoint(replica, 5) check_num_unstable_checkpoints(replica, 0) check_num_received_checkpoints(replica, 0)
def testReqExecWhenReturnedByMaster(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) async def chk(): for node in txnPoolNodeSet: entries = node.spylog.getAll(node.processOrdered.__name__) for entry in entries: arg = entry.params['ordered'] result = entry.result if arg.instId == node.instances.masterId: assert result else: assert result is False timeout = waits.expectedOrderingTime(txnPoolNodeSet[0].instances.count) looper.run(eventually(chk, timeout=timeout))
def replied1(looper, nodeSet, client1, committed1, wallet1, faultyNodes): numOfNodes = len(nodeSet) numOfInstances = getNoInstances(numOfNodes) quorum = numOfInstances * (numOfNodes - faultyNodes) def checkOrderedCount(): resp = [ requestReturnedToNode(node, wallet1.defaultId, committed1.reqId, instId) for node in nodeSet for instId in range(numOfInstances) ] assert resp.count(True) >= quorum orderingTimeout = waits.expectedOrderingTime(numOfInstances) looper.run( eventually(checkOrderedCount, retryWait=1, timeout=orderingTimeout)) waitForSufficientRepliesForRequests(looper, client1, requests=[committed1]) return committed1
def replied1(looper, txnPoolNodeSet, sdk_wallet_client, committed1, faultyNodes, sent1): numOfNodes = len(txnPoolNodeSet) numOfInstances = getNoInstances(numOfNodes) quorum = numOfInstances * (numOfNodes - faultyNodes) _, did = sdk_wallet_client def checkOrderedCount(): resp = [ requestReturnedToNode(node, committed1.digest, instId) for node in txnPoolNodeSet for instId in range(numOfInstances) ] assert resp.count(True) >= quorum orderingTimeout = waits.expectedOrderingTime(numOfInstances) looper.run( eventually(checkOrderedCount, retryWait=1, timeout=orderingTimeout)) sdk_get_and_check_replies(looper, sent1) return committed1
def replied1(looper, txnPoolNodeSet, sdk_wallet_client, committed1, faultyNodes, sent1): numOfNodes = len(txnPoolNodeSet) numOfInstances = getNoInstances(numOfNodes) quorum = numOfInstances * (numOfNodes - faultyNodes) _, did = sdk_wallet_client def checkOrderedCount(): resp = [requestReturnedToNode(node, committed1.digest, instId) for node in txnPoolNodeSet for instId in range(numOfInstances)] assert resp.count(True) >= quorum orderingTimeout = waits.expectedOrderingTime(numOfInstances) looper.run(eventually(checkOrderedCount, retryWait=1, timeout=orderingTimeout)) sdk_get_and_check_replies(looper, sent1) return committed1
def testReqExecWhenReturnedByMaster(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) async def chk(): for node in txnPoolNodeSet: entries = node.spylog.getAll( node.processOrdered.__name__) for entry in entries: arg = entry.params['ordered'] result = entry.result if arg.instId == node.instances.masterId: assert result else: assert result is False timeout = waits.expectedOrderingTime( txnPoolNodeSet[0].instances.count) looper.run(eventually(chk, timeout=timeout))
def test_stashed_checkpoint_processing(chkFreqPatched, looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ One node in a pool of 5 nodes lags to order the last 3PC-batch in a checkpoint. By the moment when it eventually orders the 3PC-batch it has already received and stashed Checkpoint message from two node, so it processes these stashed messages on completing the checkpoint. After this it receives Checkpoint messages from two other nodes, processes them and stabilizes the checkpoint. """ epsilon = txnPoolNodeSet[-1] sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 4) epsilon.nodeIbStasher.delay(cDelay()) epsilon.nodeIbStasher.delay(chk_delay(sender_filter='Gamma')) epsilon.nodeIbStasher.delay(chk_delay(sender_filter='Delta')) sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.runFor(stabilization_timeout) for inst_id, replica in epsilon.replicas.items(): assert len(replica._checkpointer._checkpoint_state) == 1 assert (1, 5) in replica._checkpointer._checkpoint_state assert replica._checkpointer._checkpoint_state[(1, 5)].seqNo == 4 assert replica._checkpointer._checkpoint_state[(1, 5)].digest is None assert replica._checkpointer._checkpoint_state[(1, 5)].isStable is False assert len(replica._checkpointer._stashed_recvd_checkpoints) == 1 assert 0 in replica._checkpointer._stashed_recvd_checkpoints assert len(replica._checkpointer._stashed_recvd_checkpoints[0]) == 1 assert (1, 5) in replica._checkpointer._stashed_recvd_checkpoints[0] assert len(replica._checkpointer._stashed_recvd_checkpoints[0][(1, 5)]) == 2 epsilon.nodeIbStasher.reset_delays_and_process_delayeds(COMMIT) def check(): for inst_id, replica in epsilon.replicas.items(): assert len(replica._checkpointer._checkpoint_state) == 1 assert (1, 5) in replica._checkpointer._checkpoint_state assert replica._checkpointer._checkpoint_state[(1, 5)].seqNo == 5 assert replica._checkpointer._checkpoint_state[(1, 5)].digest is not None assert replica._checkpointer._checkpoint_state[(1, 5)].isStable is False assert len(replica._checkpointer._stashed_recvd_checkpoints) == 0 looper.run(eventually(check, timeout=waits.expectedOrderingTime( len(txnPoolNodeSet)))) epsilon.nodeIbStasher.reset_delays_and_process_delayeds(CHECKPOINT) stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.runFor(stabilization_timeout) for inst_id, replica in epsilon.replicas.items(): assert len(replica._checkpointer._checkpoint_state) == 1 assert (1, 5) in replica._checkpointer._checkpoint_state assert replica._checkpointer._checkpoint_state[(1, 5)].seqNo == 5 assert replica._checkpointer._checkpoint_state[(1, 5)].digest is not None assert replica._checkpointer._checkpoint_state[(1, 5)].isStable is True assert len(replica._checkpointer._stashed_recvd_checkpoints) == 0
def test_stashed_checkpoint_processing(chkFreqPatched, looper, txnPoolNodeSet, sdk_wallet_client, sdk_pool_handle): """ One node in a pool of 5 nodes lags to order the last 3PC-batch in a checkpoint. By the moment when it eventually orders the 3PC-batch it has already received and stashed Checkpoint message from two node, so it processes these stashed messages on completing the checkpoint. After this it receives Checkpoint messages from two other nodes, processes them and stabilizes the checkpoint. """ epsilon = txnPoolNodeSet[-1] sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 4) epsilon.nodeIbStasher.delay(cDelay()) epsilon.nodeIbStasher.delay(chk_delay(sender_filter='Gamma')) epsilon.nodeIbStasher.delay(chk_delay(sender_filter='Delta')) sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.runFor(stabilization_timeout) for inst_id, replica in epsilon.replicas.items(): assert len(replica.checkpoints) == 1 assert (1, 5) in replica.checkpoints assert replica.checkpoints[(1, 5)].seqNo == 4 assert replica.checkpoints[(1, 5)].digest is None assert replica.checkpoints[(1, 5)].isStable is False assert len(replica.stashedRecvdCheckpoints) == 1 assert 0 in replica.stashedRecvdCheckpoints assert len(replica.stashedRecvdCheckpoints[0]) == 1 assert (1, 5) in replica.stashedRecvdCheckpoints[0] assert len(replica.stashedRecvdCheckpoints[0][(1, 5)]) == 2 epsilon.nodeIbStasher.reset_delays_and_process_delayeds(COMMIT) def check(): for inst_id, replica in epsilon.replicas.items(): assert len(replica.checkpoints) == 1 assert (1, 5) in replica.checkpoints assert replica.checkpoints[(1, 5)].seqNo == 5 assert replica.checkpoints[(1, 5)].digest is not None assert replica.checkpoints[(1, 5)].isStable is False assert len(replica.stashedRecvdCheckpoints) == 0 looper.run(eventually(check, timeout=waits.expectedOrderingTime( len(txnPoolNodeSet)))) epsilon.nodeIbStasher.reset_delays_and_process_delayeds(CHECKPOINT) stabilization_timeout = \ waits.expectedTransactionExecutionTime(len(txnPoolNodeSet)) looper.runFor(stabilization_timeout) for inst_id, replica in epsilon.replicas.items(): assert len(replica.checkpoints) == 1 assert (1, 5) in replica.checkpoints assert replica.checkpoints[(1, 5)].seqNo == 5 assert replica.checkpoints[(1, 5)].digest is not None assert replica.checkpoints[(1, 5)].isStable is True assert len(replica.stashedRecvdCheckpoints) == 0