def testPrimaryElectionCase2(case2Setup, looper, keySharedNodes): """ Case 2 - A node making nominations for a multiple other nodes. Consider 4 nodes A, B, C, and D. Lets say node B is malicious and nominates node C to all nodes. Again node B nominates node D to all nodes. """ nodeSet = keySharedNodes A, B, C, D = nodeSet.nodes.values() looper.run(checkNodesConnected(nodeSet)) # Node B sends multiple NOMINATE msgs but only after A has nominated itself looper.run(eventually(checkNomination, A, A.name, retryWait=.25, timeout=1)) instId = getSelfNominationByNode(A) BRep = Replica.generateName(B.name, instId) CRep = Replica.generateName(C.name, instId) DRep = Replica.generateName(D.name, instId) # Node B first sends NOMINATE msgs for Node C to all nodes B.send(Nomination(CRep, instId, B.viewNo)) # Node B sends NOMINATE msgs for Node D to all nodes B.send(Nomination(DRep, instId, B.viewNo)) # Ensure elections are done ensureElectionsDone(looper=looper, nodes=nodeSet, retryWait=1, timeout=45) # All nodes from node A, node C, node D(node B is malicious anyway so # not considering it) should have nomination for node C from node B since # node B first nominated node C for node in [A, C, D]: assert node.elector.nominations[instId][BRep] == CRep
def checkPrimaryPlacement(): # Node names sorted by rank sortedNodeNames = sorted(nodeSet.nodes.values(), key=operator.attrgetter("rank")) for idx, node in enumerate(sortedNodeNames): # For instance 0, the primary replica should be on the node with rank 0 if idx == 0: primaryName = Replica.generateName(sortedNodeNames[idx], 0) assert node.replicas[0].isPrimary assert not node.replicas[1].isPrimary assert not node.replicas[2].isPrimary # For instance 1, the primary replica should be on the node with rank 1 if idx == 1: primaryName = Replica.generateName(sortedNodeNames[idx], 1) assert not node.replicas[0].isPrimary assert node.replicas[1].isPrimary assert not node.replicas[2].isPrimary # For instance 2, the primary replica should be on the node with rank 2 if idx == 2: primaryName = Replica.generateName(sortedNodeNames[idx], 2) assert not node.replicas[0].isPrimary assert not node.replicas[1].isPrimary assert node.replicas[2].isPrimary
def checkPresence(): for node in [C, D]: commReqs = getCommits(node, 0) assert len(commReqs) > 0 assert Replica.generateName(A.name, 0) not in commReqs[0][1] commReqs = getCommits(node, 1) assert len(commReqs) > 0 assert Replica.generateName(A.name, 1) in commReqs[0][1]
def checkNomination(node: TestNode, nomineeName: str): matches = [replica.name for instId, replica in enumerate(node.elector.replicas) if node.elector.didReplicaNominate(instId) is True and replica.name in node.elector.nominations[instId] and node.elector.nominations[instId][replica.name] == Replica.generateName(nomineeName, instId)] assert len(matches) > 0 return matches[0]
def getSelfNominationByNode(node: TestNode) -> int: """ This function returns the index of the protocol instance for which it nominated itself @param node: the node @return: the protocol instance index """ for instId, replica in enumerate(node.elector.replicas): name = Replica.generateName(node.name, instId) if node.elector.nominations.get(instId, {}).get(name, None) == name: return instId