change the output class to run as a thread.
It is now runnable and has its own queue of (also new) OutputCommands, and its own shutdown flag.vbdev2
parent
76d3fdeac2
commit
13f8948cfb
|
@ -73,8 +73,7 @@ message EncryptedBallot {
|
||||||
|
|
||||||
message SignedEncryptedBallot {
|
message SignedEncryptedBallot {
|
||||||
EncryptedBallot encrypted_ballot = 1;
|
EncryptedBallot encrypted_ballot = 1;
|
||||||
bytes signer_id = 2;
|
Signature signature = 2;
|
||||||
Signature signature = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message BallotSecrets {
|
message BallotSecrets {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package meerkat.voting;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import com.google.protobuf.Message;
|
||||||
|
import meerkat.crypto.Encryption;
|
||||||
|
import meerkat.protobuf.Crypto.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 07/06/16.
|
||||||
|
*/
|
||||||
|
public class ToyEncryption implements Encryption {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RerandomizableEncryptedMessage encrypt(Message plaintext, EncryptionRandomness rnd) throws IOException {
|
||||||
|
ByteString cipher = ByteString.copyFromUtf8("Encryption(")
|
||||||
|
.concat(plaintext.toByteString())
|
||||||
|
.concat(ByteString.copyFromUtf8(", Random("))
|
||||||
|
.concat(rnd.getData())
|
||||||
|
.concat(ByteString.copyFromUtf8("))"));
|
||||||
|
return RerandomizableEncryptedMessage.newBuilder()
|
||||||
|
.setData(cipher)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RerandomizableEncryptedMessage rerandomize
|
||||||
|
(RerandomizableEncryptedMessage msg, EncryptionRandomness rnd) throws InvalidProtocolBufferException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EncryptionRandomness generateRandomness(Random rand) {
|
||||||
|
ByteBuffer b = ByteBuffer.allocate(4);
|
||||||
|
b.putInt(rand.nextInt());
|
||||||
|
byte[] bArr = b.array();
|
||||||
|
ByteString bs = ByteString.copyFrom(bArr);
|
||||||
|
return EncryptionRandomness.newBuilder()
|
||||||
|
.setData(bs)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package meerkat.voting;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.Message;
|
||||||
|
import meerkat.crypto.DigitalSignature;
|
||||||
|
import meerkat.protobuf.Crypto.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.security.UnrecoverableKeyException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 07/06/16.
|
||||||
|
*/
|
||||||
|
public class ToySignature implements DigitalSignature {
|
||||||
|
|
||||||
|
private final ByteString signerID;
|
||||||
|
private ByteString msgByteString;
|
||||||
|
|
||||||
|
|
||||||
|
public ToySignature(String signerID) {
|
||||||
|
this.signerID = ByteString.copyFromUtf8(signerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteString getSignerID() {
|
||||||
|
return signerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateContent(Message msg) throws SignatureException {
|
||||||
|
msgByteString = msg.toByteString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Signature sign() throws SignatureException {
|
||||||
|
ByteString signature = ByteString.copyFromUtf8("Signature(")
|
||||||
|
.concat(msgByteString)
|
||||||
|
.concat(ByteString.copyFromUtf8(")"));
|
||||||
|
return Signature.newBuilder()
|
||||||
|
.setType(SignatureType.ECDSA)
|
||||||
|
.setData(signature)
|
||||||
|
.setSignerId(getSignerID())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadVerificationCertificates(InputStream certStream) throws CertificateException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearVerificationCertificates() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initVerify(Signature sig) throws CertificateException, InvalidKeyException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder) throws IOException, CertificateException, UnrecoverableKeyException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearSigningKey() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,200 @@
|
||||||
|
package meerkat.voting;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import meerkat.crypto.DigitalSignature;
|
||||||
|
import meerkat.crypto.Encryption;
|
||||||
|
import meerkat.protobuf.Voting.*;
|
||||||
|
import meerkat.voting.controller.*;
|
||||||
|
import meerkat.voting.controller.selector.SimpleListCategoriesSelector;
|
||||||
|
import meerkat.voting.output.*;
|
||||||
|
import meerkat.voting.storage.*;
|
||||||
|
import meerkat.voting.encryptor.*;
|
||||||
|
import meerkat.voting.ui.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 26/04/16.
|
||||||
|
*/
|
||||||
|
public class VotingBoothToyRun {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Random rand = new Random();
|
||||||
|
Encryption enc = new ToyEncryption();
|
||||||
|
DigitalSignature sig = new ToySignature("MY_SIGNER_ID");
|
||||||
|
|
||||||
|
StorageManager storageManager = new StorageManagerMockup();
|
||||||
|
SystemConsoleOutputDevice outputDevice = new SystemConsoleOutputDevice();
|
||||||
|
VBCryptoManager cryptoManager = new VBCryptoManagerImpl(rand, enc, sig);
|
||||||
|
SystemConsoleUI ui = new SystemConsoleUI ();
|
||||||
|
|
||||||
|
|
||||||
|
VotingBoothImpl controller = new VotingBoothImpl();
|
||||||
|
controller.init(outputDevice, cryptoManager, ui, storageManager);
|
||||||
|
|
||||||
|
generateDemoQuestions(controller);
|
||||||
|
|
||||||
|
// create threads
|
||||||
|
|
||||||
|
|
||||||
|
Thread controllerThread = new Thread(controller);
|
||||||
|
controllerThread.setName("Meerkat VB-Controller Thread");
|
||||||
|
Thread uiThread = new Thread(ui);
|
||||||
|
uiThread.setName("Meerkat VB-UI Thread");
|
||||||
|
Thread outputThread = new Thread(outputDevice);
|
||||||
|
uiThread.setName("Meerkat VB-Output Thread");
|
||||||
|
|
||||||
|
uiThread.start();
|
||||||
|
controllerThread.start();
|
||||||
|
outputThread.start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void generateDemoQuestions(VotingBoothController controller) {
|
||||||
|
|
||||||
|
List<BallotQuestion> channelChoiceQuestions = generateCahnnelChoiceQuestions();
|
||||||
|
controller.setBallotChannelChoiceQuestions(channelChoiceQuestions);
|
||||||
|
|
||||||
|
List<BallotQuestion> allBallotQuestions = generateBallotQuestions();
|
||||||
|
controller.setBallotRaceQuestions(allBallotQuestions);
|
||||||
|
|
||||||
|
SimpleCategoriesSelectionData selectionData = generateSelectionData();
|
||||||
|
SimpleListCategoriesSelector selector = new SimpleListCategoriesSelector(allBallotQuestions, selectionData);
|
||||||
|
controller.setChannelQuestionSelector(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static List<BallotQuestion> generateCahnnelChoiceQuestions() {
|
||||||
|
ArrayList<BallotQuestion> channelChoiceQuestions = new ArrayList();
|
||||||
|
|
||||||
|
String[] ans1 = {"Red", "Blue", "Green"};
|
||||||
|
BallotQuestion ccquestion1 = generateBallotQuestion("What is your favorite color?", "Pick one answer", ans1);
|
||||||
|
channelChoiceQuestions.add(ccquestion1);
|
||||||
|
|
||||||
|
String[] ans2 = {"Yes", "No"};
|
||||||
|
BallotQuestion ccquestion2 = generateBallotQuestion("Are you a republican?", "Pick one answer", ans2);
|
||||||
|
channelChoiceQuestions.add(ccquestion2);
|
||||||
|
|
||||||
|
return channelChoiceQuestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static List<BallotQuestion> generateBallotQuestions() {
|
||||||
|
ArrayList<BallotQuestion> allBallotQuestions = new ArrayList();
|
||||||
|
|
||||||
|
String[] answers1 = {"answer 1", "answer 2", "answer 3", "answer 4"};
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 1. Asking something...", "Pick one answer", answers1));
|
||||||
|
|
||||||
|
String[] answers2 = {"Miranda Kerr", "Doutzen Kroes", "Moran Atias", "Roslana Rodina", "Adriana Lima"};
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 2: Which model do you like", "Mark as many as you want", answers2));
|
||||||
|
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 3. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 4. Asking something...", "Pick one answer", answers1));
|
||||||
|
|
||||||
|
String[] answers5 = {"Clint Eastwood", "Ninja", "Sonic", "Tai-chi", "Diablo", "Keanu"};
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 5: Good name for a cat", "Pick the best one", answers5));
|
||||||
|
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 6. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 7. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 8. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 9. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 10. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 11. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 12. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 13. Asking something...", "Pick one answer", answers1));
|
||||||
|
allBallotQuestions.add(generateBallotQuestion("question 14. Asking something...", "Pick one answer", answers1));
|
||||||
|
|
||||||
|
return allBallotQuestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static BallotQuestion generateBallotQuestion(String questionStr, String descriptionStr, String[] answers) {
|
||||||
|
UIElement question = UIElement.newBuilder()
|
||||||
|
.setType(UIElementDataType.TEXT)
|
||||||
|
.setData(stringToBytes(questionStr))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
UIElement description = UIElement.newBuilder()
|
||||||
|
.setType(UIElementDataType.TEXT)
|
||||||
|
.setData(stringToBytes(descriptionStr))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
BallotQuestion.Builder bqb = BallotQuestion.newBuilder();
|
||||||
|
bqb.setIsMandatory(false);
|
||||||
|
bqb.setQuestion(question);
|
||||||
|
bqb.setDescription(description);
|
||||||
|
for (String answerStr : answers) {
|
||||||
|
UIElement answer = UIElement.newBuilder()
|
||||||
|
.setType(UIElementDataType.TEXT)
|
||||||
|
.setData(stringToBytes(answerStr))
|
||||||
|
.build();
|
||||||
|
bqb.addAnswer(answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bqb.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static SimpleCategoriesSelectionData generateSelectionData() {
|
||||||
|
Category sharedDefaults = Category.newBuilder()
|
||||||
|
.addQuestionIndex(0)
|
||||||
|
.addQuestionIndex(5)
|
||||||
|
.addQuestionIndex(9)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Category cat00 = Category.newBuilder()
|
||||||
|
.addQuestionIndex(1)
|
||||||
|
.addQuestionIndex(4)
|
||||||
|
.addQuestionIndex(6)
|
||||||
|
.addQuestionIndex(7)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Category cat01 = Category.newBuilder()
|
||||||
|
.addQuestionIndex(2)
|
||||||
|
.addQuestionIndex(4)
|
||||||
|
.addQuestionIndex(8)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Category cat02 = Category.newBuilder()
|
||||||
|
.addQuestionIndex(3)
|
||||||
|
.addQuestionIndex(8)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Category cat10 = Category.newBuilder()
|
||||||
|
.addQuestionIndex(10)
|
||||||
|
.addQuestionIndex(11)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Category cat11 = Category.newBuilder()
|
||||||
|
.addQuestionIndex(12)
|
||||||
|
.addQuestionIndex(13)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CategoryChooser catChooser0 = CategoryChooser.newBuilder()
|
||||||
|
.addCategory(cat00)
|
||||||
|
.addCategory(cat01)
|
||||||
|
.addCategory(cat02)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CategoryChooser catChooser1 = CategoryChooser.newBuilder()
|
||||||
|
.addCategory(cat10)
|
||||||
|
.addCategory(cat11)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return SimpleCategoriesSelectionData.newBuilder()
|
||||||
|
.setSharedDefaults(sharedDefaults)
|
||||||
|
.addCategoryChooser(catChooser0)
|
||||||
|
.addCategoryChooser(catChooser1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
private static ByteString stringToBytes (String s) {
|
||||||
|
return ByteString.copyFromUtf8(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -108,6 +108,7 @@ public class VotingBoothImpl implements VotingBoothController {
|
||||||
shutDownHasBeenCalled = true;
|
shutDownHasBeenCalled = true;
|
||||||
queue.clear();
|
queue.clear();
|
||||||
ui.callShutDown();
|
ui.callShutDown();
|
||||||
|
outputDevice.callShutDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSingleTask (ControllerCommand task) {
|
private void handleSingleTask (ControllerCommand task) {
|
||||||
|
@ -122,18 +123,21 @@ public class VotingBoothImpl implements VotingBoothController {
|
||||||
if (task instanceof RestartVotingCommand) {
|
if (task instanceof RestartVotingCommand) {
|
||||||
doRestartVoting ();
|
doRestartVoting ();
|
||||||
}
|
}
|
||||||
else if (task instanceof CastCommand) {
|
|
||||||
doFinalize(false);
|
|
||||||
}
|
|
||||||
else if (task instanceof AuditCommand) {
|
|
||||||
doFinalize(true);
|
|
||||||
}
|
|
||||||
else if (task instanceof ChannelChoiceCommand) {
|
else if (task instanceof ChannelChoiceCommand) {
|
||||||
doChooseChannel();
|
doChooseChannel();
|
||||||
}
|
}
|
||||||
else if (task instanceof ChannelDeterminedCommand) {
|
else if (task instanceof ChannelDeterminedCommand) {
|
||||||
doSetChannelAndAskQuestions ((ChannelDeterminedCommand)task);
|
doSetChannelAndAskQuestions ((ChannelDeterminedCommand)task);
|
||||||
}
|
}
|
||||||
|
else if (task instanceof ChooseFinalizeOptionCommand) {
|
||||||
|
doChooseFinalizeOption();
|
||||||
|
}
|
||||||
|
else if (task instanceof CastCommand) {
|
||||||
|
doFinalize(false);
|
||||||
|
}
|
||||||
|
else if (task instanceof AuditCommand) {
|
||||||
|
doFinalize(true);
|
||||||
|
}
|
||||||
else if (task instanceof EncryptAndCommitBallotCommand) {
|
else if (task instanceof EncryptAndCommitBallotCommand) {
|
||||||
doCommit ((EncryptAndCommitBallotCommand)task);
|
doCommit ((EncryptAndCommitBallotCommand)task);
|
||||||
}
|
}
|
||||||
|
@ -213,6 +217,19 @@ public class VotingBoothImpl implements VotingBoothController {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void doChooseFinalizeOption() {
|
||||||
|
if (state.stateIdentifier == VBState.COMMITTING_TO_BALLOT) {
|
||||||
|
logger.debug("doChooseFinalizeOption");
|
||||||
|
state.stateIdentifier = VBState.CAST_OR_AUDIT;
|
||||||
|
ui.castOrAudit(new CastOrAuditCallback(generateRequestIdentifier(),
|
||||||
|
state.currentBallotSerialNumber,
|
||||||
|
this.queue));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.debug("doChooseFinalizeOption: current state is " + state.stateIdentifier);
|
||||||
|
// ignore this request
|
||||||
|
}
|
||||||
|
}
|
||||||
private void doCommit (EncryptAndCommitBallotCommand task) {
|
private void doCommit (EncryptAndCommitBallotCommand task) {
|
||||||
if (state.stateIdentifier == VBState.ANSWER_QUESTIONS) {
|
if (state.stateIdentifier == VBState.ANSWER_QUESTIONS) {
|
||||||
logger.debug("doing commit");
|
logger.debug("doing commit");
|
||||||
|
@ -224,7 +241,7 @@ public class VotingBoothImpl implements VotingBoothController {
|
||||||
this.queue));
|
this.queue));
|
||||||
outputDevice.commitToBallot(state.plaintextBallot,
|
outputDevice.commitToBallot(state.plaintextBallot,
|
||||||
state.signedEncryptedBallot,
|
state.signedEncryptedBallot,
|
||||||
new OutputDeviceCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
new OutputDeviceCommitCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logger.debug("doCommit: current state is " + state.stateIdentifier);
|
logger.debug("doCommit: current state is " + state.stateIdentifier);
|
||||||
|
@ -252,15 +269,17 @@ public class VotingBoothImpl implements VotingBoothController {
|
||||||
if (state.stateIdentifier == VBState.CAST_OR_AUDIT) {
|
if (state.stateIdentifier == VBState.CAST_OR_AUDIT) {
|
||||||
logger.debug("finalizing");
|
logger.debug("finalizing");
|
||||||
state.stateIdentifier = VBState.FINALIZING;
|
state.stateIdentifier = VBState.FINALIZING;
|
||||||
|
if (auditRequested) {
|
||||||
ui.notifyVoterToWaitForFinish(SystemMessages.getWaitForAuditMessage(),
|
ui.notifyVoterToWaitForFinish(SystemMessages.getWaitForAuditMessage(),
|
||||||
new WaitForFinishCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
new WaitForFinishCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
||||||
if (auditRequested) {
|
|
||||||
outputDevice.audit(state.secrets,
|
outputDevice.audit(state.secrets,
|
||||||
new OutputDeviceCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
new OutputDeviceFinalizeCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
ui.notifyVoterToWaitForFinish(SystemMessages.getWaitForCastMessage(),
|
||||||
|
new WaitForFinishCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
||||||
outputDevice.castBallot(
|
outputDevice.castBallot(
|
||||||
new OutputDeviceCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
new OutputDeviceFinalizeCallback(generateRequestIdentifier(), state.currentBallotSerialNumber, this.queue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package meerkat.voting.controller.callbacks;
|
||||||
|
|
||||||
|
import meerkat.voting.controller.SystemMessages;
|
||||||
|
import meerkat.voting.controller.commands.ControllerCommand;
|
||||||
|
import meerkat.voting.controller.commands.ChooseFinalizeOptionCommand;
|
||||||
|
import meerkat.voting.controller.commands.ReportErrorCommand;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
public class OutputDeviceCommitCallback extends ControllerCallback<Void> {
|
||||||
|
protected final static Logger logger = LoggerFactory.getLogger(OutputDeviceCommitCallback.class);
|
||||||
|
|
||||||
|
public OutputDeviceCommitCallback(int requestId,
|
||||||
|
long ballotSerialNumber,
|
||||||
|
LinkedBlockingQueue<ControllerCommand> controllerQueue) {
|
||||||
|
super(requestId, ballotSerialNumber, controllerQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Void v) {
|
||||||
|
logger.debug("callback for output device commit success");
|
||||||
|
enqueueCommand(new ChooseFinalizeOptionCommand(getRequestIdentifier(), getBallotSerialNumber()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
logger.error("OutputDeviceCommitCallback got a failure: " + t);
|
||||||
|
enqueueCommand(new ReportErrorCommand(getRequestIdentifier(),
|
||||||
|
getBallotSerialNumber(),
|
||||||
|
SystemMessages.getOutputDeviceFailureMessage()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,10 +9,10 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
public class OutputDeviceCallback extends ControllerCallback<Void> {
|
public class OutputDeviceFinalizeCallback extends ControllerCallback<Void> {
|
||||||
protected final static Logger logger = LoggerFactory.getLogger(OutputDeviceCallback.class);
|
protected final static Logger logger = LoggerFactory.getLogger(OutputDeviceFinalizeCallback.class);
|
||||||
|
|
||||||
public OutputDeviceCallback(int requestId,
|
public OutputDeviceFinalizeCallback(int requestId,
|
||||||
long ballotSerialNumber,
|
long ballotSerialNumber,
|
||||||
LinkedBlockingQueue<ControllerCommand> controllerQueue) {
|
LinkedBlockingQueue<ControllerCommand> controllerQueue) {
|
||||||
super(requestId, ballotSerialNumber, controllerQueue);
|
super(requestId, ballotSerialNumber, controllerQueue);
|
||||||
|
@ -20,11 +20,13 @@ public class OutputDeviceCallback extends ControllerCallback<Void> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void v) {
|
public void onSuccess(Void v) {
|
||||||
|
logger.debug("callback for output device finalize success");
|
||||||
|
enqueueCommand(new RestartVotingCommand(getRequestIdentifier(), getBallotSerialNumber()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void onFailure(Throwable t) {
|
||||||
logger.error("WaitForFinishCallback got a failure: " + t);
|
logger.error("OutputDeviceFinalizeCallback got a failure: " + t);
|
||||||
enqueueCommand(new ReportErrorCommand(getRequestIdentifier(),
|
enqueueCommand(new ReportErrorCommand(getRequestIdentifier(),
|
||||||
getBallotSerialNumber(),
|
getBallotSerialNumber(),
|
||||||
SystemMessages.getOutputDeviceFailureMessage()));
|
SystemMessages.getOutputDeviceFailureMessage()));
|
|
@ -0,0 +1,10 @@
|
||||||
|
package meerkat.voting.controller.commands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 11/04/16.
|
||||||
|
*/
|
||||||
|
public class ChooseFinalizeOptionCommand extends ControllerCommand {
|
||||||
|
public ChooseFinalizeOptionCommand(int requestIdentifier, long ballotSerialNumber) {
|
||||||
|
super(requestIdentifier, ballotSerialNumber);
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,7 +49,6 @@ public class VBCryptoManagerImpl implements VBCryptoManager {
|
||||||
|
|
||||||
SignedEncryptedBallot signedEncryptedBallot = SignedEncryptedBallot.newBuilder()
|
SignedEncryptedBallot signedEncryptedBallot = SignedEncryptedBallot.newBuilder()
|
||||||
.setEncryptedBallot(encBallot)
|
.setEncryptedBallot(encBallot)
|
||||||
.setSignerId(digitalSignature.getSignerID())
|
|
||||||
.setSignature(digitalSignature.sign())
|
.setSignature(digitalSignature.sign())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
|
@ -37,4 +37,5 @@ public interface BallotOutputDevice {
|
||||||
*/
|
*/
|
||||||
public void cancelBallot(FutureCallback<Void> callback);
|
public void cancelBallot(FutureCallback<Void> callback);
|
||||||
|
|
||||||
|
public void callShutDown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,31 @@ import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import meerkat.protobuf.Crypto.*;
|
import meerkat.protobuf.Crypto.*;
|
||||||
import meerkat.protobuf.Voting.*;
|
import meerkat.protobuf.Voting.*;
|
||||||
|
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||||
|
import meerkat.voting.output.outputcommands.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A toy OutputDevice class
|
* A toy OutputDevice class
|
||||||
* outputs everything simply to the System console
|
* outputs everything simply to the System console
|
||||||
*/
|
*/
|
||||||
public class SystemConsoleOutputDevice implements BallotOutputDevice {
|
public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
|
||||||
|
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
private LinkedBlockingQueue<OutputCommand> queue;
|
||||||
|
private volatile boolean shutDownHasBeenCalled;
|
||||||
|
|
||||||
public SystemConsoleOutputDevice () {
|
public SystemConsoleOutputDevice () {
|
||||||
logger = LoggerFactory.getLogger(SystemConsoleOutputDevice.class);
|
logger = LoggerFactory.getLogger(SystemConsoleOutputDevice.class);
|
||||||
logger.info("A SystemConsoleOutputDevice is constructed");
|
logger.info("A SystemConsoleOutputDevice is constructed");
|
||||||
|
queue = new LinkedBlockingQueue<>();
|
||||||
|
shutDownHasBeenCalled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the UTF8 decoding of byte-string data
|
* Returns the UTF8 decoding of byte-string data
|
||||||
*/
|
*/
|
||||||
|
@ -27,13 +36,69 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice {
|
||||||
return data.toStringUtf8();
|
return data.toStringUtf8();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run () {
|
||||||
|
logger.info("UI starts running");
|
||||||
|
while (! wasShutDownCalled()) {
|
||||||
|
try {
|
||||||
|
OutputCommand command = queue.take();
|
||||||
|
handleSingleCommand(command);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {
|
||||||
|
logger.warn ("Interrupted while reading from command queue " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean wasShutDownCalled () {
|
||||||
|
return shutDownHasBeenCalled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void callShutDown() {
|
||||||
|
logger.info("callShutDown command has been called");
|
||||||
|
shutDownHasBeenCalled = true;
|
||||||
|
queue.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void handleSingleCommand(OutputCommand command) {
|
||||||
|
if (command instanceof CommitOutputCommand) {
|
||||||
|
doCommitToBallot((CommitOutputCommand)command);
|
||||||
|
}
|
||||||
|
else if (command instanceof AuditOutputCommand) {
|
||||||
|
doAudit((AuditOutputCommand)command);
|
||||||
|
}
|
||||||
|
else if (command instanceof CastOutputCommand) {
|
||||||
|
doCastBallot((CastOutputCommand)command);
|
||||||
|
}
|
||||||
|
else if (command instanceof CancelOutputCommand) {
|
||||||
|
doCancel((CancelOutputCommand)command);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String errorMessage = "handleSingleCommand: unknown type of OutputCommand received: " +
|
||||||
|
command.getClass().getName();
|
||||||
|
logger.error(errorMessage);
|
||||||
|
throw new RuntimeException(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void commitToBallot(PlaintextBallot plaintextBallot,
|
public void commitToBallot(PlaintextBallot plaintextBallot,
|
||||||
SignedEncryptedBallot signedEncryptedBallot,
|
SignedEncryptedBallot signedEncryptedBallot,
|
||||||
FutureCallback<Void> callback) {
|
FutureCallback<Void> callback) {
|
||||||
logger.debug("entered method commitToBallot");
|
logger.debug("Output interface call to commit to ballot");
|
||||||
|
queue.add(new CommitOutputCommand(plaintextBallot, signedEncryptedBallot, (ControllerCallback)callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doCommitToBallot(CommitOutputCommand command) {
|
||||||
|
logger.debug("entered method doCommitToBallot");
|
||||||
|
PlaintextBallot plaintextBallot = command.getPlaintext();
|
||||||
long plaintextSerialNumber = plaintextBallot.getSerialNumber();
|
long plaintextSerialNumber = plaintextBallot.getSerialNumber();
|
||||||
System.out.println("Commitment of Ballot #" + plaintextSerialNumber + " (plaintext):");
|
System.out.println("Commitment of Ballot #" + plaintextSerialNumber + " (plaintext):");
|
||||||
|
System.out.println(plaintextBallot);
|
||||||
|
SignedEncryptedBallot signedEncryptedBallot = command.getSignedEncryptedBallot();
|
||||||
long encryptedSerialNumber = signedEncryptedBallot.getEncryptedBallot().getSerialNumber();
|
long encryptedSerialNumber = signedEncryptedBallot.getEncryptedBallot().getSerialNumber();
|
||||||
System.out.println("Commitment of Ballot #" + encryptedSerialNumber + " (ciphertext):");
|
System.out.println("Commitment of Ballot #" + encryptedSerialNumber + " (ciphertext):");
|
||||||
if (plaintextSerialNumber != encryptedSerialNumber) {
|
if (plaintextSerialNumber != encryptedSerialNumber) {
|
||||||
|
@ -42,33 +107,52 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice {
|
||||||
}
|
}
|
||||||
ByteString encryptedData = signedEncryptedBallot.getEncryptedBallot().getData().getData();
|
ByteString encryptedData = signedEncryptedBallot.getEncryptedBallot().getData().getData();
|
||||||
System.out.println(bytesToString(encryptedData));
|
System.out.println(bytesToString(encryptedData));
|
||||||
callback.onSuccess(null);
|
command.getCallback().onSuccess(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void audit(BallotSecrets ballotSecrets, FutureCallback<Void> callback) {
|
public void audit(BallotSecrets ballotSecrets, FutureCallback<Void> callback) {
|
||||||
logger.debug("entered method audit");
|
logger.debug("an interface call to audit");
|
||||||
|
queue.add(new AuditOutputCommand(ballotSecrets, (ControllerCallback)callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doAudit(AuditOutputCommand command) {
|
||||||
|
logger.debug("entered method doAudit");
|
||||||
System.out.println("Auditing");
|
System.out.println("Auditing");
|
||||||
printPlaintextBallot (ballotSecrets.getPlaintextBallot());
|
BallotSecrets ballotSecrets = command.getBallotSecrets();
|
||||||
printEncryptionRandomness (ballotSecrets.getEncryptionRandomness());
|
printEncryptionRandomness (ballotSecrets.getEncryptionRandomness());
|
||||||
printRandomnessGenerationProof (ballotSecrets.getProof());
|
printRandomnessGenerationProof (ballotSecrets.getProof());
|
||||||
callback.onSuccess(null);
|
command.getCallback().onSuccess(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printPlaintextBallot (PlaintextBallot plaintextBallot) {
|
|
||||||
long plaintextSerialNumber = plaintextBallot.getSerialNumber();
|
|
||||||
System.out.println("Plaintext serial number = " + plaintextSerialNumber);
|
|
||||||
|
|
||||||
System.out.println("Answers = ");
|
@Override
|
||||||
for (BallotAnswer ballotAnswer : plaintextBallot.getAnswersList()) {
|
public void castBallot(FutureCallback<Void> callback) {
|
||||||
String printableAnswer = "";
|
logger.debug("an interface call to cast ballot");
|
||||||
for (long n : ballotAnswer.getAnswerList()) {
|
queue.add(new CastOutputCommand((ControllerCallback)callback));
|
||||||
printableAnswer += n + " ";
|
|
||||||
}
|
}
|
||||||
System.out.println(printableAnswer);
|
|
||||||
|
public void doCastBallot(CastOutputCommand command) {
|
||||||
|
logger.debug("entered method doCastBallot");
|
||||||
|
System.out.println("Ballot finalized for casting!");
|
||||||
|
command.getCallback().onSuccess(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelBallot(FutureCallback<Void> callback) {
|
||||||
|
logger.debug("an interface call to cancel the output");
|
||||||
|
queue.add(new CancelOutputCommand((ControllerCallback)callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void doCancel(CancelOutputCommand command) {
|
||||||
|
logger.debug("entered method doCancel");
|
||||||
|
System.out.println("Ballot cancelled!");
|
||||||
|
command.getCallback().onSuccess(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void printEncryptionRandomness (EncryptionRandomness encryptionRandomness) {
|
private void printEncryptionRandomness (EncryptionRandomness encryptionRandomness) {
|
||||||
System.out.println("Encryption Randomness = ");
|
System.out.println("Encryption Randomness = ");
|
||||||
ByteString data = encryptionRandomness.getData();
|
ByteString data = encryptionRandomness.getData();
|
||||||
|
@ -81,18 +165,4 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice {
|
||||||
System.out.println(bytesToString(data));
|
System.out.println(bytesToString(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void castBallot(FutureCallback<Void> callback) {
|
|
||||||
logger.debug("entered method castBallot");
|
|
||||||
System.out.println("Ballot finalized for casting!");
|
|
||||||
callback.onSuccess(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelBallot(FutureCallback<Void> callback) {
|
|
||||||
logger.debug("entered method cancelBallot");
|
|
||||||
System.out.println("Ballot cancelled!");
|
|
||||||
callback.onSuccess(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package meerkat.voting.output.outputcommands;
|
||||||
|
|
||||||
|
import meerkat.protobuf.Voting.*;
|
||||||
|
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 15/06/16.
|
||||||
|
*/
|
||||||
|
public class AuditOutputCommand extends OutputCommand {
|
||||||
|
|
||||||
|
private final BallotSecrets ballotSecrets;
|
||||||
|
|
||||||
|
public AuditOutputCommand(BallotSecrets ballotSecrets, ControllerCallback callback) {
|
||||||
|
super(callback);
|
||||||
|
this.ballotSecrets = ballotSecrets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BallotSecrets getBallotSecrets() {
|
||||||
|
return ballotSecrets;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package meerkat.voting.output.outputcommands;
|
||||||
|
|
||||||
|
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 15/06/16.
|
||||||
|
*/
|
||||||
|
public class CancelOutputCommand extends OutputCommand {
|
||||||
|
|
||||||
|
public CancelOutputCommand(ControllerCallback callback) {
|
||||||
|
super(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package meerkat.voting.output.outputcommands;
|
||||||
|
|
||||||
|
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 15/06/16.
|
||||||
|
*/
|
||||||
|
public class CastOutputCommand extends OutputCommand {
|
||||||
|
|
||||||
|
public CastOutputCommand(ControllerCallback callback) {
|
||||||
|
super(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package meerkat.voting.output.outputcommands;
|
||||||
|
|
||||||
|
import meerkat.protobuf.Voting.*;
|
||||||
|
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hai on 15/06/16.
|
||||||
|
*/
|
||||||
|
public class CommitOutputCommand extends OutputCommand {
|
||||||
|
|
||||||
|
private final PlaintextBallot plaintextBallot;
|
||||||
|
private final SignedEncryptedBallot signedEncryptedBallot;
|
||||||
|
|
||||||
|
public CommitOutputCommand(PlaintextBallot plaintextBallot,
|
||||||
|
SignedEncryptedBallot signedEncryptedBallot,
|
||||||
|
ControllerCallback callback) {
|
||||||
|
super(callback);
|
||||||
|
this.plaintextBallot = plaintextBallot;
|
||||||
|
this.signedEncryptedBallot = signedEncryptedBallot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlaintextBallot getPlaintext() {
|
||||||
|
return plaintextBallot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignedEncryptedBallot getSignedEncryptedBallot() {
|
||||||
|
return signedEncryptedBallot;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package meerkat.voting.output.outputcommands;
|
||||||
|
|
||||||
|
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||||
|
|
||||||
|
//TODO: make this class generic
|
||||||
|
public abstract class OutputCommand {
|
||||||
|
protected final ControllerCallback callback;
|
||||||
|
|
||||||
|
protected OutputCommand(ControllerCallback callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ControllerCallback getCallback () {
|
||||||
|
return this.callback;
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run () {
|
public void run () {
|
||||||
logger.info("entered the voting flow");
|
logger.info("UI starts running");
|
||||||
while (! wasShutDownCalled()) {
|
while (! wasShutDownCalled()) {
|
||||||
try {
|
try {
|
||||||
UICommand command = queue.take();
|
UICommand command = queue.take();
|
||||||
|
|
Loading…
Reference in New Issue