def testPrimaryElectionCase5(case5Setup, looper, keySharedNodes): """ Case 5 - A node making primary declarations for a multiple other nodes. Consider 4 nodes A, B, C, and D. Lets say node B is malicious and declares node C as primary to all nodes. Again node B declares node D as primary to all nodes. """ nodeSet = keySharedNodes A, B, C, D = nodeSet.nodes.values() looper.run(checkNodesConnected(nodeSet)) BRep = Replica.generateName(B.name, 0) CRep = Replica.generateName(C.name, 0) DRep = Replica.generateName(D.name, 0) # Node B first sends PRIMARY msgs for Node C to all nodes B.send(Primary(CRep, 0, B.viewNo)) # Node B sends PRIMARY msgs for Node D to all nodes B.send(Primary(DRep, 0, 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 primary declarations for node C from node B # since node B first nominated node C for node in [A, C, D]: logger.debug( "node {} should have primary declaration for C from node B" .format(node)) assert node.elector.primaryDeclarations[0][BRep] == CRep
def testPrimaryElectionCase4(case4Setup, looper): """ Case 4 - A node making multiple primary declarations for a particular node. Consider 4 nodes A, B, C and D. Lets say node B is malicious and is repeatedly declaring Node D as primary """ allNodes = case4Setup A, B, C, D = allNodes looper.run(checkNodesConnected(allNodes)) # Node B sends multiple declarations of node D's 0th protocol instance as # primary to all nodes for i in range(5): B.send(Primary(D.name, 0, B.viewNo)) # No node from node A, node C, node D(node B is malicious anyway so not # considering it) should have more than one primary declaration for node # D since node D is slow. The one primary declaration for node D, # that nodes A, C and D might have would be because of node B def x(): primDecs = list(node.elector.primaryDeclarations[0].values()) assert primDecs.count(D.name) <= 1 for node in (A, C, D): looper.run(eventually(x, retryWait=.5, timeout=2)) ensureElectionsDone(looper=looper, nodes=allNodes, retryWait=1, timeout=45) # Node D should not have any primary replica assert not D.hasPrimary
def sendPrimary(self, instId: int, primaryName: str): """ Declare a primary and broadcast the message. :param instId: the instanceId to which the primary belongs :param primaryName: the name of the primary replica """ replica = self.replicas[instId] self.primaryDeclarations[instId][replica.name] = primaryName self.scheduledPrimaryDecisions[instId] = None logger.debug("{} declaring primary as: {} on the basis of {}".format( replica, primaryName, self.nominations[instId])) self.send(Primary(primaryName, instId, self.viewNo))
def getElectionMsgsForInstance(self, instId: int) -> \ Sequence[Union[Nomination, Primary]]: """ Get nomination and primary messages for instance with id `instId`. """ msgs = [] replica = self.replicas[instId] # If a primary for this instance has been selected then send a # primary declaration for the selected primary if replica.isPrimary is not None: msgs.append(Primary(replica.primaryName, instId, self.viewNo)) else: # If a primary for this instance has not been selected then send # nomination and primary declaration that this node made for the # instance with id `instId` if self.didReplicaNominate(instId): msgs.append(Nomination(self.nominations[instId][ replica.name], instId, self.viewNo)) if self.didReplicaDeclarePrimary(instId): msgs.append(Primary(self.primaryDeclarations[instId][replica.name], instId, self.viewNo)) return msgs
def testBlacklistNodeOnMultiplePrimaryDeclarations(looper, keySharedNodes, ready): """ A node that sends multiple primary declarations must be blacklisted by other nodes """ nodeSet = keySharedNodes A, B, C, D = nodeSet.nodes.values() # B sends more than 2 primary declarations for i in range(3): B.send(Primary(D.name, 0, B.viewNo)) # B should be blacklisted by A, C, D def chk(): for node in A, C, D: assert node.isNodeBlacklisted(B.name) looper.run(eventually(chk, retryWait=1, timeout=3))