use of bftsmart.tom.leaderchange.LCMessage in project aware by bergerch.
the class Synchronizer method catch_up.
// this method is used to verify if the leader can make the message catch-up
// and also sends the message
private void catch_up(int regency) {
logger.debug("Verifying STOPDATA info");
ObjectOutputStream out = null;
ByteArrayOutputStream bos = null;
CertifiedDecision lastHighestCID = lcManager.getHighestLastCID(regency);
int currentCID = lastHighestCID.getCID() + 1;
HashSet<SignedObject> signedCollects = null;
byte[] propose = null;
int batchSize = -1;
// normalize the collects and apply to them the predicate "sound"
if (lcManager.sound(lcManager.selectCollects(regency, currentCID))) {
logger.debug("Sound predicate is true");
// all original collects that the replica has received
signedCollects = lcManager.getCollects(regency);
// the only purpose of this object is to obtain the batchsize,
Decision dec = new Decision(-1);
// using code inside of createPropose()
propose = tom.createPropose(dec);
batchSize = dec.batchSize;
try {
// serialization of the CATCH-UP message
bos = new ByteArrayOutputStream();
out = new ObjectOutputStream(bos);
out.writeObject(lastHighestCID);
// TODO: Missing: serialization of the proof?
out.writeObject(signedCollects);
out.writeObject(propose);
out.writeInt(batchSize);
out.flush();
bos.flush();
byte[] payload = bos.toByteArray();
out.close();
bos.close();
logger.info("Sending SYNC message for regency " + regency);
// send the CATCH-UP message
communication.send(this.controller.getCurrentViewOtherAcceptors(), new LCMessage(this.controller.getStaticConf().getProcessId(), TOMUtil.SYNC, regency, payload));
finalise(regency, lastHighestCID, signedCollects, propose, batchSize, true);
} catch (IOException ex) {
logger.error("Could not serialize message", ex);
}
}
}
use of bftsmart.tom.leaderchange.LCMessage in project aware by bergerch.
the class Synchronizer method processOutOfContextSTOPs.
// Processes STOP messages that were not process upon reception, because they were
// ahead of the replica's expected regency
private void processOutOfContextSTOPs(int regency) {
logger.debug("Checking if there are out of context STOPs for regency " + regency);
Set<LCMessage> stops = getOutOfContextLC(TOMUtil.STOP, regency);
if (stops.size() > 0) {
logger.info("Processing " + stops.size() + " out of context STOPs for regency " + regency);
} else {
logger.debug("No out of context STOPs for regency " + regency);
}
for (LCMessage m : stops) {
TOMMessage[] requests = deserializeTOMMessages(m.getPayload());
// store requests that came with the STOP message
lcManager.addRequestsFromSTOP(requests);
// store information about the STOP message
lcManager.addStop(regency, m.getSender());
}
}
use of bftsmart.tom.leaderchange.LCMessage in project aware by bergerch.
the class Synchronizer method getOutOfContextLC.
// Fetches synchronization messages that were not process upon reception,
// because they were ahead of the replica's expected regency
private Set<LCMessage> getOutOfContextLC(int type, int regency) {
HashSet<LCMessage> result = new HashSet<>();
for (LCMessage m : outOfContextLC) {
if (m.getType() == type && m.getReg() == regency) {
result.add(m);
}
}
// avoid memory leaks
outOfContextLC.removeAll(result);
return result;
}
use of bftsmart.tom.leaderchange.LCMessage in project aware by bergerch.
the class Synchronizer method startSynchronization.
// this method is called when a timeout occurs or when a STOP message is recevied
private void startSynchronization(int nextReg) {
boolean condition;
ObjectOutputStream out = null;
ByteArrayOutputStream bos = null;
if (this.controller.getStaticConf().isBFT()) {
condition = lcManager.getStopsSize(nextReg) > this.controller.getCurrentViewF();
} else {
condition = lcManager.getStopsSize(nextReg) > 0;
}
// Ask to start the synchronizations phase if enough messages have been received already
if (condition && lcManager.getNextReg() == lcManager.getLastReg()) {
logger.debug("Initialize synch phase");
requestsTimer.Enabled(false);
requestsTimer.stopTimer();
// define next timestamp
lcManager.setNextReg(lcManager.getLastReg() + 1);
int regency = lcManager.getNextReg();
// store information about message I am going to send
lcManager.addStop(regency, this.controller.getStaticConf().getProcessId());
// execManager.stop(); // stop execution of consensus
// Get requests that timed out and the requests received in STOP messages
// and add those STOPed requests to the client manager
addSTOPedRequestsToClientManager();
List<TOMMessage> messages = getRequestsToRelay();
try {
// serialize conent to send in the STOP message
bos = new ByteArrayOutputStream();
out = new ObjectOutputStream(bos);
// Do I have messages to send in the STOP message?
if (messages != null && messages.size() > 0) {
// TODO: If this is null, there was no timeout nor STOP messages.
// What shall be done then?
out.writeBoolean(true);
byte[] serialized = bb.makeBatch(messages, 0, 0, controller.getStaticConf().getUseSignatures() == 1);
out.writeObject(serialized);
} else {
out.writeBoolean(false);
logger.warn("Strange... did not include any request in my STOP message for regency " + regency);
}
out.flush();
bos.flush();
byte[] payload = bos.toByteArray();
out.close();
bos.close();
// send message STOP
logger.info("Sending STOP message to install regency " + regency + " with " + (messages != null ? messages.size() : 0) + " request(s) to relay");
LCMessage stop = new LCMessage(this.controller.getStaticConf().getProcessId(), TOMUtil.STOP, regency, payload);
// make replica re-transmit the stop message until a new regency is installed
requestsTimer.setSTOP(regency, stop);
communication.send(this.controller.getCurrentViewOtherAcceptors(), stop);
} catch (IOException ex) {
logger.error("Could not deserialize STOP message", ex);
}
}
if (this.controller.getStaticConf().isBFT()) {
condition = lcManager.getStopsSize(nextReg) > (2 * this.controller.getCurrentViewF());
} else {
condition = lcManager.getStopsSize(nextReg) > this.controller.getCurrentViewF();
}
// if (lcManager.getStopsSize(nextReg) > this.reconfManager.getQuorum2F() && lcManager.getNextReg() > lcManager.getLastReg()) {
if (condition && lcManager.getNextReg() > lcManager.getLastReg()) {
// stop consensus execution if more than f replicas sent a STOP message
if (!execManager.stopped())
execManager.stop();
logger.debug("Installing regency " + lcManager.getNextReg());
// define last timestamp
lcManager.setLastReg(lcManager.getNextReg());
int regency = lcManager.getLastReg();
// avoid memory leaks
lcManager.removeStops(nextReg);
lcManager.clearCurrentRequestTimedOut();
lcManager.clearRequestsFromSTOP();
requestsTimer.Enabled(true);
requestsTimer.setShortTimeout(-1);
requestsTimer.startTimer();
// int leader = regency % this.reconfManager.getCurrentViewN(); // new leader
int leader = lcManager.getNewLeader();
// cid to execute
int in = tom.getInExec();
// last cid decided
int last = tom.getLastExec();
execManager.setNewLeader(leader);
// If I am not the leader, I have to send a STOPDATA message to the elected leader
if (leader != this.controller.getStaticConf().getProcessId()) {
try {
// serialize content of the STOPDATA message
bos = new ByteArrayOutputStream();
out = new ObjectOutputStream(bos);
Consensus cons = null;
// content of the last decided CID
if (last > -1)
cons = execManager.getConsensus(last);
// Do I have info on my last executed consensus?
if (cons != null && cons.getDecisionEpoch() != null && cons.getDecisionEpoch().propValue != null) {
out.writeBoolean(true);
out.writeInt(last);
// byte[] decision = exec.getLearner().getDecision();
byte[] decision = cons.getDecisionEpoch().propValue;
Set<ConsensusMessage> proof = cons.getDecisionEpoch().getProof();
out.writeObject(decision);
out.writeObject(proof);
// TODO: WILL BE NECESSARY TO ADD A PROOF!!!
} else {
out.writeBoolean(false);
// //// THIS IS TO CATCH A BUG!!!!!
if (last > -1) {
logger.debug("[DEBUG INFO FOR LAST CID #1]");
if (cons == null) {
if (last > -1)
logger.debug("No consensus instance for cid " + last);
} else if (cons.getDecisionEpoch() == null) {
logger.debug("No decision epoch for cid " + last);
} else {
logger.debug("epoch for cid: " + last + ": " + cons.getDecisionEpoch().toString());
if (cons.getDecisionEpoch().propValue == null) {
logger.debug("No propose for cid " + last);
} else {
logger.debug("Propose hash for cid " + last + ": " + Base64.encodeBase64String(tom.computeHash(cons.getDecisionEpoch().propValue)));
}
}
}
}
if (in > -1) {
// content of cid in execution
cons = execManager.getConsensus(in);
// cons.incEts(); // make the consensus advance to the next epoch
// make the consensus advance to the next epoch
cons.setETS(regency);
// int ets = cons.getEts();
// cons.createEpoch(ets, controller);
cons.createEpoch(regency, controller);
// Logger.println("(Synchronizer.startSynchronization) incrementing ets of consensus " + cons.getId() + " to " + ets);
logger.debug("Incrementing ets of consensus " + cons.getId() + " to " + regency);
TimestampValuePair quorumWrites;
if (cons.getQuorumWrites() != null) {
quorumWrites = cons.getQuorumWrites();
} else {
quorumWrites = new TimestampValuePair(0, new byte[0]);
}
HashSet<TimestampValuePair> writeSet = cons.getWriteSet();
// CollectData collect = new CollectData(this.controller.getStaticConf().getProcessId(), in, ets, quorumWrites, writeSet);
CollectData collect = new CollectData(this.controller.getStaticConf().getProcessId(), in, regency, quorumWrites, writeSet);
SignedObject signedCollect = tom.sign(collect);
out.writeObject(signedCollect);
} else {
cons = execManager.getConsensus(last + 1);
// cons.incEts(); // make the consensus advance to the next epoch
// make the consensus advance to the next epoch
cons.setETS(regency);
// int ets = cons.getEts();
// cons.createEpoch(ets, controller);
cons.createEpoch(regency, controller);
// Logger.println("(Synchronizer.startSynchronization) incrementing ets of consensus " + cons.getId() + " to " + ets);
logger.debug("Incrementing ets of consensus " + cons.getId() + " to " + regency);
// CollectData collect = new CollectData(this.controller.getStaticConf().getProcessId(), last + 1, ets, new TimestampValuePair(0, new byte[0]), new HashSet<TimestampValuePair>());
CollectData collect = new CollectData(this.controller.getStaticConf().getProcessId(), last + 1, regency, new TimestampValuePair(0, new byte[0]), new HashSet<TimestampValuePair>());
SignedObject signedCollect = tom.sign(collect);
out.writeObject(signedCollect);
}
out.flush();
bos.flush();
byte[] payload = bos.toByteArray();
out.close();
bos.close();
int[] b = new int[1];
b[0] = leader;
logger.info("Sending STOPDATA of regency " + regency);
// send message SYNC to the new leader
communication.send(b, new LCMessage(this.controller.getStaticConf().getProcessId(), TOMUtil.STOPDATA, regency, payload));
// TODO: Turn on timeout again?
} catch (IOException ex) {
logger.error("Could not deserialize STOPDATA message", ex);
}
// the replica might have received a SYNC that was out of context at the time it was received, but now can be processed
Set<LCMessage> sync = getOutOfContextLC(TOMUtil.SYNC, regency);
logger.debug("Checking if there are out of context SYNC for regency " + regency);
if (sync.size() > 0) {
logger.info("Processing out of context SYNC for regency " + regency);
} else {
logger.info("No out of context SYNC for regency " + regency);
}
for (LCMessage m : sync) {
if (m.getSender() == execManager.getCurrentLeader()) {
processSYNC(m.getPayload(), regency);
// makes no sense to continue, since there is only one SYNC message
return;
}
}
} else {
// If leader, I will store information that I would send in a SYNC message
logger.debug("I'm the leader for this new regency");
CertifiedDecision lastDec = null;
CollectData collect = null;
Consensus cons = null;
// Content of the last decided CID
if (last > -1)
cons = execManager.getConsensus(last);
// Do I have info on my last executed consensus?
if (cons != null && cons.getDecisionEpoch() != null && cons.getDecisionEpoch().propValue != null) {
// byte[] decision = exec.getLearner().getDecision();
byte[] decision = cons.getDecisionEpoch().propValue;
Set<ConsensusMessage> proof = cons.getDecisionEpoch().getProof();
lastDec = new CertifiedDecision(this.controller.getStaticConf().getProcessId(), last, decision, proof);
// TODO: WILL BE NECESSARY TO ADD A PROOF!!!??
} else {
lastDec = new CertifiedDecision(this.controller.getStaticConf().getProcessId(), last, null, null);
// //// THIS IS TO CATCH A BUG!!!!!
if (last > -1) {
logger.debug("[DEBUG INFO FOR LAST CID #2]");
if (cons == null) {
if (last > -1)
logger.debug("No consensus instance for cid " + last);
} else if (cons.getDecisionEpoch() == null) {
logger.debug("No decision epoch for cid " + last);
} else {
logger.debug("epoch for cid: " + last + ": " + cons.getDecisionEpoch().toString());
}
if (cons.getDecisionEpoch().propValue == null) {
logger.debug("No propose for cid " + last);
} else {
logger.debug("Propose hash for cid " + last + ": " + Base64.encodeBase64String(tom.computeHash(cons.getDecisionEpoch().propValue)));
}
}
}
lcManager.addLastCID(regency, lastDec);
if (in > -1) {
// content of cid being executed
cons = execManager.getConsensus(in);
// cons.incEts(); // make the consensus advance to the next epoch
// make the consensus advance to the next epoch
cons.setETS(regency);
// int ets = cons.getEts();
// cons.createEpoch(ets, controller);
cons.createEpoch(regency, controller);
// Logger.println("(Synchronizer.startSynchronization) incrementing ets of consensus " + cons.getId() + " to " + ets);
logger.debug("Incrementing ets of consensus " + cons.getId() + " to " + regency);
TimestampValuePair quorumWrites;
if (cons.getQuorumWrites() != null) {
quorumWrites = cons.getQuorumWrites();
} else {
quorumWrites = new TimestampValuePair(0, new byte[0]);
}
HashSet<TimestampValuePair> writeSet = cons.getWriteSet();
// collect = new CollectData(this.controller.getStaticConf().getProcessId(), in, ets, quorumWrites, writeSet);
collect = new CollectData(this.controller.getStaticConf().getProcessId(), in, regency, quorumWrites, writeSet);
} else {
cons = execManager.getConsensus(last + 1);
// cons.incEts(); // make the consensus advance to the next epoch
// make the consensus advance to the next epoch
cons.setETS(regency);
// int ets = cons.getEts();
// cons.createEpoch(ets, controller);
cons.createEpoch(regency, controller);
// Logger.println("startSynchronization) incrementing ets of consensus " + cons.getId() + " to " + ets);
logger.debug("Incrementing ets of consensus " + cons.getId() + " to " + regency);
// collect = new CollectData(this.controller.getStaticConf().getProcessId(), last + 1, ets, new TimestampValuePair(0, new byte[0]), new HashSet<TimestampValuePair>());
collect = new CollectData(this.controller.getStaticConf().getProcessId(), last + 1, regency, new TimestampValuePair(0, new byte[0]), new HashSet<TimestampValuePair>());
}
SignedObject signedCollect = tom.sign(collect);
lcManager.addCollect(regency, signedCollect);
// the replica might have received STOPDATAs that were out of context at the time they were received, but now can be processed
Set<LCMessage> stopdatas = getOutOfContextLC(TOMUtil.STOPDATA, regency);
logger.debug("Checking if there are out of context STOPDATAs for regency " + regency);
if (stopdatas.size() > 0) {
logger.debug("Processing " + stopdatas.size() + " out of context STOPDATAs for regency " + regency);
} else {
logger.debug("No out of context STOPDATAs for regency " + regency);
}
for (LCMessage m : stopdatas) {
processSTOPDATA(m, regency);
}
}
}
}
use of bftsmart.tom.leaderchange.LCMessage in project aware by bergerch.
the class MessageHandler method processData.
@SuppressWarnings("unchecked")
protected void processData(SystemMessage sm) {
if (sm instanceof ConsensusMessage) {
int myId = tomLayer.controller.getStaticConf().getProcessId();
ConsensusMessage consMsg = (ConsensusMessage) sm;
if (tomLayer.controller.getStaticConf().getUseMACs() == 0 || consMsg.authenticated || consMsg.getSender() == myId)
acceptor.deliver(consMsg);
else if (consMsg.getType() == MessageFactory.ACCEPT && consMsg.getProof() != null) {
// We are going to verify the MAC vector at the algorithm level
HashMap<Integer, byte[]> macVector = (HashMap<Integer, byte[]>) consMsg.getProof();
byte[] recvMAC = macVector.get(myId);
ConsensusMessage cm = new ConsensusMessage(MessageFactory.ACCEPT, consMsg.getNumber(), consMsg.getEpoch(), consMsg.getSender(), consMsg.getValue());
ByteArrayOutputStream bOut = new ByteArrayOutputStream(248);
try {
new ObjectOutputStream(bOut).writeObject(cm);
} catch (IOException ex) {
logger.error("Failed to serialize consensus message", ex);
}
byte[] data = bOut.toByteArray();
// byte[] hash = tomLayer.computeHash(data);
byte[] myMAC = null;
/*byte[] k = tomLayer.getCommunication().getServersConn().getSecretKey(paxosMsg.getSender()).getEncoded();
SecretKeySpec key = new SecretKeySpec(new String(k).substring(0, 8).getBytes(), "DES");*/
SecretKey key = tomLayer.getCommunication().getServersConn().getSecretKey(consMsg.getSender());
try {
this.mac.init(key);
myMAC = this.mac.doFinal(data);
} catch (/*IllegalBlockSizeException | BadPaddingException |*/
InvalidKeyException ex) {
logger.error("Failed to generate MAC", ex);
}
if (recvMAC != null && myMAC != null && Arrays.equals(recvMAC, myMAC))
acceptor.deliver(consMsg);
else {
logger.warn("Invalid MAC from " + sm.getSender());
}
} else {
logger.warn("Discarding unauthenticated message from " + sm.getSender());
}
} else {
if (tomLayer.controller.getStaticConf().getUseMACs() == 0 || sm.authenticated) {
/**
* This is Joao's code, related to leader change
*/
if (sm instanceof LCMessage) {
LCMessage lcMsg = (LCMessage) sm;
String type = null;
switch(lcMsg.getType()) {
case TOMUtil.STOP:
type = "STOP";
break;
case TOMUtil.STOPDATA:
type = "STOPDATA";
break;
case TOMUtil.SYNC:
type = "SYNC";
break;
default:
type = "LOCAL";
break;
}
if (lcMsg.getReg() != -1 && lcMsg.getSender() != -1)
logger.info("Received leader change message of type {} for regency {} from replica {}", type, lcMsg.getReg(), lcMsg.getSender());
else
logger.debug("Received leader change message from myself");
if (lcMsg.TRIGGER_LC_LOCALLY)
tomLayer.requestsTimer.run_lc_protocol();
else
tomLayer.getSynchronizer().deliverTimeoutRequest(lcMsg);
/**
***********************************************************
*/
} else if (sm instanceof ForwardedMessage) {
TOMMessage request = ((ForwardedMessage) sm).getRequest();
tomLayer.requestReceived(request);
/**
* This is Joao's code, to handle state transfer
*/
} else if (sm instanceof SMMessage) {
SMMessage smsg = (SMMessage) sm;
// System.out.println("(MessageHandler.processData) SM_MSG received: type " + smsg.getType() + ", regency " + smsg.getRegency() + ", (replica " + smsg.getSender() + ")");
switch(smsg.getType()) {
case TOMUtil.SM_REQUEST:
tomLayer.getStateManager().SMRequestDeliver(smsg, tomLayer.controller.getStaticConf().isBFT());
break;
case TOMUtil.SM_REPLY:
tomLayer.getStateManager().SMReplyDeliver(smsg, tomLayer.controller.getStaticConf().isBFT());
break;
case TOMUtil.SM_ASK_INITIAL:
tomLayer.getStateManager().currentConsensusIdAsked(smsg.getSender(), smsg.getCID());
break;
case TOMUtil.SM_REPLY_INITIAL:
tomLayer.getStateManager().currentConsensusIdReceived(smsg);
break;
default:
tomLayer.getStateManager().stateTimeout();
break;
}
/**
***************************************************************
*/
} else {
logger.warn("UNKNOWN MESSAGE TYPE: " + sm);
}
} else {
logger.warn("Discarding unauthenticated message from " + sm.getSender());
}
}
}
Aggregations