use of bftsmart.tom.leaderchange.CertifiedDecision in project aware by bergerch.
the class CSTState method getCertifiedDecision.
/**
* Retrieves the certified decision for the last consensus present in this object
* @param controller
* @return The certified decision for the last consensus present in this object
*/
@Override
public CertifiedDecision getCertifiedDecision(ServerViewController controller) {
CommandsInfo ci = getMessageBatch(getLastCID());
if (ci != null && ci.msgCtx[0].getProof() != null) {
// do I have a proof for the consensus?
Set<ConsensusMessage> proof = ci.msgCtx[0].getProof();
LinkedList<TOMMessage> requests = new LinkedList<>();
// Recreate all TOMMessages ordered in the consensus
for (int i = 0; i < ci.commands.length; i++) {
requests.add(ci.msgCtx[i].recreateTOMMessage(ci.commands[i]));
}
// Serialize the TOMMessages to re-create the proposed value
BatchBuilder bb = new BatchBuilder(0);
byte[] value = bb.makeBatch(requests, ci.msgCtx[0].getNumOfNonces(), ci.msgCtx[0].getSeed(), ci.msgCtx[0].getTimestamp(), controller.getStaticConf().getUseSignatures() == 1);
// Assemble and return the certified decision
return new CertifiedDecision(pid, getLastCID(), value, proof);
} else
// there was no proof for the consensus
return null;
}
use of bftsmart.tom.leaderchange.CertifiedDecision in project aware by bergerch.
the class Synchronizer method processSTOPDATA.
// Processes STOPDATA messages that were not process upon reception, because they were
// ahead of the replica's expected regency
private void processSTOPDATA(LCMessage msg, int regency) {
// TODO: It is necessary to verify the proof of the last decided consensus and the signature of the state of the current consensus!
CertifiedDecision lastData = null;
SignedObject signedCollect = null;
int last = -1;
byte[] lastValue = null;
Set<ConsensusMessage> proof = null;
ByteArrayInputStream bis;
ObjectInputStream ois;
try {
// deserialize the content of the message
bis = new ByteArrayInputStream(msg.getPayload());
ois = new ObjectInputStream(bis);
if (ois.readBoolean()) {
// content of the last decided cid
last = ois.readInt();
lastValue = (byte[]) ois.readObject();
proof = (Set<ConsensusMessage>) ois.readObject();
// TODO: Proof is missing!
}
lastData = new CertifiedDecision(msg.getSender(), last, lastValue, proof);
lcManager.addLastCID(regency, lastData);
signedCollect = (SignedObject) ois.readObject();
ois.close();
bis.close();
lcManager.addCollect(regency, signedCollect);
int bizantineQuorum = (controller.getCurrentViewN() + controller.getCurrentViewF()) / 2;
int cftQuorum = (controller.getCurrentViewN()) / 2;
// Did I already got messages from a Byzantine/Crash quorum,
// related to the last cid as well as for the current?
boolean conditionBFT = (controller.getStaticConf().isBFT() && lcManager.getLastCIDsSize(regency) > bizantineQuorum && lcManager.getCollectsSize(regency) > bizantineQuorum);
boolean conditionCFT = (lcManager.getLastCIDsSize(regency) > cftQuorum && lcManager.getCollectsSize(regency) > cftQuorum);
if (conditionBFT || conditionCFT) {
catch_up(regency);
}
} catch (IOException | ClassNotFoundException ex) {
logger.error("Could not deserialize STOPDATA message", ex);
}
}
use of bftsmart.tom.leaderchange.CertifiedDecision 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.CertifiedDecision in project aware by bergerch.
the class Synchronizer method processSYNC.
// Processes SYNC messages that were not process upon reception, because they were
// ahead of the replica's expected regency
private void processSYNC(byte[] payload, int regency) {
CertifiedDecision lastHighestCID = null;
int currentCID = -1;
HashSet<SignedObject> signedCollects = null;
byte[] propose = null;
int batchSize = -1;
ByteArrayInputStream bis;
ObjectInputStream ois;
try {
// deserialization of the message content
bis = new ByteArrayInputStream(payload);
ois = new ObjectInputStream(bis);
lastHighestCID = (CertifiedDecision) ois.readObject();
signedCollects = (HashSet<SignedObject>) ois.readObject();
propose = (byte[]) ois.readObject();
batchSize = ois.readInt();
lcManager.setCollects(regency, signedCollects);
currentCID = lastHighestCID.getCID() + 1;
// Is the predicate "sound" true? Is the certificate for LastCID valid?
if (lcManager.sound(lcManager.selectCollects(regency, currentCID)) && (!controller.getStaticConf().isBFT() || lcManager.hasValidProof(lastHighestCID))) {
finalise(regency, lastHighestCID, signedCollects, propose, batchSize, false);
}
ois.close();
bis.close();
} catch (IOException | ClassNotFoundException ex) {
logger.error("Could not deserialize SYNC message", ex);
}
}
use of bftsmart.tom.leaderchange.CertifiedDecision 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);
}
}
}
}
Aggregations