def test_client_sends_get_request_to_one_node(looper, client1, wallet1, txnPoolNodeSet): """ Check that client sends read only request to one node only """ client = client1 wallet = wallet1 def sign_and_send(op): signed = wallet.signOp(op) send_signed_requests(client, [signed]) logger.info("Send set request") buy = {'type': 'buy', 'amount': random.randint(10, 100)} sign_and_send(buy) send_args = getAllArgs(client, client.send) rids = send_args[0]['rids'] assert len(rids) > 1 logger.info("Send get request") get_buy = {'type': 'get_buy'} client._read_only_requests.add('get_buy') sign_and_send(get_buy) send_args = getAllArgs(client, client.send) rids = send_args[0]['rids'] assert len(rids) == 1
def requestReturnedToNode(node: TestNode, key: str, instId: int): params = getAllArgs(node, node.processOrdered) # Skipping the view no and time from each ordered request recvdOrderedReqs = [(p['ordered'].instId, p['ordered'].valid_reqIdr[0]) for p in params] expected = (instId, key) return expected in recvdOrderedReqs
def nonPrimaryReceivesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE received by non-primaries must be 1 with zero faults in system, and 0 faults in system. """ passes = 0 for npr in nonPrimaryReplicas: l4 = len([param for param in getAllArgs(npr._ordering_service, npr._ordering_service._add_to_pre_prepares) if param['pp'].reqIdr[0] == propagated1.digest and param['pp'].digest == OrderingService.generate_pp_digest([propagated1.digest, ], get_original_viewno(param['pp']), param['pp'].ppTime)]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += msgCountOK(nodesSize, faultyNodes, l4, numOfMsgsWithZFN, numOfMsgsWithFaults) assert passes >= len(nonPrimaryReplicas) - faultyNodes, \ '2Non-primary receives correct number of pre-prepare -- {}'.format(passes)
def checkPrePrepareReqRecvd(replicas: Iterable[TestReplica], expectedRequest: PrePrepare): for replica in replicas: params = getAllArgs(replica, replica._can_process_pre_prepare) assert expectedRequest.reqIdr in [ p['pre_prepare'].reqIdr for p in params ]
def replicasReceivesCorrectNumberOfCOMMITs(): """ num of commit messages seen by replica must be equal to n - 1; when zero fault and greater than or equal to 2f+1 with faults. """ passes = 0 numOfMsgsWithZFN = nodeCount - 1 numOfMsgsWithFault = 2 * f for r in allReplicas: args = getAllArgs(r, r.processCommit) actualMsgsReceived = len(args) passes += int(msgCountOK(nodeCount, faultyNodes, actualMsgsReceived, numOfMsgsWithZFN, numOfMsgsWithFault)) for arg in args: assert arg['commit'].viewNo == primaryReplica.viewNo and \ arg['commit'].ppSeqNo == primaryReplica.lastPrePrepareSeqNo and \ arg['commit'].digest == prepared1.digest assert r.name != arg['sender'] assert passes >= len(allReplicas) - faultyNodes
def nonPrimaryReceivesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE received by non-primaries must be 1 with zero faults in system, and 0 faults in system. """ passes = 0 for npr in nonPrimaryReplicas: l4 = len([param for param in getAllArgs(npr, npr.addToPrePrepares) if (param['pp'].identifier, param['pp'].reqId, param['pp'].digest) == ( propagated1.identifier, propagated1.reqId, propagated1.digest)]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += msgCountOK(nodesSize, faultyNodes, l4, numOfMsgsWithZFN, numOfMsgsWithFaults) assert passes >= len(nonPrimaryReplicas) - faultyNodes
def primarySentsCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE sent by primary is 1 with or without fault in system but, when primary is faulty no of sent PRE_PREPARE will be zero and primary must be marked as malicious. """ actualMsgs = len([param for param in getAllArgs(primary, primary.doPrePrepare) if (param['reqDigest'].identifier, param['reqDigest'].reqId, param['reqDigest'].digest) == (propagated1.identifier, propagated1.reqId, propagated1.digest) ]) numOfMsgsWithZFN = 1 # TODO: Considering, Primary is not faulty and will always send # PRE-PREPARE. Write separate test for testing when Primary # is faulty assert msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithZFN)
def nonPrimarySeesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be 1; whn zero faulty nodes in system. 2. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be greater than or equal to 0; with faults in system. """ expectedPrePrepareRequest = PrePrepare( instId, primary.viewNo, primary.lastPrePrepareSeqNo, get_utc_epoch(), [propagated1.digest], init_discarded(), Replica.batchDigest([ propagated1, ]), DOMAIN_LEDGER_ID, primary.stateRootHash(DOMAIN_LEDGER_ID), primary.txnRootHash(DOMAIN_LEDGER_ID), 0, True) passes = 0 for npr in nonPrimaryReplicas: actualMsgs = len([ param for param in getAllArgs(npr, npr.processPrePrepare) if (param['pre_prepare'][0:3] + param['pre_prepare'][4:], param['sender']) == (expectedPrePrepareRequest[0:3] + expectedPrePrepareRequest[4:], primary.name) ]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += int( msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)) assert passes >= len(nonPrimaryReplicas) - faultyNodes, \ 'Non-primary sees correct number pre-prepares - {}'.format(passes)
def chk(instId): for node in nodeSet: if node.name != maliciousNode.name: args = getAllArgs(node, Node.processInstanceChange) assert len(args) == 5 for arg in args: assert arg['frm'] == maliciousNode.name
def nonPrimaryReplicasReceiveCorrectNumberOfPREPAREs(): """ num of PREPARE seen by Non primary replica is n - 2 without faults and n-f-2 with faults. """ passes = 0 numOfMsgsWithZFN = nodeCount - 2 numOfMsgsWithFaults = quorums.prepare.value - 1 for npr in nonPrimaryReplicas: actualMsgs = len( [ param for param in getAllArgs( npr._ordering_service, npr._ordering_service.process_prepare) if (param['prepare'].instId, param['prepare'].viewNo, param['prepare'].ppSeqNo) == ( primary.instId, primary.viewNo, primary.lastPrePrepareSeqNo)]) passes += int(msgCountOK(nodeCount, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)) assert passes >= len(nonPrimaryReplicas) - faultyNodes
def testPrimarySendsAPrepareAndMarkedSuspicious(looper, nodeSet, preprepared1): def sendPrepareFromPrimary(instId): primary = getPrimaryReplica(nodeSet, instId) viewNo, ppSeqNo = next(iter(primary.sentPrePrepares.keys())) prepare = Prepare(instId, viewNo, ppSeqNo, preprepared1.digest, time.time()) primary.doPrepare(prepare) def chk(): for r in getNonPrimaryReplicas(nodeSet, instId): l = len([ param for param in getAllArgs(r, r.processPrepare) if param['sender'] == primary.name ]) assert l == 1 looper.run(eventually(chk)) sendPrepareFromPrimary(0) for node in nodeSet: if node in getNonPrimaryReplicas(nodeSet, 0): frm, reason, code = getAllArgs(node, TestNode.reportSuspiciousNode) assert frm == getPrimaryReplica(nodeSet, 0).node.name assert isinstance(reason, SuspiciousNode) assert len(getNodeSuspicions(node, Suspicions.PR_FRM_PRIMARY.code)) == 10
def requestReturnedToNode(node: TestNode, identifier: str, reqId: int, instId: int): params = getAllArgs(node, node.processOrdered) # Skipping the view no and time from each ordered request recvdOrderedReqs = [p['ordered'][:1] + p['ordered'][2:-1] for p in params] expected = (instId, identifier, reqId) return expected in recvdOrderedReqs
def nonPrimaryReplicasReceiveCorrectNumberOfPREPAREs(): """ num of PREPARE seen by Non primary replica is n - 2 without faults and n-f-2 with faults. """ passes = 0 numOfMsgsWithZFN = nodeCount - 2 numOfMsgsWithFaults = quorums.prepare.value - 1 for npr in nonPrimaryReplicas: actualMsgs = len( [ param for param in getAllArgs( npr, npr.processPrepare) if ( param['prepare'].instId, param['prepare'].viewNo, param['prepare'].ppSeqNo) == ( primary.instId, primary.viewNo, primary.lastPrePrepareSeqNo)]) passes += int(msgCountOK(nodeCount, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)) assert passes >= len(nonPrimaryReplicas) - faultyNodes
def primarySentsCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE sent by primary is 1 with or without fault in system but, when primary is faulty no of sent PRE_PREPARE will be zero and primary must be marked as malicious. """ actualMsgs = len([param for param in getAllArgs(primary, primary.sendPrePrepare) if (param['ppReq'].reqIdr[0][0], param['ppReq'].reqIdr[0][1], param['ppReq'].digest) == (propagated1.identifier, propagated1.reqId, primary.batchDigest([propagated1, ])) ]) numOfMsgsWithZFN = 1 # TODO: Considering, Primary is not faulty and will always send # PRE-PREPARE. Write separate test for testing when Primary # is faulty assert msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithZFN), 'Primary sends correct number of per-prepare'
def sentPrepare(replica: TestReplica, viewNo: int = None, ppSeqNo: int = None): params = getAllArgs(replica, TestReplica.doPrepare) return [ param["pp"] for param in params if (viewNo is None or param["pp"].viewNo == viewNo) and ( viewNo is None or param["pp"].viewNo == viewNo) ]
def check_propagates_requested(): # Node should have received delayed PrePrepare assert len(recvdPrePrepareForInstId(lagged_node, 0)) >= 1 # Check that PROPAGATEs are requested by both replicas as PrePrepare has been # received for request that was dropped. tmp = getAllArgs(lagged_node, TestNode.request_propagates) assert len(tmp) == 2
def testPrimarySendsAPrepareAndMarkedSuspicious(looper, txnPoolNodeSet, delay_commits, preprepared1): def sendPrepareFromPrimary(instId): primary = getPrimaryReplica(txnPoolNodeSet, instId) viewNo, ppSeqNo = next(iter(primary._ordering_service.sentPrePrepares.keys())) ppReq = primary._ordering_service.sentPrePrepares[viewNo, ppSeqNo] primary._ordering_service._do_prepare(ppReq) def chk(): for r in getNonPrimaryReplicas(txnPoolNodeSet, instId): l = len([param for param in getAllArgs(r._ordering_service, r._ordering_service.process_prepare) if param['sender'] == primary.name]) assert l == 1 looper.run(eventually(chk)) sendPrepareFromPrimary(0) for node in txnPoolNodeSet: if node in getNonPrimaryReplicas(txnPoolNodeSet, 0): frm, reason, code = getAllArgs(node, TestNode.reportSuspiciousNode) assert frm == getPrimaryReplica(txnPoolNodeSet, 0).node.name assert isinstance(reason, SuspiciousNode) assert len(getNodeSuspicions(node, Suspicions.PR_FRM_PRIMARY.code)) == 10
def nonPrimaryReceivesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE received by non-primaries must be 1 with zero faults in system, and 0 faults in system. """ passes = 0 for npr in nonPrimaryReplicas: l4 = len([ param for param in getAllArgs(npr, npr.addToPrePrepares) if (param['pp'].reqIdr[0][0], param['pp'].reqIdr[0][1], param['pp'].digest) == (propagated1.identifier, propagated1.reqId, primary.batchDigest([ propagated1, ])) ]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += msgCountOK(nodesSize, faultyNodes, l4, numOfMsgsWithZFN, numOfMsgsWithFaults) assert passes >= len(nonPrimaryReplicas) - faultyNodes, \ 'Non-primary receives correct number of pre-prepare -- {}'.format(passes)
def nonPrimarySeesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be 1; whn zero faulty nodes in system. 2. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be greater than or equal to 0; with faults in system. """ expectedPrePrepareRequest = PrePrepare(instId, primary.viewNo, primary.lastPrePrepareSeqNo, propagated1.identifier, propagated1.reqId, propagated1.digest, time.time()) passes = 0 for npr in nonPrimaryReplicas: actualMsgs = len([ param for param in getAllArgs(npr, npr.processPrePrepare) if (param['pp'][:-1], param['sender']) == (expectedPrePrepareRequest[:-1], primary.name) ]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += int( msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)) assert passes >= len(nonPrimaryReplicas) - faultyNodes
def sentPrepare(replica: TestReplica, viewNo: int = None, ppSeqNo: int = None): params = getAllArgs(replica._ordering_service, OrderingService._do_prepare) return [ param["pp"] for param in params if (viewNo is None or param["pp"].viewNo == viewNo) and ( viewNo is None or param["pp"].viewNo == viewNo) ]
def chk(instId): for node in txnPoolNodeSet: if node.name != maliciousNode.name: args = getAllArgs(node, ViewChanger.process_instance_change_msg) assert len(args) == 5 for arg in args: assert arg['frm'] == maliciousNode.name
def chk(): for r in getNonPrimaryReplicas(nodeSet, instId): l = len([ param for param in getAllArgs(r, r.processPrepare) if param['sender'] == primary.name ]) assert l == 1
def replicasReceivesCorrectNumberOfCOMMITs(): """ num of commit messages seen by replica must be equal to n - 1; when zero fault and greater than or equal to 2f+1 with faults. """ passes = 0 numOfMsgsWithZFN = nodeCount - 1 numOfMsgsWithFault = 2 * f for r in allReplicas: args = getAllArgs(r, r.processCommit) actualMsgsReceived = len(args) passes += int( msgCountOK(nodeCount, faultyNodes, actualMsgsReceived, numOfMsgsWithZFN, numOfMsgsWithFault)) for arg in args: assert arg['commit'].viewNo == primaryReplica.viewNo and \ arg['commit'].ppSeqNo == primaryReplica.lastPrePrepareSeqNo and \ arg['commit'].digest == prepared1.digest assert r.name != arg['sender'] assert passes >= len(allReplicas) - faultyNodes
def primarySentsCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE sent by primary is 1 with or without fault in system but, when primary is faulty no of sent PRE_PREPARE will be zero and primary must be marked as malicious. """ actualMsgs = len([param for param in getAllArgs(primary._ordering_service, primary._ordering_service.send_pre_prepare) if param['ppReq'].reqIdr[0] == propagated1.digest and param['ppReq'].digest == primary._ordering_service.generate_pp_digest([propagated1.digest], get_original_viewno(param['ppReq']), param['ppReq'].ppTime)]) numOfMsgsWithZFN = 1 # TODO: Considering, Primary is not faulty and will always send # PRE-PREPARE. Write separate test for testing when Primary # is faulty assert msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithZFN), 'Primary sends correct number of per-prepare'
def primaryDontSendAnyPREPAREs(): """ 1. no of PREPARE sent by primary should be 0 """ for r in allReplicas: for param in getAllArgs(r, Replica.processPrepare): sender = param['sender'] assert sender != primary.name
def requestReturnedToNode(node: TestNode, key: str, instId: int): params = getAllArgs(node, node.processOrdered) # Skipping the view no and time from each ordered request recvdOrderedReqs = [ (p['ordered'].instId, p['ordered'].valid_reqIdr[0]) for p in params] expected = (instId, key) return expected in recvdOrderedReqs
def g(): for node in nodeSet: if node.name != maliciousNode.name: frm, reason, code = getAllArgs(node, Node.reportSuspiciousNode) assert frm == maliciousNode.name assert isinstance(reason, SuspiciousNode) assert len(getNodeSuspicions(node, Suspicions.FREQUENT_INST_CHNG.code)) == 13
def primarySeesCorrectNumberOfPREPREPAREs(): """ no of PRE-PREPARE as seen by processPrePrepare method for primary must be 0 with or without faults in system """ l1 = len([param for param in getAllArgs(primary, primary.processPrePrepare)]) assert l1 == 0, 'Primary {} sees no pre-prepare'.format(primary)
def chk(instId): for node in nodeSet: if node.name != maliciousNode.name: args = getAllArgs(node, ViewChanger.process_instance_change_msg) assert len(args) == 5 for arg in args: assert arg['frm'] == maliciousNode.name
def checkPrepareReqSent(replica: TestReplica, identifier: str, reqId: int): paramsList = getAllArgs(replica, replica.canSendPrepare) rv = getAllReturnVals(replica, replica.canSendPrepare) for params in paramsList: req = params['request'] assert req.identifier == identifier assert req.reqId == reqId assert all(rv)
def getNodeSuspicions(node: TestNode, code: int = None): params = getAllArgs(node, TestNode.reportSuspiciousNode) if params and code is not None: params = [ param for param in params if 'code' in param and param['code'] == code ] return params
def primaryDontSendAnyPREPAREs(): """ 1. no of PREPARE sent by primary should be 0 """ for r in allReplicas: for param in getAllArgs(r._ordering_service, OrderingService.process_prepare): sender = param['sender'] assert sender != primary.name
def checkPrepareReqSent(replica: TestReplica, key: str, view_no: int): paramsList = getAllArgs(replica, replica.canPrepare) rv = getAllReturnVals(replica, replica.canPrepare) args = [p["ppReq"].reqIdr for p in paramsList if p["ppReq"].viewNo == view_no] assert [key] in args idx = args.index([key]) assert rv[idx]
def chk(): for r in getNonPrimaryReplicas(txnPoolNodeSet, instId): l = len([ param for param in getAllArgs( r._ordering_service, r._ordering_service.process_prepare) if param['sender'] == primary.name ]) assert l == 1
def checkPrepareReqSent(replica: TestReplica, key: str, view_no: int): paramsList = getAllArgs(replica, replica.canPrepare) rv = getAllReturnVals(replica, replica.canPrepare) args = [ p["ppReq"].reqIdr for p in paramsList if p["ppReq"].viewNo == view_no ] assert [key] in args idx = args.index([key]) assert rv[idx]
def check_propagates_requested(): # Node should have received delayed PrePrepare assert len(recvdPrePrepareForInstId(lagged_node, 0)) >= 1 # Check that PROPAGATEs are requested by at least one replica as PrePrepare has been # received for request that was dropped. # We can check that the number of requested propagates is more or equal to 1, # since the first replica who sees non-finalized requests sends MessageReq for Propagates, # and it can receive Propagates before a PrePrepare for the next replica is received, # so that the for the second replica all requests will be already finalized. assert len(getAllArgs(lagged_node, TestNode.request_propagates)) == 2
def checkViewChangeInitiatedForNode(node: TestNode, proposedViewNo: int): """ Check if view change initiated for a given node :param node: The node to check for :param proposedViewNo: The view no which is proposed :return: """ params = [args for args in getAllArgs(node.view_changer, ViewChanger.start_view_change)] assert len(params) > 0 args = params[-1] assert args["proposedViewNo"] == proposedViewNo assert node.viewNo == proposedViewNo
def checkViewChangeInitiatedForNode(node: TestNode, proposedViewNo: int): """ Check if view change initiated for a given node :param node: The node to check for :param proposedViewNo: The view no which is proposed :return: """ params = [args for args in getAllArgs(node.view_changer, ViewChanger.startViewChange)] assert len(params) > 0 args = params[-1] assert args["proposedViewNo"] == proposedViewNo assert node.viewNo == proposedViewNo assert node.elector.viewNo == proposedViewNo
def nonPrimarySeesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be 1; whn zero faulty nodes in system. 2. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be greater than or equal to 0; with faults in system. """ expectedPrePrepareRequest = PrePrepare( instId, primary.viewNo, primary.lastPrePrepareSeqNo, get_utc_epoch(), [propagated1.digest], init_discarded(), Replica.batchDigest([propagated1, ]), DOMAIN_LEDGER_ID, primary.stateRootHash(DOMAIN_LEDGER_ID), primary.txnRootHash(DOMAIN_LEDGER_ID), 0, True, primary.stateRootHash(POOL_LEDGER_ID) ) passes = 0 for npr in nonPrimaryReplicas: actualMsgs = len([param for param in getAllArgs(npr, npr.processPrePrepare) if (param['pre_prepare'][0:3] + param['pre_prepare'][4:], param['sender']) == ( expectedPrePrepareRequest[0:3] + expectedPrePrepareRequest[4:], primary.name)]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += int(msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)) assert passes >= len(nonPrimaryReplicas) - faultyNodes, \ 'Non-primary sees correct number pre-prepares - {}'.format(passes)
def testPrePrepareProcessedInOrder(perf_chk_patched, looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): """ A non-primary receives PRE-PREPARE out of order, it receives with ppSeqNo 2 earlier than it receives the one with ppSeqNo 1 but it stashes the one with ppSeqNo 2 and only unstashes it for processing once it has processed PRE-PREPARE with ppSeqNo 1 :return: """ tconf = perf_chk_patched pr, otherR = getPrimaryReplica(txnPoolNodeSet, instId=0), \ getNonPrimaryReplicas(txnPoolNodeSet, instId=0) otherNodes = [r.node for r in otherR] ppsToDelay = 2 delayeds = 0 expectedDelayeds = (len(txnPoolNodeSet) - 1) * ppsToDelay delayedPpSeqNos = set() def specificPrePrepares(wrappedMsg): nonlocal delayeds msg, sender = wrappedMsg if isinstance(msg, PrePrepare) and delayeds < expectedDelayeds: delayeds += 1 delayedPpSeqNos.add(msg.ppSeqNo) logger.debug('ppSeqNo {} would be delayed'.format(msg.ppSeqNo)) return pp_delay for node in otherNodes: logger.debug('{} would be delaying reception of some pre-prepares'. format(node)) node.nodeIbStasher.delay(specificPrePrepares) sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, (ppsToDelay + 1) * tconf.Max3PCBatchSize) checkNodesHaveSameRoots(txnPoolNodeSet) for r in otherR: seqNos = [a['pp'].ppSeqNo for a in getAllArgs(r, r.addToPrePrepares)] seqNos.reverse() assert sorted(seqNos) == seqNos
def g(node: TestNode): """ 1. no of propagate received by node must be n -1 with zero faulty nodes in system; where n = num of nodes 2. no of propagate received by node must be greater than or equal to f + 1 """ actualMsgs = len([x for x in getAllArgs(node, Node.processPropagate) if x['msg'].request[f.REQ_ID.nm] == request.reqId and x['msg'].request[f.IDENTIFIER.nm] == request.identifier and x['msg'].request[OPERATION] == request.operation]) numOfMsgsWithZFN = nodesSize - 1 numOfMsgsWithFaults = faultyNodes + 1 assert msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)
def primarySentsCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE sent by primary is 1 with or without fault in system but, when primary is faulty no of sent PRE_PREPARE will be zero and primary must be marked as malicious. """ actualMsgs = len([param for param in getAllArgs(primary, primary.sendPrePrepare) if param['ppReq'].reqIdr[0] == propagated1.digest and param['ppReq'].digest == primary.batchDigest([propagated1, ])]) numOfMsgsWithZFN = 1 # TODO: Considering, Primary is not faulty and will always send # PRE-PREPARE. Write separate test for testing when Primary # is faulty assert msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithZFN), 'Primary sends correct number of per-prepare'
def nonPrimarySeesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be 1; whn zero faulty nodes in system. 2. no of PRE-PREPARE as seen by processPrePrepare method for non-primaries must be greater than or equal to 0; with faults in system. """ expectedPrePrepareRequest = PrePrepare( instId, primary.viewNo, primary.lastPrePrepareSeqNo, propagated1.identifier, propagated1.reqId, propagated1.digest, time.time()) passes = 0 for npr in nonPrimaryReplicas: actualMsgs = len([param for param in getAllArgs(npr, npr.processPrePrepare) if (param['pp'][:-1], param['sender']) == ( expectedPrePrepareRequest[:-1], primary.name)]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += int(msgCountOK(nodesSize, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)) assert passes >= len(nonPrimaryReplicas) - faultyNodes
def nonPrimaryReceivesCorrectNumberOfPREPREPAREs(): """ 1. no of PRE-PREPARE received by non-primaries must be 1 with zero faults in system, and 0 faults in system. """ passes = 0 for npr in nonPrimaryReplicas: l4 = len([param for param in getAllArgs(npr, npr.addToPrePrepares) if param['pp'].reqIdr[0] == propagated1.digest and param['pp'].digest == primary.batchDigest([propagated1, ])]) numOfMsgsWithZFN = 1 numOfMsgsWithFaults = 0 passes += msgCountOK(nodesSize, faultyNodes, l4, numOfMsgsWithZFN, numOfMsgsWithFaults) assert passes >= len(nonPrimaryReplicas) - faultyNodes, \ 'Non-primary receives correct number of pre-prepare -- {}'.format(passes)
def primaryReceivesCorrectNumberOfPREPAREs(): """ num of PREPARE seen by primary replica is n - 1; n = num of nodes without fault, and greater than or equal to n-f-1 with faults. """ actualMsgs = len([param for param in getAllArgs(primary, primary.processPrepare) if (param['prepare'].instId, param['prepare'].viewNo, param['prepare'].ppSeqNo) == ( primary.instId, primary.viewNo, primary.lastPrePrepareSeqNo) and param['sender'] != primary.name]) numOfMsgsWithZFN = nodeCount - 1 numOfMsgsWithFaults = quorums.prepare.value assert msgCountOK(nodeCount, faultyNodes, actualMsgs, numOfMsgsWithZFN, numOfMsgsWithFaults)
def printedTokens(self): return getAllArgs(self, TestCli.printTokens)
def check_propagates_requested(): # Node should have received delayed PrePrepare assert len(recvdPrePrepareForInstId(lagged_node, 0)) == 1 # Check that PROPAGATEs are requested by both replicas as PrePrepare has been # received for request that was dropped. assert len(getAllArgs(lagged_node, TestNode.request_propagates)) == 2
def recvdPropagate(node: TestNode): return getAllArgs(node, TestNode.processPropagate)
def recvdRequest(node: TestNode): return getAllArgs(node, TestNode.processRequest)
def forwardedRequest(node: TestNode): return getAllArgs(node, TestNode.forward)
def recvdCommitForInstId(node: TestNode, instId: int): params = getAllArgs(node.replicas[instId], Replica.dispatchThreePhaseMsg) return [p for p in params if isinstance(p['msg'], Commit)]
def sentPropagate(node: TestNode): params = getAllArgs(node, TestNode.send) return [p for p in params if isinstance(p['msg'], Propagate)]
def recvd_pre_prepares(replica: TestReplica): return [arg['pre_prepare'] for arg in getAllArgs(replica, TestReplica.processPrePrepare)]
def sentPrepare(replica: TestReplica, viewNo: int = None, ppSeqNo: int = None): params = getAllArgs(replica, TestReplica.doPrepare) return [param["pp"] for param in params if (viewNo is None or param["pp"].viewNo == viewNo) and (viewNo is None or param["pp"].viewNo == viewNo)]
def printeds(self): return getAllArgs(self, TestCli.print)
def processedPrePrepare(replica: TestReplica): return getAllArgs(replica, TestReplica.addToPrePrepares)