Just a small test for my git-gui.
Files pushed to 'vbdev' branch. The files cannot run yet. They still need quite a lot of work.vbdev
parent
cbe3b5c765
commit
6e64c57431
|
@ -0,0 +1,52 @@
|
|||
package meerkat.voting;
|
||||
|
||||
import meerkat.protobuf.Voting.EncryptedBallot;
|
||||
import meerkat.protobuf.Voting.PlaintextBallot;
|
||||
|
||||
public class VBMessage {
|
||||
|
||||
public enum VBMessageType
|
||||
{
|
||||
VB_TICK,
|
||||
VB_CONTROLLER_RESPONSE,
|
||||
VB_ENCRYPTION_QUERY
|
||||
}
|
||||
|
||||
private VBMessageType m_type;
|
||||
private EncryptedBallot m_encryptedBallot;
|
||||
private PlaintextBallot m_plaintextBallot;
|
||||
|
||||
public static VBMessage newTick () {
|
||||
VBMessage retVal = new VBMessage();
|
||||
retVal.m_type = VBMessageType.VB_TICK;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static VBMessage newEncryptionQuery (PlaintextBallot plaintextBallot) {
|
||||
VBMessage retVal = new VBMessage();
|
||||
retVal.m_type = VBMessageType.VB_ENCRYPTION_QUERY;
|
||||
retVal.m_plaintextBallot = plaintextBallot;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static VBMessage newControllerResponse (EncryptedBallot encryptedBallot) {
|
||||
VBMessage retVal = new VBMessage();
|
||||
retVal.m_type = VBMessageType.VB_CONTROLLER_RESPONSE;
|
||||
retVal.m_encryptedBallot = encryptedBallot;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public EncryptedBallot getEncryptedBallot () {
|
||||
assert m_type == VBMessageType.VB_CONTROLLER_RESPONSE;
|
||||
return m_encryptedBallot;
|
||||
}
|
||||
|
||||
public PlaintextBallot getPlaintextBallot () {
|
||||
assert m_type == VBMessageType.VB_ENCRYPTION_QUERY;
|
||||
return m_plaintextBallot;
|
||||
}
|
||||
|
||||
public boolean isEmptyMessage () {
|
||||
return (m_type == VBMessageType.VB_TICK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package meerkat.voting;
|
||||
|
||||
import meerkat.protobuf.Voting.BallotAnswer;
|
||||
import meerkat.protobuf.Voting.BallotAnswerTranslationTable;
|
||||
import meerkat.protobuf.Voting.BallotQuestion;
|
||||
import meerkat.protobuf.Voting.BallotSecrets;
|
||||
import meerkat.protobuf.Voting.BoothParams;
|
||||
import meerkat.protobuf.Voting.ElectionParams;
|
||||
import meerkat.protobuf.Voting.PlaintextBallot;
|
||||
import meerkat.protobuf.Crypto.EncryptionPublicKey;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
public class VotingBoothToy implements VotingBooth, Runnable {
|
||||
|
||||
//private ElectionParams m_electionParams;
|
||||
private EncryptionPublicKey m_ballotEncryptionKey;
|
||||
private List<BallotQuestion> l_questions;
|
||||
private BallotQuestion a_questions[];
|
||||
private BallotAnswer a_answers[];
|
||||
private BallotAnswerTranslationTable m_answerTranslationTable;
|
||||
|
||||
private BoothParams m_boothParams;
|
||||
private VotingBooth.UI m_ui;
|
||||
|
||||
|
||||
public VotingBoothToy () {
|
||||
}
|
||||
|
||||
public void registerUI (UI ui) {
|
||||
m_ui = ui;
|
||||
}
|
||||
|
||||
public void run () {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth#init(meerkat.protobuf.Voting.ElectionParams, meerkat.protobuf.Voting.BoothParams)
|
||||
*/
|
||||
@Override
|
||||
public void init(ElectionParams globalParams, BoothParams boothParams) {
|
||||
System.err.println ("debug VB: init.");
|
||||
//this.m_electionParams = globalParams;
|
||||
this.m_ballotEncryptionKey = globalParams.getBallotEncryptionKey();
|
||||
this.l_questions = globalParams.getQuestionsList();
|
||||
|
||||
this.m_answerTranslationTable = globalParams.getAnswerTranslationTable();
|
||||
|
||||
this.m_boothParams = boothParams;
|
||||
|
||||
}
|
||||
|
||||
public void registerVBUI (VotingBooth.UI ui)
|
||||
{
|
||||
m_ui = ui;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth#submitBallot(meerkat.protobuf.Voting.PlaintextBallot)
|
||||
*/
|
||||
@Override
|
||||
public void submitBallot(PlaintextBallot ballot) {
|
||||
System.err.println ("debug VB: submit ballot.");
|
||||
// encryptBallot (PlaintextBallot)
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth#cancelBallot()
|
||||
*/
|
||||
@Override
|
||||
public void cancelBallot() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth#voterCastOrAudit(boolean)
|
||||
*/
|
||||
@Override
|
||||
public void voterCastOrAudit(boolean castVote) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
//A ballot question. This is an opaque
|
||||
//data type that is parsed by the UI to display
|
||||
//the question.
|
||||
message BallotQuestion {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
//An answer to a specific ballot question.
|
||||
//The answer is a vector of signed integers,
|
||||
//to encompass voting schemes such as ranked voting
|
||||
//and STV.
|
||||
message BallotAnswer {
|
||||
repeated sint64 answer = 1 [packed=true];
|
||||
}
|
||||
|
||||
message PlaintextBallot {
|
||||
uint64 serialNumber = 1; // Ballot serial number
|
||||
|
||||
repeated BallotAnswer answers = 2;
|
||||
}
|
||||
|
||||
message BallotSecrets {
|
||||
PlaintextBallot plaintext_ballot = 1;
|
||||
|
||||
EncryptionRandomness encryption_randomness = 2;
|
||||
RandomnessGenerationProof proof = 3;
|
||||
}
|
||||
|
||||
message BoothParams {
|
||||
repeated SignatureVerificationKey pscVerificationKeys = 1;
|
||||
|
||||
}
|
||||
|
||||
//A table to translate to and from compactly encoded answers
|
||||
//and their human-understandable counterparts.
|
||||
//This should be parsable by the UI
|
||||
message BallotAnswerTranslationTable {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
message ElectionParams {
|
||||
// TODO: different sets of keys for different roles?
|
||||
//repeated SignatureVerificationKey trusteeVerificationKeys = 1;
|
||||
|
||||
// How many trustees must participate in a signature for it to be considered valid.
|
||||
//uint32 trusteeSignatureThreshold = 2;
|
||||
|
||||
// The key used to encrypt ballots. The corresponding private key
|
||||
// is shared between the trustees.
|
||||
EncryptionPublicKey ballotEncryptionKey = 3;
|
||||
|
||||
// Verification keys for valid mixers.
|
||||
//repeated SignatureVerificationKey mixerVerificationKeys = 4;
|
||||
|
||||
// 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;
|
||||
|
||||
// Translation table between answers and plaintext encoding
|
||||
BallotAnswerTranslationTable answerTranslationTable = 7;
|
||||
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,305 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
package meerkat.voting;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import meerkat.protobuf.Voting.*;
|
||||
import meerkat.voting.VotingBooth.UI;
|
||||
|
||||
/**
|
||||
* @author hai
|
||||
*
|
||||
*/
|
||||
public class VotingBoothToyConsoleUI implements UI, Runnable {
|
||||
|
||||
private BufferedReader m_in;
|
||||
private VotingBooth m_vbController;
|
||||
//private SharedPlaintextBallotMessage m_sharedPlaintext;
|
||||
//private SharedEncryptedBallotMessage m_sharedEncrypted;
|
||||
private ArrayBlockingQueue<VBMessage> a_queue;
|
||||
static private int m_queueSize = 5;
|
||||
private BallotQuestion a_questions[];
|
||||
private int m_serialNumber;
|
||||
private PlaintextBallot m_plaintextBallot;
|
||||
private EncryptedBallot m_encryptedBallot;
|
||||
private int m_waitForControllerMillisecTimeout = 10;
|
||||
|
||||
|
||||
public VotingBoothToyConsoleUI () {
|
||||
a_queue = new ArrayBlockingQueue<VBMessage> (m_queueSize, true);
|
||||
}
|
||||
|
||||
public VotingBoothToyConsoleUI(ElectionParams globalParams) {
|
||||
m_serialNumber = 0;
|
||||
List<BallotQuestion> l_questions = globalParams.getQuestionsList();
|
||||
a_questions = new BallotQuestion[l_questions.size()];
|
||||
m_in = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
int i = 0;
|
||||
for (BallotQuestion q: l_questions) {
|
||||
a_questions[i] = q;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth.UI#votingBegin()
|
||||
*/
|
||||
@Override
|
||||
public void votingBegin() {
|
||||
System.err.println ("UI debug: preparing console UI for a new user.");
|
||||
System.out.println ("UI screen: Welcome. Press to start");
|
||||
readInputLine();
|
||||
|
||||
++ m_serialNumber;
|
||||
boolean votingOccured = listQuestionsToUserAndGetAnswers ();
|
||||
|
||||
if (! votingOccured)
|
||||
{
|
||||
// cancel vote;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
sendBallotToControllerForEncryptionAndWaitForResponse ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth.UI#commitToEncryptedBallot(meerkat.voting.EncryptedBallot)
|
||||
*/
|
||||
@Override
|
||||
public void commitToEncryptedBallot(EncryptedBallot encryptedBallot) {
|
||||
try {
|
||||
a_queue.put (VBMessage.newControllerResponse(encryptedBallot));
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
System.err.println ("Interrupted in VotingBoothToyConsoleUI.commitToEncryptedBallot");
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth.UI#castVote()
|
||||
*/
|
||||
@Override
|
||||
public void castVote() {
|
||||
System.err.println ("UI debug: voter decided to cast vote.");
|
||||
System.out.println ("UI printer: print empty space until end of page");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see meerkat.voting.VotingBooth.UI#auditVote(meerkat.protobuf.Voting.BallotSecrets)
|
||||
*/
|
||||
@Override
|
||||
public void auditVote(BallotSecrets ballotSecrets) {
|
||||
// audit = calcAudit (ballotSecrets)
|
||||
// sendToPrinter (audit)
|
||||
System.err.println ("UI debug: voter decided to audit vote.");
|
||||
System.out.println ("UI printer: here we should print audit of ballot");
|
||||
|
||||
}
|
||||
|
||||
public void run () {
|
||||
System.out.println("UI screen: Initializing the magic");
|
||||
|
||||
System.out.println("UI screen: press something to start the system");
|
||||
readInputLine();
|
||||
|
||||
while (true) {
|
||||
votingBegin();
|
||||
|
||||
if (m_encryptedBallot != null) {
|
||||
|
||||
printBallot();
|
||||
|
||||
castOrAudit ();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void castOrAudit () {
|
||||
|
||||
// fix the flow here!!
|
||||
// keeping the same vote should return for a new encryption
|
||||
|
||||
System.out.println("UI screen: printing ended. Do you want to (c)ast the ballot or (a)udit?");
|
||||
|
||||
boolean keepThisVote = true;
|
||||
String s = readInputLine();
|
||||
if (s.equals("c") || s.equals("cancel") || s.equals("cast")) {
|
||||
castVote();
|
||||
keepThisVote = false;
|
||||
}
|
||||
else if (s.equals("a") || s.equals("audit")) {
|
||||
auditVote();
|
||||
System.out.println("Do you still want to keep this vote? Type 'y' for casting/auditing the same vote. Type 'n' tp start from scratch");
|
||||
if (s.equals("y") || s.equals("yes")) {
|
||||
//
|
||||
}
|
||||
else if (s.equals("n") || s.equals("no")) {
|
||||
keepThisVote = false;
|
||||
}
|
||||
else {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerVBController (VotingBooth vb)
|
||||
{
|
||||
m_vbController = vb;
|
||||
//m_sharedPlaintext = sharedPlaintext;
|
||||
//m_sharedEncrypted = sharedEncrypted;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns true if voting finished successfully
|
||||
* false if cancelled in the middle
|
||||
*/
|
||||
private boolean listQuestionsToUserAndGetAnswers()
|
||||
{
|
||||
PlaintextBallot.Builder ptbb = PlaintextBallot.newBuilder();
|
||||
|
||||
ptbb.setSerialNumber(m_serialNumber);
|
||||
|
||||
int index = 0;
|
||||
while (index < a_questions.length) {
|
||||
BallotQuestion q = a_questions[index];
|
||||
printQuestion(index, q);
|
||||
System.out.println("UI screen: Enter your answer. You can also type 'back' or 'cancel'");
|
||||
String s = readInputLine();
|
||||
|
||||
if (s.equals("cancel") || (index == 0 && s.equals("back"))) {
|
||||
m_plaintextBallot = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s.equals("back")) {
|
||||
--index;
|
||||
continue;
|
||||
}
|
||||
|
||||
BallotAnswer answer = translateStringAnswerToProtoBufMessageAnswer (s);
|
||||
ptbb.setAnswers(index, answer);
|
||||
}
|
||||
|
||||
m_plaintextBallot = ptbb.build();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private String readInputLine () {
|
||||
String s;
|
||||
try {
|
||||
s = this.m_in.readLine();
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println("UI debug: VotingBegin(): some error with reading input. " + e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String getHexData (ByteString data) {
|
||||
String s = "";
|
||||
for (Byte b : data) {
|
||||
s += "0123456789ABCDEF".charAt((int)b / 16);
|
||||
s += "0123456789ABCDEF".charAt((int)b % 16);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private void printHexData (ByteString data) {
|
||||
String s = getHexData(data);
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
private void printQuestion (int i, BallotQuestion q) {
|
||||
System.out.println("UI screen: question number " + i);
|
||||
System.out.println(q.getData());
|
||||
printHexData (q.getData());
|
||||
}
|
||||
|
||||
private BallotAnswer translateStringAnswerToProtoBufMessageAnswer (String s) {
|
||||
BallotAnswer.Builder bab = BallotAnswer.newBuilder();
|
||||
StringTokenizer st = new StringTokenizer(s);
|
||||
int index = 0;
|
||||
while (st.hasMoreTokens()) {
|
||||
++index;
|
||||
bab.setAnswer(index, Integer.parseInt(st.nextToken()));
|
||||
}
|
||||
|
||||
BallotAnswer ba = bab.build();
|
||||
return ba;
|
||||
}
|
||||
|
||||
public void tick () {
|
||||
// adds a 'tick'. If queue is full, do nothing
|
||||
a_queue.add (VBMessage.newTick());
|
||||
}
|
||||
|
||||
private void sendBallotToControllerForEncryptionAndWaitForResponse () {
|
||||
|
||||
class TickerTask extends TimerTask {
|
||||
private VotingBoothToyConsoleUI m_ui;
|
||||
public TickerTask (VotingBoothToyConsoleUI ui) {
|
||||
m_ui = ui;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
m_ui.tick();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("UI screen: Please wait for encryption");
|
||||
m_vbController.submitBallot(m_plaintextBallot);
|
||||
m_encryptedBallot = null;
|
||||
Timer timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TickerTask(this), new Date(), m_waitForControllerMillisecTimeout);
|
||||
|
||||
while (m_encryptedBallot == null)
|
||||
{
|
||||
VBMessage msg = null;
|
||||
try {
|
||||
msg = a_queue.take();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
System.err.println("VotingBoothToyConsoleUI.sendBallotToControllerForEncryptionAndWaitForResponse interrupted!");
|
||||
return;
|
||||
}
|
||||
if (msg.isEmptyMessage()) {
|
||||
System.out.print(".");
|
||||
}
|
||||
else {
|
||||
m_encryptedBallot = msg.getEncryptedBallot();
|
||||
if (m_encryptedBallot.getSerialNumber() != m_plaintextBallot.getSerialNumber())
|
||||
{
|
||||
m_encryptedBallot = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\nUI debug: Received EncryptedBallot");
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue