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();
}
Aggregations