in AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/Main.java [133:244]
private static <TState extends GroupMessagingState> TestResult testRun(
int n,
int activeCount,
TState[] states,
GroupMessagingSetupPhase<TState> setupPhase,
GroupMessagingTestImplementation<TState> implementation
) {
String testName = implementation.getClass().getSimpleName();
if (debug) Utils.print("\nStarting " + testName + " test run with " + n + " participants, of which " + activeCount + " active.\n");
TestResult result = new TestResult(testName, n, activeCount);
if (debug) Utils.print("Creating random messages and senders.");
SecureRandom random = new SecureRandom();
Set<Integer> activeSet = new HashSet<>();
activeSet.add(0); // We always want the initiator in the set.
while (activeSet.size() < activeCount) {
activeSet.add(random.nextInt(n));
}
Integer[] active = activeSet.toArray(new Integer[0]);
int messagesToSend = 100;
int messageLength = 32; // Message length 32 bytes, so we can compare as if we were just sending a symmetric key.
int[] messageSenders = new int[messagesToSend];
byte[][] messages = new byte[messagesToSend][messageLength];
for (int i = 0; i < messagesToSend; i++) {
// We're only interested in ratcheting events, so senders should always be
// different from the previous sender.
messageSenders[i] = active[random.nextInt(activeCount)];
while (i != 0 && messageSenders[i] == messageSenders[i-1]) {
messageSenders[i] = active[random.nextInt(activeCount)];
}
random.nextBytes(messages[i]);
}
// Create the necessary setup tooling in advance.
DHPubKey[] identities = new DHPubKey[n];
for (int i = 0; i < n ; i++) {
identities[i] = states[i].getIdentityKeyPair().getPubKey();
}
KeyServer keyServer = new KeyServer(states);
// Create and cache the necessary PreKeys in advance.
setupPhase.generateNecessaryPreKeys(states);
// We'll need two timers; as some interleaving events are counted.
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
if (debug) Utils.print("Setting up session for initiator.");
stopwatch1.startInterval();
setupPhase.setupInitiator(implementation, states, identities, keyServer);
stopwatch1.endInterval();
if (debug) Utils.print("Took " + stopwatch1.getTotal() + " nanoseconds.");
if (debug) Utils.print("Initiator sent " + setupPhase.getBytesSentByInitiator() + " bytes.");
result.setInitiatorSetupTime(stopwatch1.getTotal());
result.setInitiatorSetupBytes(setupPhase.getBytesSentByInitiator());
stopwatch1.reset();
if (debug) Utils.print("Setting up session for " + activeCount + " peers.");
stopwatch1.startInterval();
setupPhase.setupAllOthers(implementation, states, active, identities, keyServer);
stopwatch1.endInterval();
if (debug) Utils.print("Took " + stopwatch1.getTotal() + " nanoseconds.");
if (debug) Utils.print("Others received " + setupPhase.getBytesReceivedByOthers() + " bytes.");
if (debug) Utils.print("Others sent " + setupPhase.getBytesSentByOthers() + " bytes.");
result.setOthersSetupTime(stopwatch1.getTotal());
result.setOthersSetupBytesReceived(setupPhase.getBytesReceivedByOthers());
result.setOthersSetupBytesSent(setupPhase.getBytesSentByOthers());
stopwatch1.reset();
// Use stopwatch1 for sender, stopwatch2 for receiving.
if (debug) Utils.print("Sending " + messagesToSend + " messages.");
int totalSendSizes = 0;
int totalReceiveSizes = 0;
for (int i = 0; i < messagesToSend; i++) {
int sender = messageSenders[i];
byte[] message = messages[i];
stopwatch1.startInterval();
MessageDistributer messageDistributer = implementation.sendMessage(states[sender], message);
stopwatch1.endInterval();
totalSendSizes += messageDistributer.totalSize();
for (int j = 0; j < activeCount; j++) {
int receiver = active[j];
if (receiver == sender) {
continue;
}
byte[] received = messageDistributer.getUpdateMessageForParticipantNum(receiver);
totalReceiveSizes += received.length;
stopwatch2.startInterval();
byte[] decrypted = implementation.receiveMessage(states[receiver], received);
stopwatch2.endInterval();
if (!Arrays.equals(message, decrypted)) {
Utils.except("Message doesn't match.");
}
}
}
if (debug) Utils.print("Total sending time " + stopwatch1.getTotal() + " nanoseconds.");
if (debug) Utils.print("Total receiving time " + stopwatch2.getTotal() + " nanoseconds.");
if (debug) Utils.print("Total bytes sent: " + totalSendSizes + ".");
if (debug) Utils.print("Total bytes received: " + totalReceiveSizes + ".");
result.setSendingTime(stopwatch1.getTotal());
result.setReceivingTime(stopwatch2.getTotal());
result.setBytesSent(totalSendSizes);
result.setBytesReceived(totalReceiveSizes);
if (debug) Utils.print("Ended test run with " + n + " participants.\n---------------\n");
return result;
}