diff --git a/meerkat-common/src/main/proto/meerkat/voting.proto b/meerkat-common/src/main/proto/meerkat/voting.proto index 4edc9f5..09c8b21 100644 --- a/meerkat-common/src/main/proto/meerkat/voting.proto +++ b/meerkat-common/src/main/proto/meerkat/voting.proto @@ -88,6 +88,10 @@ message BoothParams { } +message BoothSystemMessages { + map system_message = 1; +} + // A table to translate to and from compactly encoded answers // and their human-understandable counterparts. // This should be parsable by the UI @@ -122,14 +126,17 @@ message ElectionParams { // How many mixers must participate for the mixing to be considered valid uint32 mixerThreshold = 5; - // Candidate list (or other question format) - repeated BallotQuestion questions = 6; + // questions to first indicate the voter's channel + repeated BallotQuestion channel_choice_questions = 6; - // Translation table between answers and plaintext encoding - //BallotAnswerTranslationTable answerTranslationTable = 7; + // translating the channel-choice answers to the voter's channel + SimpleCategoriesSelectionData selection_data = 7; + + // Candidate list (or other question format) + repeated BallotQuestion race_questions = 8; // Data required in order to access the Bulletin Board Servers - BulletinBoardClientParams bulletinBoardClientParams = 8; + BulletinBoardClientParams bulletinBoardClientParams = 9; } message Category { diff --git a/voting-booth/src/main/java/meerkat/voting/controller/SystemMessages.java b/voting-booth/src/main/java/meerkat/voting/controller/SystemMessages.java index ee6b506..4f57809 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/SystemMessages.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/SystemMessages.java @@ -33,13 +33,6 @@ final public class SystemMessages { .build(); } - public static UIElement getFatalForceRestartMessage() { - return UIElement.newBuilder() - .setType(UIElementDataType.TEXT) - .setData(ByteString.copyFromUtf8("Fatal error: Internal controller queue received unrecognized command. Force restarting the voting process.")) - .build(); - } - public static UIElement getRestartVotingButton() { return UIElement.newBuilder() .setType(UIElementDataType.TEXT) diff --git a/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothController.java b/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothController.java index 6b706f3..e8eae93 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothController.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothController.java @@ -7,6 +7,7 @@ import meerkat.voting.ui.VotingBoothUI; import meerkat.voting.output.BallotOutputDevice; import meerkat.voting.storage.StorageManager; +import java.io.IOException; import java.util.List; @@ -25,25 +26,7 @@ public interface VotingBoothController extends Runnable{ public void init (BallotOutputDevice outputDevice, VBCryptoManager vbCrypto, VotingBoothUI vbUI, - StorageManager vbStorageManager); - - /** - * set the voting questions - * @param questions - */ - public void setBallotChannelChoiceQuestions(List questions); - - /** - * Set the channel question-selector (the component which matches the ballot questions to each user) - * @param selector the question selector instance - */ - public void setChannelQuestionSelector (QuestionSelector selector); - - /** - * set the voting race questions - * @param questions - */ - public void setBallotRaceQuestions(List questions); + StorageManager vbStorageManager) throws IOException; /** * an asynchronous call from Admin Console (If there is such one implemented) to shut down the system diff --git a/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothImpl.java b/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothImpl.java index a9221bf..b20a11d 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothImpl.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/VotingBoothImpl.java @@ -1,9 +1,11 @@ package meerkat.voting.controller; +import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting.*; import meerkat.voting.controller.callbacks.*; import meerkat.voting.controller.commands.*; import meerkat.voting.controller.selector.QuestionSelector; +import meerkat.voting.controller.selector.SimpleListCategoriesSelector; import meerkat.voting.encryptor.VBCryptoManager; import meerkat.voting.encryptor.VBCryptoManager.EncryptionAndSecrets; import meerkat.voting.output.BallotOutputDevice; @@ -15,6 +17,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.security.SignatureException; import java.util.List; +import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; /** @@ -29,6 +32,7 @@ public class VotingBoothImpl implements VotingBoothController { private List questionsForChoosingChannel; private List questions; private QuestionSelector questionSelector; + private Map systemMessages; private LinkedBlockingQueue queue; @@ -41,6 +45,7 @@ public class VotingBoothImpl implements VotingBoothController { private static int requestCounter = 0; + public VotingBoothImpl () { logger = LoggerFactory.getLogger(VotingBoothImpl.class); logger.info("A VotingBoothImpl is constructed"); @@ -53,30 +58,32 @@ public class VotingBoothImpl implements VotingBoothController { public void init(BallotOutputDevice outputDevice, VBCryptoManager vbCrypto, VotingBoothUI vbUI, - StorageManager vbStorageManager) { + StorageManager vbStorageManager) throws IOException { logger.info("init is called"); this.outputDevice = outputDevice; this.crypto = vbCrypto; this.ui = vbUI; this.storageManager = vbStorageManager; + + ElectionParams electionParams; + try { + logger.info("init: reading election params"); + electionParams = storageManager.readElectionParams(); + logger.info("init: reading system messages"); + systemMessages = storageManager.readSystemMessages(); + } + catch (IOException e) { + logger.error("init could not read info from a file. Exception is: " + e); + throw e; + } + + logger.info("init: setting the election parameters"); + this.questionsForChoosingChannel = electionParams.getChannelChoiceQuestionsList(); + this.questions = electionParams.getRaceQuestionsList(); + this.questionSelector = new SimpleListCategoriesSelector(this.questions, electionParams.getSelectionData()); + logger.info("init: setting finished"); } - @Override - public void setBallotChannelChoiceQuestions(List questions) { - logger.info("setting questions"); - this.questionsForChoosingChannel = questions; - } - - @Override - public void setChannelQuestionSelector(QuestionSelector selector) { - this.questionSelector = selector; - } - - @Override - public void setBallotRaceQuestions(List questions) { - logger.info("setting questions"); - this.questions = questions; - } @Override public void run() { @@ -146,7 +153,7 @@ public class VotingBoothImpl implements VotingBoothController { } else { logger.error("handleSingleTask: unknown type of ControllerCommand received: " + task.getClass().getName()); - doReportErrorAndForceRestart(SystemMessages.getSomethingWrongMessage()); + doReportErrorAndForceRestart(systemMessages.get(storageManager.SOMETHING_WRONG_MESSAGE)); } } @@ -156,18 +163,13 @@ public class VotingBoothImpl implements VotingBoothController { private void doShutDown () { logger.info("running callShutDown"); - state.clearPlaintext(); - state.clearCiphertext(); - state.stateIdentifier = VBState.SHUT_DOWN; + state.clearAndResetState(VBState.SHUT_DOWN); //TODO: add commands to actually shut down the machine } private void doRestartVoting () { queue.clear(); - state.clearPlaintext(); - state.clearCiphertext(); - state.stateIdentifier = VBState.NEW_VOTER; - state.currentBallotSerialNumber += 1; + state.clearAndResetState(VBState.NEW_VOTER); ui.startNewVoterSession(new NewVoterCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); } @@ -178,13 +180,12 @@ public class VotingBoothImpl implements VotingBoothController { private void doReportErrorAndForceRestart(UIElement errorMessage) { queue.clear(); - state.clearPlaintext(); - state.clearCiphertext(); - state.stateIdentifier = VBState.FATAL_ERROR_FORCE_NEW_VOTER; - state.currentBallotSerialNumber += 1; + state.clearAndResetState(VBState.FATAL_ERROR_FORCE_NEW_VOTER); ui.showErrorMessageWithButtons(errorMessage, - new UIElement[]{SystemMessages.getRestartVotingButton()}, - new ErrorMessageRestartCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + new UIElement[]{systemMessages.get(storageManager.RESTART_VOTING_BUTTON)}, + new ErrorMessageRestartCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue)); } private void doChooseChannel () { @@ -192,7 +193,10 @@ public class VotingBoothImpl implements VotingBoothController { logger.debug("doing chooseChannel"); state.stateIdentifier = VBState.CHOOSE_CHANNEL; ui.chooseChannel(this.questionsForChoosingChannel, - new ChannelChoiceCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + new ChannelChoiceCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.UNSUCCESSFUL_CHANNEL_CHOICE_MESSAGE))); } else { logger.debug("doChooseChannel: current state is " + state.stateIdentifier); @@ -208,7 +212,10 @@ public class VotingBoothImpl implements VotingBoothController { state.channelIdentifier = questionSelector.getChannelIdentifier(channelChoiceAnswers); state.channelSpecificQuestions = questionSelector.selectQuestionsForVoter(state.channelIdentifier); ui.askVoterQuestions(state.channelSpecificQuestions, - new VotingCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + new VotingCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.UNSUCCESSFUL_VOTING_MESSAGE))); } else { logger.debug("doSetChannelAndAskQuestions: current state is " + state.stateIdentifier); @@ -223,7 +230,8 @@ public class VotingBoothImpl implements VotingBoothController { state.stateIdentifier = VBState.CAST_OR_AUDIT; ui.castOrAudit(new CastOrAuditCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, - this.queue)); + this.queue, + systemMessages.get(storageManager.UNRECOGNIZED_FINALIZE_RESPONSE_MESSAGE))); } else { logger.debug("doChooseFinalizeOption: current state is " + state.stateIdentifier); @@ -233,15 +241,33 @@ public class VotingBoothImpl implements VotingBoothController { private void doCommit (EncryptAndCommitBallotCommand task) { if (state.stateIdentifier == VBState.ANSWER_QUESTIONS) { logger.debug("doing commit"); - state.stateIdentifier = VBState.COMMITTING_TO_BALLOT; - setBallotData (task); - ui.notifyVoterToWaitForFinish(SystemMessages.getWaitForCommitMessage(), - new WaitForFinishCallback(generateRequestIdentifier(), - state.currentBallotSerialNumber, - this.queue)); - outputDevice.commitToBallot(state.plaintextBallot, - state.signedEncryptedBallot, - new OutputDeviceCommitCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + try { + setBallotData(task); + ui.notifyVoterToWaitForFinish(systemMessages.get(storageManager.WAIT_FOR_COMMIT_MESSAGE), + new WaitForFinishCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.SOMETHING_WRONG_MESSAGE))); + outputDevice.commitToBallot(state.plaintextBallot, + state.signedEncryptedBallot, + new OutputDeviceCommitCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.OUTPUT_DEVICE_FAILURE_MESSAGE))); + state.stateIdentifier = VBState.COMMITTING_TO_BALLOT; + } + catch (SignatureException | IOException e) { + logger.error("doCommit: encryption failed. exception: " + e); + UIElement errorMessage = systemMessages.get(storageManager.ENCRYPTION_FAILED_MESSAGE); + UIElement[] buttons = new UIElement[]{ + systemMessages.get(storageManager.RETRY_BUTTON), + systemMessages.get(storageManager.CANCEL_VOTE_BUTTON)}; + + EncryptionFailedCallback callback = new EncryptionFailedCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue); + ui.showErrorMessageWithButtons(errorMessage, buttons, callback); + } } else { logger.debug("doCommit: current state is " + state.stateIdentifier); @@ -249,18 +275,16 @@ public class VotingBoothImpl implements VotingBoothController { } } - private void setBallotData (EncryptAndCommitBallotCommand task) { - state.plaintextBallot = PlaintextBallot.newBuilder() - .setSerialNumber(task.getBallotSerialNumber()) - .addAllAnswers(task.getVotingAnswers()) - .build(); - EncryptionAndSecrets encryptionAndSecrets = null; - try { - encryptionAndSecrets = crypto.encrypt(state.plaintextBallot); - } - catch (SignatureException | IOException e) { - // TODO: handle exception + private void setBallotData (EncryptAndCommitBallotCommand task) throws IOException, SignatureException{ + if (! (task instanceof RetryEncryptAndCommitBallotCommand)) { + // this is not a retry attempt, so the plaintext is not set yet + // otherwise, we have the plaintext from the previous encryption attempt + state.plaintextBallot = PlaintextBallot.newBuilder() + .setSerialNumber(task.getBallotSerialNumber()) + .addAllAnswers(task.getVotingAnswers()) + .build(); } + EncryptionAndSecrets encryptionAndSecrets = crypto.encrypt(state.plaintextBallot); state.signedEncryptedBallot = encryptionAndSecrets.getSignedEncryptedBallot(); state.secrets = encryptionAndSecrets.getSecrets(); } @@ -270,16 +294,28 @@ public class VotingBoothImpl implements VotingBoothController { logger.debug("finalizing"); state.stateIdentifier = VBState.FINALIZING; if (auditRequested) { - ui.notifyVoterToWaitForFinish(SystemMessages.getWaitForAuditMessage(), - new WaitForFinishCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + ui.notifyVoterToWaitForFinish(systemMessages.get(storageManager.WAIT_FOR_AUDIT_MESSAGE), + new WaitForFinishCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.SOMETHING_WRONG_MESSAGE))); outputDevice.audit(state.secrets, - new OutputDeviceFinalizeCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + new OutputDeviceFinalizeCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.OUTPUT_DEVICE_FAILURE_MESSAGE))); } else { ui.notifyVoterToWaitForFinish(SystemMessages.getWaitForCastMessage(), - new WaitForFinishCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + new WaitForFinishCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.SOMETHING_WRONG_MESSAGE))); outputDevice.castBallot( - new OutputDeviceFinalizeCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue)); + new OutputDeviceFinalizeCallback(generateRequestIdentifier(), + state.currentBallotSerialNumber, + this.queue, + systemMessages.get(storageManager.OUTPUT_DEVICE_FAILURE_MESSAGE))); } } else { @@ -325,14 +361,22 @@ public class VotingBoothImpl implements VotingBoothController { } - public void clearPlaintext () { + private void clearPlaintext () { plaintextBallot = null; } - public void clearCiphertext () { + private void clearCiphertext () { signedEncryptedBallot = null; secrets = null; } + + public void clearAndResetState(VBState newStateIdentifier) { + state.clearPlaintext(); + state.clearCiphertext(); + state.stateIdentifier = newStateIdentifier; + state.currentBallotSerialNumber += 1; + } + } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java index 69d5123..47ecd3b 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java @@ -1,9 +1,8 @@ package meerkat.voting.controller.callbacks; -import meerkat.voting.controller.SystemMessages; +import meerkat.protobuf.Voting.UIElement; import meerkat.voting.controller.commands.*; import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.RestartVotingCommand; import meerkat.voting.ui.VotingBoothUI.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,11 +11,14 @@ import java.util.concurrent.LinkedBlockingQueue; public class CastOrAuditCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(CastOrAuditCallback.class); + protected final UIElement unrecognizedFinalizeResponseMessage; public CastOrAuditCallback(int requestId, long ballotSerialNumber, - LinkedBlockingQueue controllerQueue) { + LinkedBlockingQueue controllerQueue, + UIElement unrecognizedFinalizeResponseMessage) { super(requestId, ballotSerialNumber, controllerQueue); + this.unrecognizedFinalizeResponseMessage = unrecognizedFinalizeResponseMessage; } @Override @@ -31,7 +33,7 @@ public class CastOrAuditCallback extends ControllerCallback> { protected final static Logger logger = LoggerFactory.getLogger(ChannelChoiceCallback.class); + protected final UIElement unsuccessfulChannelChoiceMessage; public ChannelChoiceCallback(int requestId, long ballotSerialNumber, - LinkedBlockingQueue controllerQueue) { + LinkedBlockingQueue controllerQueue, + UIElement unsuccessfulChannelChoiceMessage) { super(requestId, ballotSerialNumber, controllerQueue); + this.unsuccessfulChannelChoiceMessage = unsuccessfulChannelChoiceMessage; } @Override @@ -37,7 +39,7 @@ public class ChannelChoiceCallback extends ControllerCallback logger.error("channel choice initiated a failure: " + t); enqueueCommand(new ReportErrorCommand(getRequestIdentifier(), getBallotSerialNumber(), - SystemMessages.getUnsuccessfulChannelChoiceMessage())); + unsuccessfulChannelChoiceMessage)); } } } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/EncryptionFailedCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/EncryptionFailedCallback.java new file mode 100644 index 0000000..de7a61e --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/EncryptionFailedCallback.java @@ -0,0 +1,43 @@ +package meerkat.voting.controller.callbacks; + +import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException; +import meerkat.voting.controller.commands.ControllerCommand; +import meerkat.voting.controller.commands.RestartVotingCommand; +import meerkat.voting.controller.commands.RetryEncryptAndCommitBallotCommand; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.LinkedBlockingQueue; + +public class EncryptionFailedCallback extends ControllerCallback { + protected final static Logger logger = LoggerFactory.getLogger(EncryptionFailedCallback.class); + + public EncryptionFailedCallback(int requestId, + long ballotSerialNumber, + LinkedBlockingQueue controllerQueue) { + super(requestId, ballotSerialNumber, controllerQueue); + } + + @Override + public void onSuccess(Integer result) { + logger.debug("callback for voting returned success"); + int res = result.intValue(); + if (res == 0) { + logger.debug("voter chose to retry encryption"); + enqueueCommand(new RetryEncryptAndCommitBallotCommand(getRequestIdentifier(), getBallotSerialNumber())); + } + else if (res == 1) { + logger.debug("voter chose to cancel the vote"); + enqueueCommand(new RestartVotingCommand(getRequestIdentifier(), getBallotSerialNumber())); + } + else { + onFailure(new ValueException("EncryptionFailedCallback got an unknown result (" + res + ")")); + } + } + + @Override + public void onFailure(Throwable t) { + logger.error("Error message execution initiated a failure: " + t); + enqueueCommand(new RestartVotingCommand(getRequestIdentifier(), getBallotSerialNumber())); + } +} diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java index a6eaadf..a832572 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java @@ -1,6 +1,6 @@ package meerkat.voting.controller.callbacks; -import meerkat.voting.controller.SystemMessages; +import meerkat.protobuf.Voting.UIElement; import meerkat.voting.controller.commands.ControllerCommand; import meerkat.voting.controller.commands.ChooseFinalizeOptionCommand; import meerkat.voting.controller.commands.ReportErrorCommand; @@ -11,11 +11,14 @@ import java.util.concurrent.LinkedBlockingQueue; public class OutputDeviceCommitCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(OutputDeviceCommitCallback.class); + protected final UIElement outputDeviceFailureMessage; public OutputDeviceCommitCallback(int requestId, long ballotSerialNumber, - LinkedBlockingQueue controllerQueue) { + LinkedBlockingQueue controllerQueue, + UIElement outputDeviceFailureMessage) { super(requestId, ballotSerialNumber, controllerQueue); + this.outputDeviceFailureMessage = outputDeviceFailureMessage; } @Override @@ -29,6 +32,6 @@ public class OutputDeviceCommitCallback extends ControllerCallback { logger.error("OutputDeviceCommitCallback got a failure: " + t); enqueueCommand(new ReportErrorCommand(getRequestIdentifier(), getBallotSerialNumber(), - SystemMessages.getOutputDeviceFailureMessage())); + outputDeviceFailureMessage)); } } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java index 74a85e0..414bdb0 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java @@ -1,6 +1,6 @@ package meerkat.voting.controller.callbacks; -import meerkat.voting.controller.SystemMessages; +import meerkat.protobuf.Voting.UIElement; import meerkat.voting.controller.commands.ControllerCommand; import meerkat.voting.controller.commands.ReportErrorCommand; import meerkat.voting.controller.commands.RestartVotingCommand; @@ -11,11 +11,14 @@ import java.util.concurrent.LinkedBlockingQueue; public class OutputDeviceFinalizeCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(OutputDeviceFinalizeCallback.class); + protected final UIElement outputDeviceFailureMessage; public OutputDeviceFinalizeCallback(int requestId, long ballotSerialNumber, - LinkedBlockingQueue controllerQueue) { + LinkedBlockingQueue controllerQueue, + UIElement outputDeviceFailureMessage) { super(requestId, ballotSerialNumber, controllerQueue); + this.outputDeviceFailureMessage = outputDeviceFailureMessage; } @Override @@ -29,6 +32,6 @@ public class OutputDeviceFinalizeCallback extends ControllerCallback { logger.error("OutputDeviceFinalizeCallback got a failure: " + t); enqueueCommand(new ReportErrorCommand(getRequestIdentifier(), getBallotSerialNumber(), - SystemMessages.getOutputDeviceFailureMessage())); + outputDeviceFailureMessage)); } } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java index 4b6f2f7..173fa82 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java @@ -1,7 +1,6 @@ package meerkat.voting.controller.callbacks; import meerkat.protobuf.Voting.*; -import meerkat.voting.controller.SystemMessages; import meerkat.voting.controller.commands.ControllerCommand; import meerkat.voting.controller.commands.EncryptAndCommitBallotCommand; import meerkat.voting.controller.commands.ReportErrorCommand; @@ -14,11 +13,14 @@ import java.util.concurrent.LinkedBlockingQueue; public class VotingCallback extends ControllerCallback> { protected final static Logger logger = LoggerFactory.getLogger(VotingCallback.class); + protected final UIElement unsuccessfulVotingMessage; public VotingCallback(int requestId, long ballotSerialNumber, - LinkedBlockingQueue controllerQueue) { + LinkedBlockingQueue controllerQueue, + UIElement unsuccessfulVotingMessage) { super(requestId, ballotSerialNumber, controllerQueue); + this.unsuccessfulVotingMessage = unsuccessfulVotingMessage; } @Override @@ -37,7 +39,7 @@ public class VotingCallback extends ControllerCallback> { logger.error("voting initiated a failure: " + t); enqueueCommand(new ReportErrorCommand(getRequestIdentifier(), getBallotSerialNumber(), - SystemMessages.getUnsuccessfulVotingMessage())); + unsuccessfulVotingMessage)); } } } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java index 9f7a159..2634e27 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java @@ -1,9 +1,8 @@ package meerkat.voting.controller.callbacks; -import meerkat.voting.controller.SystemMessages; +import meerkat.protobuf.Voting.UIElement; import meerkat.voting.controller.commands.ControllerCommand; import meerkat.voting.controller.commands.ReportErrorCommand; -import meerkat.voting.controller.commands.RestartVotingCommand; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,11 +10,14 @@ import java.util.concurrent.LinkedBlockingQueue; public class WaitForFinishCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(WaitForFinishCallback.class); + protected final UIElement somethingWrongMessage; public WaitForFinishCallback(int requestId, long ballotSerialNumber, - LinkedBlockingQueue controllerQueue) { + LinkedBlockingQueue controllerQueue, + UIElement somethingWrongMessage) { super(requestId, ballotSerialNumber, controllerQueue); + this.somethingWrongMessage = somethingWrongMessage; } @Override @@ -27,6 +29,6 @@ public class WaitForFinishCallback extends ControllerCallback { logger.error("WaitForFinishCallback got a failure: " + t); enqueueCommand(new ReportErrorCommand(getRequestIdentifier(), getBallotSerialNumber(), - SystemMessages.getSomethingWrongMessage())); + somethingWrongMessage)); } } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java index 074216f..d7e4508 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java @@ -1,13 +1,14 @@ package meerkat.voting.controller.commands; -import meerkat.protobuf.Voting.*; - +import meerkat.protobuf.Voting.BallotAnswer; import java.util.List; public class EncryptAndCommitBallotCommand extends ControllerCommand { private final List votingAnswers; - public EncryptAndCommitBallotCommand(int requestIdentifier, long ballotSerialNumber, List answers) { + public EncryptAndCommitBallotCommand(int requestIdentifier, + long ballotSerialNumber, + List answers) { super(requestIdentifier, ballotSerialNumber); votingAnswers = answers; } @@ -15,4 +16,5 @@ public class EncryptAndCommitBallotCommand extends ControllerCommand { public List getVotingAnswers() { return votingAnswers; } + } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/RetryEncryptAndCommitBallotCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/RetryEncryptAndCommitBallotCommand.java new file mode 100644 index 0000000..66dc992 --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/RetryEncryptAndCommitBallotCommand.java @@ -0,0 +1,10 @@ +package meerkat.voting.controller.commands; + +public class RetryEncryptAndCommitBallotCommand extends EncryptAndCommitBallotCommand { + + public RetryEncryptAndCommitBallotCommand(int requestIdentifier, + long ballotSerialNumber) { + super(requestIdentifier, ballotSerialNumber, null); + } + +} diff --git a/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManager.java b/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManager.java index e664607..d5216e4 100644 --- a/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManager.java +++ b/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManager.java @@ -36,6 +36,7 @@ public interface VBCryptoManager { * @param plaintextBallot - all plaintext ballot info of the voter * @return an encryption of the ballot */ + // TODO: do we seed the random here? public EncryptionAndSecrets encrypt (PlaintextBallot plaintextBallot) throws SignatureException, IOException; diff --git a/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManagerImpl.java b/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManagerImpl.java index 722c24e..2bc9729 100644 --- a/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManagerImpl.java +++ b/voting-booth/src/main/java/meerkat/voting/encryptor/VBCryptoManagerImpl.java @@ -52,6 +52,8 @@ public class VBCryptoManagerImpl implements VBCryptoManager { .setSignature(digitalSignature.sign()) .build(); + // TODO: still has to supply RandomnessGenerationProof as well + return new EncryptionAndSecrets(signedEncryptedBallot, secrets); } catch (IOException e) { diff --git a/voting-booth/src/main/java/meerkat/voting/storage/StorageManager.java b/voting-booth/src/main/java/meerkat/voting/storage/StorageManager.java index 9bf7764..b9ccca7 100644 --- a/voting-booth/src/main/java/meerkat/voting/storage/StorageManager.java +++ b/voting-booth/src/main/java/meerkat/voting/storage/StorageManager.java @@ -3,6 +3,7 @@ package meerkat.voting.storage; import meerkat.protobuf.Voting.*; import java.io.IOException; +import java.util.Map; /** * An interface for the storage component of the voting booth @@ -29,4 +30,20 @@ public interface StorageManager { */ public void writeElectionParams(ElectionParams params) throws IOException; + + public Map readSystemMessages() throws IOException; + + + public final static String WAIT_FOR_COMMIT_MESSAGE = "waitForCommit"; + public final static String WAIT_FOR_AUDIT_MESSAGE = "waitForAudit"; + public final static String WAIT_FOR_CAST_MESSAGE = "waitForCast"; + public final static String RESTART_VOTING_BUTTON = "restartVotingButton"; + public final static String UNRECOGNIZED_FINALIZE_RESPONSE_MESSAGE = "unrecognizedFinalizeResponse"; + public final static String UNSUCCESSFUL_CHANNEL_CHOICE_MESSAGE = "unsuccessfulChannelChoice"; + public final static String OUTPUT_DEVICE_FAILURE_MESSAGE = "outputDeviceFailure"; + public final static String UNSUCCESSFUL_VOTING_MESSAGE = "unsuccessfulVoting"; + public final static String SOMETHING_WRONG_MESSAGE = "somethingWrong"; + public final static String ENCRYPTION_FAILED_MESSAGE = "encryptionFailed"; + public final static String RETRY_BUTTON = "retryButton"; + public final static String CANCEL_VOTE_BUTTON = "cancelVoteButton"; } diff --git a/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java b/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java index 23c89cf..ea9ac08 100644 --- a/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java +++ b/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java @@ -1,5 +1,6 @@ package meerkat.voting.storage; +import com.google.protobuf.ByteString; import meerkat.protobuf.Voting.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,6 +8,8 @@ import org.slf4j.LoggerFactory; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; /** * A mockup for the StorageManager interface @@ -16,7 +19,8 @@ public class StorageManagerMockup implements StorageManager { private boolean adminHardwareKeyInserted; private Logger logger; - private String electionParamFullFilename = "~/meerkat_election_params_tempfile.dat"; + public static final String electionParamFullFilename = "/home/hai/meerkat-java/meerkat_election_params_tempfile.dat"; + public static final String systemMessagesFilename = "/home/hai/meerkat-java/meerkat_booth_system_messages.dat"; public StorageManagerMockup () { logger = LoggerFactory.getLogger(StorageManagerMockup.class); @@ -64,4 +68,23 @@ public class StorageManagerMockup implements StorageManager { } } + + @Override + public Map readSystemMessages() throws IOException { + + logger.info("Entered method readSystemMessages"); + BoothSystemMessages systemMessages; + try { + FileInputStream inputStream = new FileInputStream(systemMessagesFilename); + systemMessages = BoothSystemMessages.parseFrom(inputStream); + inputStream.close(); + logger.info ("Successfully read systemMessages protobuf from a file"); + } + catch (IOException e) { + logger.error("Could not read from the systemMessages file: '" + systemMessagesFilename + "'."); + throw e; + } + return systemMessages.getSystemMessage(); + } + }