Search in sources :

Example 1 with CertifiedDecision

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;
}
Also used : TOMMessage(bftsmart.tom.core.messages.TOMMessage) ConsensusMessage(bftsmart.consensus.messages.ConsensusMessage) CertifiedDecision(bftsmart.tom.leaderchange.CertifiedDecision) BatchBuilder(bftsmart.tom.util.BatchBuilder) CommandsInfo(bftsmart.tom.server.defaultservices.CommandsInfo) LinkedList(java.util.LinkedList)

Example 2 with CertifiedDecision

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);
    }
}
Also used : CertifiedDecision(bftsmart.tom.leaderchange.CertifiedDecision) ConsensusMessage(bftsmart.consensus.messages.ConsensusMessage) ByteArrayInputStream(java.io.ByteArrayInputStream) IOException(java.io.IOException) SignedObject(java.security.SignedObject) ObjectInputStream(java.io.ObjectInputStream)

Example 3 with CertifiedDecision

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);
        }
    }
}
Also used : CertifiedDecision(bftsmart.tom.leaderchange.CertifiedDecision) LCMessage(bftsmart.tom.leaderchange.LCMessage) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) ObjectOutputStream(java.io.ObjectOutputStream) SignedObject(java.security.SignedObject) Decision(bftsmart.consensus.Decision) CertifiedDecision(bftsmart.tom.leaderchange.CertifiedDecision)

Example 4 with CertifiedDecision

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);
    }
}
Also used : CertifiedDecision(bftsmart.tom.leaderchange.CertifiedDecision) ByteArrayInputStream(java.io.ByteArrayInputStream) IOException(java.io.IOException) SignedObject(java.security.SignedObject) ObjectInputStream(java.io.ObjectInputStream)

Example 5 with CertifiedDecision

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);
            }
        }
    }
}
Also used : TOMMessage(bftsmart.tom.core.messages.TOMMessage) TimestampValuePair(bftsmart.consensus.TimestampValuePair) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) ObjectOutputStream(java.io.ObjectOutputStream) CollectData(bftsmart.tom.leaderchange.CollectData) Consensus(bftsmart.consensus.Consensus) LCMessage(bftsmart.tom.leaderchange.LCMessage) ConsensusMessage(bftsmart.consensus.messages.ConsensusMessage) CertifiedDecision(bftsmart.tom.leaderchange.CertifiedDecision) SignedObject(java.security.SignedObject) HashSet(java.util.HashSet)

Aggregations

CertifiedDecision (bftsmart.tom.leaderchange.CertifiedDecision)18 ConsensusMessage (bftsmart.consensus.messages.ConsensusMessage)10 SignedObject (java.security.SignedObject)8 TOMMessage (bftsmart.tom.core.messages.TOMMessage)7 IOException (java.io.IOException)7 Consensus (bftsmart.consensus.Consensus)4 Decision (bftsmart.consensus.Decision)4 LCMessage (bftsmart.tom.leaderchange.LCMessage)4 BatchBuilder (bftsmart.tom.util.BatchBuilder)4 ByteArrayInputStream (java.io.ByteArrayInputStream)4 ObjectInputStream (java.io.ObjectInputStream)4 LinkedList (java.util.LinkedList)4 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3 ObjectOutputStream (java.io.ObjectOutputStream)3 Epoch (bftsmart.consensus.Epoch)2 TimestampValuePair (bftsmart.consensus.TimestampValuePair)2 View (bftsmart.reconfiguration.views.View)2 ApplicationState (bftsmart.statemanagement.ApplicationState)2 CollectData (bftsmart.tom.leaderchange.CollectData)2 CommandsInfo (bftsmart.tom.server.defaultservices.CommandsInfo)2