Search in sources :

Example 1 with DurabilityCoordinator

use of bftsmart.tom.server.defaultservices.durability.DurabilityCoordinator in project bftsmart by blockchain-jd-com.

the class DurableStateManager method SMReplyDeliver.

@Override
public void SMReplyDeliver(SMMessage msg, boolean isBFT) {
    lockTimer.lock();
    CSTSMMessage reply = (CSTSMMessage) msg;
    if (topology.getStaticConf().isStateTransferEnabled()) {
        LOGGER.debug("(TOMLayer.SMReplyDeliver) The state transfer protocol is enabled");
        LOGGER.info("(TOMLayer.SMReplyDeliver) I received a state reply for CID {} from replica {}", reply.getCID(), reply.getSender());
        LOGGER.info("--- Received CID: {}, Waiting CID: {}", reply.getCID(), waitingCID);
        if (waitingCID != -1 && reply.getCID() == waitingCID) {
            int currentRegency = -1;
            int currentLeader = -1;
            View currentView = null;
            if (!appStateOnly) {
                senderRegencies.put(reply.getSender(), reply.getRegency());
                senderLeaders.put(reply.getSender(), reply.getLeader());
                senderViews.put(reply.getSender(), reply.getView());
                // msg.getState().getCertifiedDecision(SVController));
                if (enoughRegencies(reply.getRegency()))
                    currentRegency = reply.getRegency();
                if (enoughLeaders(reply.getLeader()))
                    currentLeader = reply.getLeader();
                if (enoughViews(reply.getView())) {
                    currentView = reply.getView();
                    if (!currentView.isMember(topology.getStaticConf().getProcessId())) {
                        LOGGER.error("Not a member!");
                    }
                }
            // if (enoughProofs(waitingCID, this.tomLayer.getSynchronizer().getLCManager()))
            // currentProof = msg.getState().getCertifiedDecision(SVController);
            } else {
                currentLeader = tomLayer.execManager.getCurrentLeader();
                currentRegency = tomLayer.getSynchronizer().getLCManager().getLastReg();
                currentView = topology.getCurrentView();
            }
            LOGGER.info("(TOMLayer.SMReplyDeliver) The reply is for the CID that I want!");
            NodeNetwork address = reply.getCstConfig().getAddress();
            Socket clientSocket;
            ApplicationState stateReceived = null;
            try {
                clientSocket = new Socket(address.getHost(), address.getConsensusPort());
                ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
                stateReceived = (ApplicationState) in.readObject();
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if (stateReceived instanceof CSTState) {
                senderStates.put(reply.getSender(), stateReceived);
                if (reply.getSender() == cstRequest.getCheckpointReplica())
                    this.stateCkp = (CSTState) stateReceived;
                if (reply.getSender() == cstRequest.getLogLower())
                    this.stateLower = (CSTState) stateReceived;
                if (reply.getSender() == cstRequest.getLogUpper())
                    this.stateUpper = (CSTState) stateReceived;
            }
            if (senderStates.size() == 3) {
                CommandsInfo[] lowerLog = stateLower.getLogLower();
                CommandsInfo[] upperLog = stateUpper.getLogUpper();
                LOGGER.debug("lowerLog ");
                if (lowerLog != null)
                    LOGGER.debug("Lower log length size: {} ", lowerLog.length);
                LOGGER.debug("upperLog ");
                if (upperLog != null)
                    LOGGER.debug("Upper log length size: {} ", upperLog.length);
                boolean haveState = false;
                byte[] lowerbytes = TOMUtil.getBytes(lowerLog);
                LOGGER.debug("Log lower bytes size: {}", lowerbytes.length);
                byte[] upperbytes = TOMUtil.getBytes(upperLog);
                LOGGER.debug("Log upper bytes size: {}", upperbytes.length);
                byte[] lowerLogHash = new byte[0];
                byte[] upperLogHash = new byte[0];
                try {
                    lowerLogHash = TOMUtil.computeHash(lowerbytes);
                    upperLogHash = TOMUtil.computeHash(upperbytes);
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
                // validate lower log
                if (Arrays.equals(stateCkp.getHashLogLower(), lowerLogHash))
                    haveState = true;
                else
                    LOGGER.error("Lower log don't match");
                // validate upper log
                if (!haveState || !Arrays.equals(stateCkp.getHashLogUpper(), upperLogHash)) {
                    haveState = false;
                    LOGGER.error("Upper log don't match");
                }
                CSTState statePlusLower = new CSTState(stateCkp.getSerializedState(), TOMUtil.getBytes(stateCkp.getSerializedState()), stateLower.getLogLower(), stateCkp.getHashLogLower(), null, null, stateCkp.getCheckpointCID(), stateUpper.getCheckpointCID(), topology.getStaticConf().getProcessId());
                if (haveState) {
                    // validate checkpoint
                    LOGGER.debug("validating checkpoint!!!");
                    dt.getRecoverer().setState(statePlusLower);
                    byte[] currentStateHash = ((DurabilityCoordinator) dt.getRecoverer()).getCurrentStateHash();
                    if (!Arrays.equals(currentStateHash, stateUpper.getHashCheckpoint())) {
                        LOGGER.error("ckp hash don't match");
                        haveState = false;
                    }
                }
                LOGGER.info("-- current regency: {} ", currentRegency);
                LOGGER.info("-- current leader: {}", currentLeader);
                LOGGER.info("-- current view: {}", currentView);
                if (currentRegency > -1 && currentLeader > -1 && currentView != null && haveState && (!isBFT || /* currentProof != null || */
                appStateOnly)) {
                    LOGGER.info("---- RECEIVED VALID STATE ----");
                    LOGGER.info("(TOMLayer.SMReplyDeliver) The state of those replies is good!");
                    LOGGER.info("(TOMLayer.SMReplyDeliver) CID State requested: {}", reply.getCID());
                    LOGGER.info("(TOMLayer.SMReplyDeliver) CID State received: {}", stateUpper.getLastCID());
                    if (currentRegency > tomLayer.getSynchronizer().getLCManager().getCurrentRegency().getId()) {
                        tomLayer.getSynchronizer().getLCManager().jumpToRegency(new LeaderRegency(currentLeader, currentRegency));
                        tomLayer.execManager.setNewLeader(currentLeader);
                    }
                    // one
                    if (currentRegency > 0)
                        tomLayer.getSynchronizer().removeSTOPretransmissions(currentRegency - 1);
                    LOGGER.debug("trying to acquire deliverlock");
                    dt.deliverLock();
                    LOGGER.debug("acquired");
                    // this makes the isRetrievingState() evaluates to false
                    waitingCID = -1;
                    dt.update(stateUpper);
                    // synchronization phase
                    if (!appStateOnly && execManager.stopped()) {
                        Queue<ConsensusMessage> stoppedMsgs = execManager.getStoppedMsgs();
                        for (ConsensusMessage stopped : stoppedMsgs) {
                            if (stopped.getNumber() > state.getLastCID())
                                execManager.addOutOfContextMessage(stopped);
                        }
                        execManager.clearStopped();
                        execManager.restart();
                    }
                    LOGGER.info("Processing out of context messages");
                    tomLayer.processOutOfContext();
                    if (topology.getCurrentViewId() != currentView.getId()) {
                        LOGGER.info("Installing current view!");
                        topology.reconfigureTo(currentView);
                    }
                    isInitializing = false;
                    dt.canDeliver();
                    dt.deliverUnlock();
                    reset();
                    LOGGER.info("I updated the state!");
                    // tomLayer.requestsTimer.startTimer();
                    if (stateTimer != null)
                        stateTimer.cancel();
                    if (appStateOnly) {
                        appStateOnly = false;
                        tomLayer.getSynchronizer().resumeLC();
                    }
                } else if (state == null && (topology.getCurrentViewN() / 2) < getReplies()) {
                    LOGGER.error("---- DIDNT RECEIVE STATE ----");
                    LOGGER.error("(TOMLayer.SMReplyDeliver) I have more than {} messages that are no good!", (topology.getCurrentViewN() / 2));
                    waitingCID = -1;
                    reset();
                    if (stateTimer != null)
                        stateTimer.cancel();
                    if (appStateOnly) {
                        requestState();
                    }
                } else if (!haveState) {
                    LOGGER.error("---- RECEIVED INVALID STATE  ----");
                    LOGGER.error("(TOMLayer.SMReplyDeliver) The replica from which I expected the state, sent one which doesn't match the hash of the others, or it never sent it at all");
                    reset();
                    requestState();
                    if (stateTimer != null)
                        stateTimer.cancel();
                }
            }
        }
    }
    lockTimer.unlock();
}
Also used : UnknownHostException(java.net.UnknownHostException) ApplicationState(bftsmart.statemanagement.ApplicationState) LeaderRegency(bftsmart.tom.leaderchange.LeaderRegency) IOException(java.io.IOException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) View(bftsmart.reconfiguration.views.View) DurabilityCoordinator(bftsmart.tom.server.defaultservices.durability.DurabilityCoordinator) ConsensusMessage(bftsmart.consensus.messages.ConsensusMessage) CommandsInfo(bftsmart.tom.server.defaultservices.CommandsInfo) NodeNetwork(bftsmart.reconfiguration.views.NodeNetwork) Socket(java.net.Socket) ObjectInputStream(java.io.ObjectInputStream)

Aggregations

ConsensusMessage (bftsmart.consensus.messages.ConsensusMessage)1 NodeNetwork (bftsmart.reconfiguration.views.NodeNetwork)1 View (bftsmart.reconfiguration.views.View)1 ApplicationState (bftsmart.statemanagement.ApplicationState)1 LeaderRegency (bftsmart.tom.leaderchange.LeaderRegency)1 CommandsInfo (bftsmart.tom.server.defaultservices.CommandsInfo)1 DurabilityCoordinator (bftsmart.tom.server.defaultservices.durability.DurabilityCoordinator)1 IOException (java.io.IOException)1 ObjectInputStream (java.io.ObjectInputStream)1 Socket (java.net.Socket)1 UnknownHostException (java.net.UnknownHostException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1