diff --git a/meerkat-common/src/main/proto/meerkat/voting.proto b/meerkat-common/src/main/proto/meerkat/voting.proto index 9837cce..759a708 100644 --- a/meerkat-common/src/main/proto/meerkat/voting.proto +++ b/meerkat-common/src/main/proto/meerkat/voting.proto @@ -6,13 +6,38 @@ import 'meerkat/crypto.proto'; option java_package = "meerkat.protobuf"; -// A ballot question. This is an opaque -// data type that is parsed by the UI to display -// the question. -message BallotQuestion { - bytes data = 1; + + +// Type of the element data to be presented by UI +enum UIElementDataType { + TEXT = 0; + IMAGE = 1; + VOICE = 2; } +// Type of question +enum QuestionType { + MULTIPLE_CHOICE = 0; + MULTIPLE_SELECTION = 1; + ORDER = 2; +} + +// An element to be presented by UI +message UIElement { + UIElementDataType type = 1; + bytes data = 2; +} + +// a new data structure for BallotQuestion. Need to delete the old one +message BallotQuestion { + bool is_mandatory = 1; + UIElement question = 2; + UIElement description = 3; + repeated UIElement answer = 4; +} + + + // An answer to a specific ballot question. // The answer is a vector of signed integers, // to encompass voting schemes such as ranked voting @@ -83,7 +108,7 @@ message ElectionParams { repeated BallotQuestion questions = 6; // Translation table between answers and plaintext encoding - BallotAnswerTranslationTable answerTranslationTable = 7; + //BallotAnswerTranslationTable answerTranslationTable = 7; // Data required in order to access the Bulletin Board Servers BulletinBoardClientParams bulletinBoardClientParams = 8; diff --git a/voting-booth/src/main/java/meerkat/voting/BallotOutputDevice.java b/voting-booth/src/main/java/meerkat/voting/BallotOutputDevice.java new file mode 100644 index 0000000..32e3208 --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/BallotOutputDevice.java @@ -0,0 +1,19 @@ +package meerkat.voting; + +import meerkat.protobuf.Voting.*; + +/** + * Created by hai on 15/02/16. + */ +public interface BallotOutputDevice { + + void commitToBallot(long sessionId, EncryptedBallot encryptedBallot, VotingBooth.Callback callback); + + void audit(long sessionId, EncryptedBallot encryptedBallot, BallotSecrets ballotSecrets, VotingBooth.Callback callback); + + void castBallot(long sessionId, VotingBooth.Callback callback); + + // probably has no difference than cast. Maybe drop this method + void cancelBallot(long sessionId, VotingBooth.Callback callback); + +} diff --git a/voting-booth/src/main/java/meerkat/voting/Encryptor.java b/voting-booth/src/main/java/meerkat/voting/Encryptor.java new file mode 100644 index 0000000..4cfcf57 --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/Encryptor.java @@ -0,0 +1,13 @@ +package meerkat.voting; + +import meerkat.protobuf.Voting.*; + +/** + * Created by hai on 23/02/16. + */ +public interface Encryptor { + + public void encrypt (long sessionId, PlaintextBallot plaintextBallot); + + //TODO: probably needs some key generation methods as well +} diff --git a/voting-booth/src/main/java/meerkat/voting/StorageManager.java b/voting-booth/src/main/java/meerkat/voting/StorageManager.java new file mode 100644 index 0000000..3edff7a --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/StorageManager.java @@ -0,0 +1,12 @@ +package meerkat.voting; + +/** + * Created by hai on 23/02/16. + */ +public interface StorageManager { + + // should these methods be synchronous or asynchronous? Can we rely on it being immediate? + public void detectAdminHardwareKey(); + + public void readElectionParams (); +} diff --git a/voting-booth/src/main/java/meerkat/voting/SystemConsoleOutputDevice.java b/voting-booth/src/main/java/meerkat/voting/SystemConsoleOutputDevice.java new file mode 100644 index 0000000..7546d53 --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/SystemConsoleOutputDevice.java @@ -0,0 +1,56 @@ +package meerkat.voting; + +import com.google.protobuf.ByteString; +import meerkat.protobuf.Voting.*; + +/** + * Created by hai on 15/02/16. + */ +public class SystemConsoleOutputDevice implements BallotOutputDevice { + + /* + * Returns the UTF8 decoding of byte-string data + */ + private static String bytesToString(ByteString data) { + return data.toStringUtf8(); + } + + @Override + public void commitToBallot(long sessionId, EncryptedBallot encryptedBallot, VotingBooth.Callback callback) { + + System.out.println("Ballot #" + encryptedBallot.getSerialNumber() + ": " + + bytesToString(encryptedBallot.getData().getData())); + + callback.ballotCommitResult(sessionId, true); + + } + + @Override + public void audit(long sessionId, EncryptedBallot encryptedBallot, BallotSecrets ballotSecrets, VotingBooth.Callback callback) { + + //TODO: generate standard form for this + System.out.println("Ballot #" + encryptedBallot.getSerialNumber() + ": " + + bytesToString(encryptedBallot.getData().getData())); + + callback.ballotAuditResult(sessionId, true); + + } + + @Override + public void castBallot(long sessionId, VotingBooth.Callback callback) { + + System.out.println("Ballot finalized!"); + + callback.ballotCastResult(sessionId, true); + + } + + @Override + public void cancelBallot(long sessionId, VotingBooth.Callback callback) { + + System.out.println("Ballot cancelled!"); + + callback.ballotCancelResult(sessionId, true); + + } +} diff --git a/voting-booth/src/main/java/meerkat/voting/UI.java b/voting-booth/src/main/java/meerkat/voting/UI.java new file mode 100644 index 0000000..83739db --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/UI.java @@ -0,0 +1,32 @@ +package meerkat.voting; + +import meerkat.protobuf.Voting.*; + +/** + * Created by hai on 23/02/16. + */ +public interface UI { + + + // Voter scenario methods + void introductionToVoter (long sessionId); + + void chooseChannel (long sessionId, BallotQuestion question); + + void askVoterQuestion (long sessionId, int questionNumber, BallotQuestion question); + + void castOrAudit (long sessionId); + + void showWaitForFinishScreen (long sessionId); + + + // Admin scenario methods + //TODO: the admin scenario still needs some more thinking + + + + // bad thing happened scenario + void showErrorMessageAndHalt (String errorMessage); + void showErrorMessageWithCancelButton (long sessionId, String errorMessage); + +} diff --git a/voting-booth/src/main/java/meerkat/voting/VotingBooth.java b/voting-booth/src/main/java/meerkat/voting/VotingBooth.java new file mode 100644 index 0000000..a7df483 --- /dev/null +++ b/voting-booth/src/main/java/meerkat/voting/VotingBooth.java @@ -0,0 +1,82 @@ +package meerkat.voting; + +import meerkat.protobuf.Voting; +import meerkat.protobuf.Voting.*; + +/** + * Created by hai on 23/02/16. + */ +public interface VotingBooth { + + public enum ErrorID { + OUTPUT_DEVICE_OUT_OF_PAPER, + OUTPUT_DEVICE_OUT_OF_INK, + OUTPUT_DEVICE_NO_CONNECTION, + OUTPUT_DEVICE_HARDWARE_NOT_FOUND, + + UI_HARDWARE_NOT_FOUND + } + + + // keeps track in which state we are + // internal state will also include the number of the current question and the answers we got so far, + // later it includes the details of the PlaintextBallot and later the Encryption and the secrets + public enum State { + INITIALIZED, + + VOTER_INTRODUCTION, + VOTER_CHOOSE_CHANNEL, + VOTER_VOTING, + VOTER_ENCRYPTING, + VOTER_CAST_OR_AUDIT, + VOTER_CASTING, + VOTER_AUDITING + + } + + public interface Callback { + + // callbacks and messages from BallotOutputDevice + + public void ballotCommitResult (long sessionId, boolean result); + public void ballotCastResult (long sessionId, boolean result); + public void ballotAuditResult (long sessionId, boolean result); + public void ballotCancelResult (long sessionId, boolean result); + // other error messages, such as Printer turned-off or out-of-paper + public void outputDeviceReportProblem (ErrorID errorId); + + + // callbacks and messages from UI + + public void introductionFinished (long sessionId); + public void choiceOfChannel (long sessionId, int channelNumber); + public void skipQuestion (long sessionId, int questionNumber); + public void backwardsQuestion (long sessionId, int questionNumber); + public void cancelVotingSession (long sessionId); + public void answer (long sessionId, int questionNumber, String answer); + public void cast (long sessionId); + public void audit (long sessionId); + // other error messages, such as hardware-not-detected + public void uiReportProblem (ErrorID errorId); + + + // callbacks from encryptor + + public void returnEncryption (long sessionId, EncryptedBallot encryptedBallot, BallotSecrets secrets); + + + // callbacks from StorageManager + + public void adminHardwareKeyDetected (boolean isKeyInserted); + public void loadElectionParams (ElectionParams electionParams); + } + + // this function is synchronous + public void start (); + + + // messages from Admin Console (If there is such one) + // this function is asynchronous + public void shutDown(); + +}