def doPrePrepare(self, reqDigest: ReqDigest) -> None: """ Broadcast a PRE-PREPARE to all the replicas. :param reqDigest: a tuple with elements identifier, reqId, and digest """ if not self.node.isParticipating: logger.error("Non participating node is attempting PRE-PREPARE. " "This should not happen.") return if self.lastPrePrepareSeqNo == self.H: logger.debug("{} stashing PRE-PREPARE {} since outside greater " "than high water mark {}".format( self, (self.viewNo, self.lastPrePrepareSeqNo + 1), self.H)) self.stashingWhileOutsideWaterMarks.append(reqDigest) return self.lastPrePrepareSeqNo += 1 tm = time.time() * 1000 logger.debug("{} Sending PRE-PREPARE {} at {}".format( self, (self.viewNo, self.lastPrePrepareSeqNo), time.perf_counter())) prePrepareReq = PrePrepare(self.instId, self.viewNo, self.lastPrePrepareSeqNo, *reqDigest, tm) self.sentPrePrepares[self.viewNo, self.lastPrePrepareSeqNo] = (reqDigest.key, tm) self.send(prePrepareReq, TPCStat.PrePrepareSent)
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 testPrePrepareWithHighSeqNo(looper, nodeSet, propagated1): def chk(): for r in getNonPrimaryReplicas(nodeSet, instId): nodeSuspicions = len( getNodeSuspicions(r.node, Suspicions.WRONG_PPSEQ_NO.code)) assert nodeSuspicions == 1 def checkPreprepare(replica, viewNo, ppSeqNo, req, numOfPrePrepares): assert (replica.prePrepares[viewNo, ppSeqNo][0]) == \ (req.identifier, req.reqId, req.digest) primary = getPrimaryReplica(nodeSet, instId) nonPrimaryReplicas = getNonPrimaryReplicas(nodeSet, instId) req = propagated1.reqDigest primary.doPrePrepare(req) for np in nonPrimaryReplicas: looper.run( eventually(checkPreprepare, np, primary.viewNo, primary.lastPrePrepareSeqNo - 1, req, 1, retryWait=.5, timeout=10)) newReqDigest = ReqDigest(req.identifier, req.reqId + 1, req.digest) incorrectPrePrepareReq = PrePrepare(instId, primary.viewNo, primary.lastPrePrepareSeqNo + 2, *newReqDigest, time.time()) primary.send(incorrectPrePrepareReq, TPCStat.PrePrepareSent) looper.run(eventually(chk, retryWait=1, timeout=50))
def testReplicasRejectSamePrePrepareMsg(looper, nodeSet, client1, wallet1): """ Replicas should not accept PRE-PREPARE for view "v" and prepare sequence number "n" if it has already accepted a request with view number "v" and sequence number "n" """ numOfNodes = 4 fValue = getMaxFailures(numOfNodes) request1 = sendRandomRequest(wallet1, client1) result1 = looper.run( eventually(checkSufficientRepliesRecvd, client1.inBox, request1.reqId, fValue, retryWait=1, timeout=5)) logger.debug("request {} gives result {}".format(request1, result1)) primaryRepl = getPrimaryReplica(nodeSet) logger.debug("Primary Replica: {}".format(primaryRepl)) logger.debug( "Decrementing the primary replica's pre-prepare sequence number by " "one...") primaryRepl.lastPrePrepareSeqNo -= 1 request2 = sendRandomRequest(wallet1, client1) looper.run( eventually(checkPrePrepareReqSent, primaryRepl, request2, retryWait=1, timeout=10)) nonPrimaryReplicas = getNonPrimaryReplicas(nodeSet) logger.debug("Non Primary Replicas: " + str(nonPrimaryReplicas)) prePrepareReq = PrePrepare(primaryRepl.instId, primaryRepl.viewNo, primaryRepl.lastPrePrepareSeqNo, wallet1.defaultId, request2.reqId, request2.digest, time.time()) logger.debug("""Checking whether all the non primary replicas have received the pre-prepare request with same sequence number""") looper.run( eventually(checkPrePrepareReqRecvd, nonPrimaryReplicas, prePrepareReq, retryWait=1, timeout=10)) logger.debug("""Check that none of the non primary replicas didn't send any prepare message " in response to the pre-prepare message""") for npr in nonPrimaryReplicas: with pytest.raises(AssertionError): looper.run( eventually(checkPrepareReqSent, npr, wallet1.defaultId, request2.reqId, retryWait=1, timeout=10))
def evilSendPrePrepareRequest(self, reqDigest: ReqDigest): logger.debug("EVIL: Creating pre-prepare message for request {}". format(reqDigest)) tm = time.time() prePrepare = PrePrepare(self.instId, self.viewNo, self.prePrepareSeqNo, *reqDigest, tm) self.sentPrePrepares[self.viewNo, self.prePrepareSeqNo] = (reqDigest, tm) sendDup(self, prePrepare, TPCStat.PrePrepareSent, count)
def evilSendPrePrepareRequest(self, reqDigest: ReqDigest): logger.debug("EVIL: Creating pre-prepare message for request {}". format(reqDigest)) reqDigest = ReqDigest(reqDigest.identifier, reqDigest.reqId, "random") tm = time.time() prePrepare = PrePrepare(self.instId, self.viewNo, self.prePrepareSeqNo, *reqDigest, tm) self.sentPrePrepares[self.viewNo, self.prePrepareSeqNo] = (reqDigest, tm) self.send(prePrepare, TPCStat.PrePrepareSent)
def sendPrePrepareFromNonPrimary(replica): firstNpr.doPrePrepare(propagated1.reqDigest) return PrePrepare( replica.instId, firstNpr.viewNo, firstNpr.prePrepareSeqNo, propagated1.identifier, propagated1.reqId, propagated1.digest, time.time())
def testNodeDiscardMessageFromUnknownView(txnPoolNodeSet, nodeSetWithNodeAddedAfterSomeTxns, newNodeCaughtUp, tdirWithPoolTxns, tconf, allPluginsPath): """ Node discards 3-phase and election messages from view nos that it does not know of (view nos before it joined the pool) :return: """ looper, nodeX, client, wallet, _, _ = nodeSetWithNodeAddedAfterSomeTxns viewNo = nodeX.viewNo # Delay processing of PRE-PREPARE from all non primary replicas of master # so master's performance falls and view changes delayNonPrimaries(txnPoolNodeSet, 0, 10) sendReqsToNodesAndVerifySuffReplies(looper, wallet, client, 4) looper.run(eventually(partial(checkViewNoForNodes, txnPoolNodeSet, viewNo + 1), retryWait=1, timeout=20)) newStewardName = "testClientSteward" + randomString(3) nodeName = "Theta" _, _, nodeTheta = addNewStewardAndNode(looper, client, wallet, newStewardName, nodeName, tdirWithPoolTxns, tconf, allPluginsPath) txnPoolNodeSet.append(nodeTheta) looper.run(checkNodesConnected(txnPoolNodeSet)) looper.run(client.ensureConnectedToNodes()) looper.run(eventually(checkNodeLedgersForEquality, nodeTheta, *txnPoolNodeSet[:-1], retryWait=1, timeout=5)) checkProtocolInstanceSetup(looper, txnPoolNodeSet, retryWait=1, timeout=10) electMsg = Nomination(nodeX.name, 0, viewNo) threePMsg = PrePrepare( 0, viewNo, 10, wallet.defaultId, wallet._getIdData().lastReqId+1, "random digest", time.time() ) ridTheta = nodeX.nodestack.getRemote(nodeTheta.name).uid nodeX.send(electMsg, ridTheta) nodeX.send(threePMsg, ridTheta) nodeX.send(electMsg, ridTheta) looper.run(eventually(checkDiscardMsg, [nodeTheta, ], electMsg, 'un-acceptable viewNo', retryWait=1, timeout=5)) nodeX.send(threePMsg, ridTheta) looper.run(eventually(checkDiscardMsg, [nodeTheta, ], threePMsg, 'un-acceptable viewNo', retryWait=1, timeout=5))
def doPrePrepare(self, reqDigest: ReqDigest) -> None: """ Broadcast a PRE-PREPARE to all the replicas. :param reqDigest: a tuple with elements identifier, reqId, and digest """ logger.debug("{} Sending PRE-PREPARE at {}".format( self, time.perf_counter())) self.prePrepareSeqNo += 1 tm = time.time() * 1000 prePrepareReq = PrePrepare(self.instId, self.viewNo, self.prePrepareSeqNo, *reqDigest, tm) self.sentPrePrepares[self.viewNo, self.prePrepareSeqNo] = (reqDigest, tm) self.send(prePrepareReq, TPCStat.PrePrepareSent)