integrated to AsyncBBClient
parent
be6449f27d
commit
75c411a5e7
|
@ -1,4 +1,4 @@
|
|||
#Thu Dec 17 12:20:25 IST 2015
|
||||
#Sun Dec 27 09:28:01 IST 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
@ -10,6 +10,9 @@ message BoolMsg {
|
|||
bool value = 1;
|
||||
}
|
||||
|
||||
message IntMsg {
|
||||
int32 value = 1;
|
||||
}
|
||||
|
||||
message MessageID {
|
||||
// The ID of a message for unique retrieval.
|
||||
|
@ -26,10 +29,10 @@ message UnsignedBulletinBoardMessage {
|
|||
}
|
||||
|
||||
message BulletinBoardMessage {
|
||||
|
||||
|
||||
// Serial entry number of message in database
|
||||
int64 entryNum = 1;
|
||||
|
||||
|
||||
// Unsigned raw data of message
|
||||
UnsignedBulletinBoardMessage msg = 2;
|
||||
|
||||
|
@ -38,9 +41,9 @@ message BulletinBoardMessage {
|
|||
}
|
||||
|
||||
message BulletinBoardMessageList {
|
||||
|
||||
|
||||
repeated BulletinBoardMessage message = 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
enum FilterType {
|
||||
|
@ -49,13 +52,17 @@ enum FilterType {
|
|||
MAX_ENTRY = 2; // Find all entries in database up to specified entry number (chronological)
|
||||
SIGNER_ID = 3; // Find all entries in database that correspond to specific signature (signer)
|
||||
TAG = 4; // Find all entries in database that have a specific tag
|
||||
|
||||
// NOTE: The MAX_MESSAGES filter must remain the last filter type
|
||||
// This is because the condition it specifies in an SQL statement must come last in the statement
|
||||
// Keeping it last here allows for easily sorting the filters and keeping the code general
|
||||
MAX_MESSAGES = 5; // Return at most some specified number of messages
|
||||
}
|
||||
|
||||
message MessageFilter {
|
||||
|
||||
|
||||
FilterType type = 1;
|
||||
|
||||
|
||||
oneof filter{
|
||||
bytes id = 2;
|
||||
int64 entry = 3;
|
||||
|
@ -65,9 +72,36 @@ message MessageFilter {
|
|||
}
|
||||
|
||||
message MessageFilterList {
|
||||
|
||||
|
||||
// Combination of filters.
|
||||
// To be implemented using intersection ("AND") operations.
|
||||
repeated MessageFilter filter = 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// This message is used to start a batch transfer to the Bulletin Board Server
|
||||
message BeginBatchMessage {
|
||||
bytes signerId = 1; // Unique signer identifier
|
||||
int32 batchId = 2; // Unique identifier for the batch (unique per signer)
|
||||
repeated string tag = 3; // Tags for the batch message
|
||||
}
|
||||
|
||||
// This message is used to finalize and sign a batch transfer to the Bulletin Board Server
|
||||
message CloseBatchMessage {
|
||||
int32 batchId = 1; // Unique identifier for the batch (unique per signer)
|
||||
int32 batchLength = 2; // Number of messages in the batch
|
||||
meerkat.Signature sig = 3; // Signature on the (ordered) batch messages
|
||||
}
|
||||
|
||||
// Container for single batch message data
|
||||
message BatchData {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
// These messages comprise a batch message
|
||||
message BatchMessage {
|
||||
bytes signerId = 1; // Unique signer identifier
|
||||
int32 batchId = 2; // Unique identifier for the batch (unique per signer)
|
||||
int32 serialNum = 3; // Location of the message in the batch: starting from 0
|
||||
BatchData data = 4; // Actual data
|
||||
}
|
|
@ -52,6 +52,16 @@ message BallotAnswerTranslationTable {
|
|||
bytes data = 1;
|
||||
}
|
||||
|
||||
// Data required in order to access the Bulletin Board Servers
|
||||
message BulletinBoardClientParams {
|
||||
|
||||
// Addresses of all Bulletin Board Servers
|
||||
repeated string bulletinBoardAddress = 1;
|
||||
|
||||
// Threshold fraction of successful servers posts before a post task is considered complete
|
||||
float minRedundancy = 2;
|
||||
}
|
||||
|
||||
message ElectionParams {
|
||||
// TODO: different sets of keys for different roles?
|
||||
repeated SignatureVerificationKey trusteeVerificationKeys = 1;
|
||||
|
@ -75,4 +85,6 @@ message ElectionParams {
|
|||
// Translation table between answers and plaintext encoding
|
||||
BallotAnswerTranslationTable answerTranslationTable = 7;
|
||||
|
||||
// Data required in order to access the Bulletin Board Servers
|
||||
BulletinBoardClientParams bulletinBoardClientParams = 8;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
package main;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||
import meerkat.crypto.mixnet.Mixer;
|
||||
import meerkat.protobuf.BulletinBoardAPI;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import meerkat.protobuf.Mixing;
|
||||
import necessary.AsyncBulletinBoardClient;
|
||||
import necessary.BulletinBoardClient;
|
||||
import necessary.SignedBatch;
|
||||
import qilin.util.Pair;
|
||||
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -15,119 +24,247 @@ import java.util.List;
|
|||
*/
|
||||
public class MainMixing {
|
||||
|
||||
Mixer mixer;
|
||||
Mix2ZeroKnowledgeVerifier verifier;
|
||||
int n,layers;
|
||||
private Mixer mixer;
|
||||
private Mix2ZeroKnowledgeVerifier verifier;
|
||||
private int n, layers;
|
||||
private AsyncBulletinBoardClient asyncBulletinBoardClient;
|
||||
private final byte[] id;
|
||||
private final int mixerOrder;
|
||||
|
||||
public MainMixing(Mixer mixer, Mix2ZeroKnowledgeVerifier verifier, int n) {
|
||||
|
||||
public MainMixing(Mixer mixer, int mixerOrder, Mix2ZeroKnowledgeVerifier verifier, int n
|
||||
, AsyncBulletinBoardClient asyncBulletinBoardClient, byte[] id) {
|
||||
this.mixer = mixer;
|
||||
this.mixerOrder = mixerOrder;
|
||||
this.verifier = verifier;
|
||||
this.n = n;
|
||||
this.layers = (int) (2 * Math.log(n) / Math.log(2)) - 1; // layers = 2logn -1
|
||||
this.asyncBulletinBoardClient = asyncBulletinBoardClient;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private void firstMixing( ) throws Exception
|
||||
{
|
||||
updateBB(mixer.mix(getInputForFirstMixer()));
|
||||
}
|
||||
public void main(List<Integer> prevBatchIds, int batchId, BulletinBoardClient.ClientCallback<?> callback) throws Exception {
|
||||
|
||||
private void otherMixing() throws Exception
|
||||
{
|
||||
List<Mixing.ZeroKnowledgeProof[][]> zeroKnowledgeProofsLists = downloadProofs();
|
||||
List<Crypto.RerandomizableEncryptedMessage[][]> rerandomizableEncryptedMessageLists = downloadEncryptionTable();
|
||||
|
||||
for (int i = 0; i < zeroKnowledgeProofsLists.size(); i++)
|
||||
{
|
||||
if(!verifyTable(n,layers,zeroKnowledgeProofsLists.get(i),rerandomizableEncryptedMessageLists.get(i)))
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
Crypto.RerandomizableEncryptedMessage[] lastLayerInCurrent,firstLineInNext;
|
||||
for (int i = 0; i < rerandomizableEncryptedMessageLists.size() - 1 ; i++)
|
||||
{
|
||||
lastLayerInCurrent = rerandomizableEncryptedMessageLists.get(i)[layers - 1];
|
||||
firstLineInNext = rerandomizableEncryptedMessageLists.get(i + 1)[0];
|
||||
if(!Arrays.equals(lastLayerInCurrent,firstLineInNext))
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
List<Crypto.RerandomizableEncryptedMessage> inputForMixer =
|
||||
Arrays.asList(rerandomizableEncryptedMessageLists
|
||||
.get(rerandomizableEncryptedMessageLists.size() - 1)[layers - 1]);
|
||||
|
||||
updateBB(mixer.mix(inputForMixer));
|
||||
}
|
||||
|
||||
private List<Mixing.ZeroKnowledgeProof[][]> downloadProofs()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Crypto.RerandomizableEncryptedMessage[][]> downloadEncryptionTable()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Crypto.RerandomizableEncryptedMessage> getInputForFirstMixer()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateBB(Pair<Mixing.ZeroKnowledgeProof[][],Crypto.RerandomizableEncryptedMessage[][]> mixerOutput){
|
||||
|
||||
}
|
||||
|
||||
private boolean verifyTable(int n,int layers, Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs,
|
||||
Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages)
|
||||
{
|
||||
int index1,index2,layer;
|
||||
|
||||
//initialize locationChecksum table
|
||||
// use for check BeneshNet validity
|
||||
boolean[][] locationChecksum = new boolean[layers][n];
|
||||
for (boolean[] locationChecksumLayer: locationChecksum) {
|
||||
Arrays.fill(locationChecksumLayer,false);
|
||||
}
|
||||
List<Crypto.RerandomizableEncryptedMessage> mixerInput;
|
||||
|
||||
|
||||
for (Mixing.ZeroKnowledgeProof[] zkpLayer: zeroKnowledgeProofs) {
|
||||
for (Mixing.ZeroKnowledgeProof zkp: zkpLayer) {
|
||||
Mixing.ZeroKnowledgeProof.Location location = zkp.getLocation();
|
||||
index1 = location.getI();
|
||||
index2 = location.getJ();
|
||||
layer = location.getLayer();
|
||||
if (mixerOrder > 0) {
|
||||
List<BatchHandler> batchHandlers = new ArrayList<BatchHandler>(prevBatchIds.size());
|
||||
BatchHandler currentBatchHandler;
|
||||
for (Integer prevBatchId : prevBatchIds) {
|
||||
currentBatchHandler = new BatchHandler(n, layers);
|
||||
asyncBulletinBoardClient.readBatch(id, prevBatchId, currentBatchHandler);
|
||||
batchHandlers.add(currentBatchHandler);
|
||||
}
|
||||
|
||||
// check location validity
|
||||
if (layer > layers >> 1) {
|
||||
if (index2 - index1 != n >> (layers - layer))
|
||||
return false;
|
||||
boolean allDone = false;
|
||||
while (!allDone) {
|
||||
try {
|
||||
Thread.sleep(30);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
else{
|
||||
if (index2 - index1 != n >> (layer + 1))
|
||||
return false;
|
||||
// check all handlers done
|
||||
allDone = true;
|
||||
for (BatchHandler batchHandler : batchHandlers) {
|
||||
allDone &= batchHandler.done;
|
||||
}
|
||||
|
||||
// mark location in table
|
||||
locationChecksum[layer][index1] = true;
|
||||
locationChecksum[layer][index2] = true;
|
||||
|
||||
// verify proof
|
||||
if(!verifier.verify(rerandomizableEncryptedMessages[index1][layer],
|
||||
rerandomizableEncryptedMessages[index2][layer],
|
||||
rerandomizableEncryptedMessages[index1][layer + 1],
|
||||
rerandomizableEncryptedMessages[index2][layer + 1],
|
||||
zkp))
|
||||
return false;
|
||||
}
|
||||
|
||||
// assert all handlers succeeded
|
||||
for (BatchHandler batchHandler : batchHandlers) {
|
||||
if(batchHandler.e != null)
|
||||
throw batchHandler.e;
|
||||
}
|
||||
|
||||
BatchHandler lastBatchHandler = batchHandlers.get(batchHandlers.size() - 1);
|
||||
mixerInput = lastBatchHandler.getInputForMixer();
|
||||
|
||||
} else {
|
||||
// ToDo : handle first mixer case
|
||||
mixerInput = null;
|
||||
}
|
||||
|
||||
Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]> mixerOutput
|
||||
= mixer.mix(mixerInput);
|
||||
updateBB(mixerOutput, batchId, callback);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void updateBB(Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]> mixerOutput
|
||||
, int batchId, BulletinBoardClient.ClientCallback<?> callback) {
|
||||
|
||||
BatchConverter batchConverter = new BatchConverter();
|
||||
List<BulletinBoardAPI.BatchData> batchDataList = batchConverter.mixerOutput2BatchData(mixerOutput);
|
||||
asyncBulletinBoardClient.postBatch(id, batchId, batchDataList, callback);
|
||||
}
|
||||
|
||||
private class BatchConverter {
|
||||
|
||||
ByteString IntegerToByteString(int a){
|
||||
return ByteString.copyFrom(BigInteger.valueOf(a).toByteArray());
|
||||
}
|
||||
|
||||
int ByteString2Integer(ByteString bs) {
|
||||
return Integer.valueOf(bs.toString());
|
||||
}
|
||||
|
||||
List<BulletinBoardAPI.BatchData> mixerOutput2BatchData
|
||||
(Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]> mixerOutput) {
|
||||
|
||||
List<BulletinBoardAPI.BatchData> result = new ArrayList<BulletinBoardAPI.BatchData>();
|
||||
|
||||
//
|
||||
|
||||
result.add(BulletinBoardAPI.BatchData.newBuilder()
|
||||
.setData(IntegerToByteString(n))
|
||||
.build());
|
||||
|
||||
for (Mixing.ZeroKnowledgeProof[] zkpLayer : mixerOutput.a) {
|
||||
for (Mixing.ZeroKnowledgeProof zkp : zkpLayer) {
|
||||
result.add(BulletinBoardAPI.BatchData.newBuilder()
|
||||
.setData(zkp.toByteString())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
for (Crypto.RerandomizableEncryptedMessage[] encryptionLayer : mixerOutput.b) {
|
||||
for (Crypto.RerandomizableEncryptedMessage encryption : encryptionLayer) {
|
||||
result.add(BulletinBoardAPI.BatchData.newBuilder()
|
||||
.setData(encryption.toByteString())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]> batchDataList2MixerOutput
|
||||
(List<BulletinBoardAPI.BatchData> batchDataList) throws Exception {
|
||||
|
||||
if (n != ByteString2Integer(batchDataList.remove(0).getData())){
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
int nDiv2 = n >>1;
|
||||
Mixing.ZeroKnowledgeProof[][] proofs = new Mixing.ZeroKnowledgeProof[layers][nDiv2];
|
||||
for (int layer = 0; layer <layers; layer++)
|
||||
{
|
||||
for (int proofIndex = 0 ; proofIndex < nDiv2 ; proofIndex ++)
|
||||
{
|
||||
proofs[layer][proofIndex] = Mixing.ZeroKnowledgeProof.parseFrom(batchDataList.remove(0).getData());
|
||||
}
|
||||
}
|
||||
|
||||
Crypto.RerandomizableEncryptedMessage[][] encryptions
|
||||
= new Crypto.RerandomizableEncryptedMessage[layers + 1][n];
|
||||
for (int layer = 0; layer <layers + 1; layer++)
|
||||
{
|
||||
for (int encryptionIndex = 0 ; encryptionIndex < n ; encryptionIndex ++)
|
||||
{
|
||||
encryptions[layer][encryptionIndex] = Crypto.RerandomizableEncryptedMessage
|
||||
.parseFrom(batchDataList.remove(0).getData());
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<Mixing.ZeroKnowledgeProof[][], Crypto.RerandomizableEncryptedMessage[][]>(proofs,encryptions);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class BatchHandler implements BulletinBoardClient.ClientCallback<SignedBatch> {
|
||||
|
||||
public Pair<Mixing.ZeroKnowledgeProof[][],Crypto.RerandomizableEncryptedMessage[][]> mixerOutput;
|
||||
public boolean done;
|
||||
private int n,layers;
|
||||
private Exception e;
|
||||
|
||||
public BatchHandler(int n, int layers) {
|
||||
this.n = n;
|
||||
this.layers = layers;
|
||||
done = false;
|
||||
e = null;
|
||||
}
|
||||
|
||||
// convert batch message to MixerInput
|
||||
// and verify it
|
||||
@Override
|
||||
public void handleCallback(SignedBatch msg) {
|
||||
BatchConverter batchConverter = new BatchConverter();
|
||||
try {
|
||||
mixerOutput = batchConverter.batchDataList2MixerOutput(msg.getBatchDataList());
|
||||
done = verifyTable();
|
||||
} catch (Exception e) {
|
||||
this.e = e;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
// verify all necessary locations for BeneshNet were proved
|
||||
for (boolean[] checksumLayer: locationChecksum) {
|
||||
for (boolean locationBoolean: checksumLayer) {
|
||||
if (!locationBoolean)
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void handleFailure(Throwable t) {
|
||||
|
||||
}
|
||||
|
||||
private boolean verifyTable()
|
||||
{
|
||||
int index1,index2,layer;
|
||||
|
||||
//initialize locationChecksum table
|
||||
// use for check BeneshNet validity
|
||||
boolean[][] locationChecksum = new boolean[layers][n];
|
||||
for (boolean[] locationChecksumLayer: locationChecksum) {
|
||||
Arrays.fill(locationChecksumLayer,false);
|
||||
}
|
||||
|
||||
Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs = mixerOutput.a;
|
||||
Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages = mixerOutput.b;
|
||||
|
||||
for (Mixing.ZeroKnowledgeProof[] zkpLayer: zeroKnowledgeProofs) {
|
||||
for (Mixing.ZeroKnowledgeProof zkp: zkpLayer) {
|
||||
Mixing.ZeroKnowledgeProof.Location location = zkp.getLocation();
|
||||
index1 = location.getI();
|
||||
index2 = location.getJ();
|
||||
layer = location.getLayer();
|
||||
|
||||
// check location validity
|
||||
if (layer > layers >> 1) {
|
||||
if (index2 - index1 != n >> (layers - layer))
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
if (index2 - index1 != n >> (layer + 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark location in table
|
||||
locationChecksum[layer][index1] = true;
|
||||
locationChecksum[layer][index2] = true;
|
||||
|
||||
// verify proof
|
||||
if(!verifier.verify(rerandomizableEncryptedMessages[index1][layer],
|
||||
rerandomizableEncryptedMessages[index2][layer],
|
||||
rerandomizableEncryptedMessages[index1][layer + 1],
|
||||
rerandomizableEncryptedMessages[index2][layer + 1],
|
||||
zkp))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// verify all necessary locations for BeneshNet were proved
|
||||
for (boolean[] checksumLayer: locationChecksum) {
|
||||
for (boolean locationBoolean: checksumLayer) {
|
||||
if (!locationBoolean)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Crypto.RerandomizableEncryptedMessage> getInputForMixer()
|
||||
{
|
||||
return Arrays.asList(mixerOutput.b[mixerOutput.b.length - 1]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package necessary;
|
||||
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 14-Dec-15.
|
||||
*/
|
||||
public interface AsyncBulletinBoardClient extends BulletinBoardClient {
|
||||
|
||||
/**
|
||||
* Post a message to the bulletin board in an asynchronous manner
|
||||
* @param msg is the message to be posted
|
||||
* @param callback is a class containing methods to handle the result of the operation
|
||||
* @return a unique message ID for the message, that can be later used to retrieve the batch
|
||||
*/
|
||||
MessageID postMessage(BulletinBoardMessage msg, ClientCallback<?> callback);
|
||||
|
||||
/**
|
||||
* This method allows for sending large messages as a batch to the bulletin board
|
||||
* @param signerId is the canonical form for the ID of the sender of this batch
|
||||
* @param batchId is a unique (per signer) ID for this batch
|
||||
* @param batchDataList is the (canonically ordered) list of data comprising the batch message
|
||||
* @param startPosition is the location (in the batch) of the first entry in batchDataList (optionally used to continue interrupted post operations)
|
||||
* @param callback is a callback function class for handling results of the operation
|
||||
* @return a unique message ID for the entire message, that can be later used to retrieve the batch
|
||||
*/
|
||||
MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, int startPosition, ClientCallback<?> callback);
|
||||
|
||||
/**
|
||||
* Overloading of the postBatch method in which startPosition is set to the default value 0
|
||||
*/
|
||||
MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, ClientCallback<?> callback);
|
||||
|
||||
/**
|
||||
* Check how "safe" a given message is in an asynchronous manner
|
||||
* The result of the computation is a rank between 0.0 and 1.0 indicating the fraction of servers containing the message
|
||||
* @param id is the unique message identifier for retrieval
|
||||
* @param callback is a callback function class for handling results of the operation
|
||||
*/
|
||||
void getRedundancy(MessageID id, ClientCallback<Float> callback);
|
||||
|
||||
/**
|
||||
* Read all messages posted matching the given filter in an asynchronous manner
|
||||
* Note that if messages haven't been "fully posted", this might return a different
|
||||
* set of messages in different calls. However, messages that are fully posted
|
||||
* are guaranteed to be included.
|
||||
* @param filterList return only messages that match the filters (null means no filtering).
|
||||
* @param callback is a callback function class for handling results of the operation
|
||||
*/
|
||||
void readMessages(MessageFilterList filterList, ClientCallback<List<BulletinBoardMessage>> callback);
|
||||
|
||||
/**
|
||||
* Read a given batch message from the bulletin board
|
||||
* @param signerId is the ID of the signer (sender) of the batch message
|
||||
* @param batchId is the unique (per signer) ID of the batch
|
||||
* @param callback is a callback class for handling the result of the operation
|
||||
*/
|
||||
void readBatch(byte[] signerId, int batchId, ClientCallback<SignedBatch> callback);
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package necessary;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 12/27/2015.
|
||||
*/
|
||||
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.Voting.*;
|
||||
|
||||
import static meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by talm on 24/10/15.
|
||||
*/
|
||||
public interface BulletinBoardClient {
|
||||
|
||||
interface ClientCallback<T> {
|
||||
void handleCallback(T msg);
|
||||
void handleFailure(Throwable t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the client to use some specified servers
|
||||
* @param clientParams contains the parameters required for the client setup
|
||||
*/
|
||||
void init(BulletinBoardClientParams clientParams);
|
||||
|
||||
/**
|
||||
* Post a message to the bulletin board in a synchronous manner
|
||||
* @param msg is the message to be posted
|
||||
* @return a unique message ID for the message, that can be later used to retrieve the batch
|
||||
* @throws CommunicationException
|
||||
*/
|
||||
MessageID postMessage(BulletinBoardMessage msg) throws CommunicationException;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check how "safe" a given message is in a synchronous manner
|
||||
* @param id is the unique message identifier for retrieval
|
||||
* @return a normalized "redundancy score" from 0 (local only) to 1 (fully published)
|
||||
*/
|
||||
float getRedundancy(MessageID id);
|
||||
|
||||
/**
|
||||
* Read all messages posted matching the given filter in a synchronous manner
|
||||
* Note that if messages haven't been "fully posted", this might return a different
|
||||
* set of messages in different calls. However, messages that are fully posted
|
||||
* are guaranteed to be included.
|
||||
* @param filterList return only messages that match the filters (null means no filtering).
|
||||
* @return the list of messages
|
||||
*/
|
||||
List<BulletinBoardMessage> readMessages(MessageFilterList filterList);
|
||||
|
||||
/**
|
||||
* Closes all connections, if any.
|
||||
* This is done in a synchronous (blocking) way.
|
||||
*/
|
||||
void close();
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package necessary;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 12/27/2015.
|
||||
*/
|
||||
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.protobuf.Crypto.*;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Arbel Deutsch Peled on 14-Dec-15.
|
||||
*
|
||||
* A data structure for holding both a batch message and its signature
|
||||
*/
|
||||
public class SignedBatch {
|
||||
|
||||
private List<BatchData> batchDataList;
|
||||
private Signature signature;
|
||||
|
||||
public SignedBatch() {
|
||||
batchDataList = new LinkedList<BatchData>();
|
||||
}
|
||||
|
||||
public SignedBatch(List<BatchData> newDataList) {
|
||||
this();
|
||||
appendBatchData(newDataList);
|
||||
}
|
||||
|
||||
public SignedBatch(List<BatchData> newDataList, Signature newSignature) {
|
||||
this(newDataList);
|
||||
signature = newSignature;
|
||||
}
|
||||
|
||||
public List<BatchData> getBatchDataList() {
|
||||
return batchDataList;
|
||||
}
|
||||
|
||||
public Signature getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void appendBatchData(BatchData newBatchData) {
|
||||
batchDataList.add(newBatchData);
|
||||
}
|
||||
|
||||
public void appendBatchData(List<BatchData> newBatchDataList) {
|
||||
batchDataList.addAll(newBatchDataList);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue