Skip to content
3 changes: 3 additions & 0 deletions demos/array-mpc-as-a-service/compute-party.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* computation_id is optional, by default it will be 'test'.
*/
const path = require('path');
/* eslint-disable */
const jiff_restAPI = require('../../lib/ext/jiff-client-restful.js');
console.log('Command line arguments: [/path/to/configuration/file.json] [computation_id]');

// Read config
Expand All @@ -35,6 +37,7 @@ const jiffClient = new JIFFClient('http://localhost:8080', computation_id, {
party_count: config.party_count,
initialization: {role: 'compute'} // indicate to the server that this is a compute party
});
jiffClient.apply_extension(jiff_restAPI);

// the computation code
const compute = function () {
Expand Down
2 changes: 1 addition & 1 deletion lib/client/api/initialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module.exports = function (jiffClient) {
}

jiffClient.wait_callbacks.push({ parties: parties, callback: callback, initialization: wait_for_initialization });
jiffClient.execute_wait_callbacks(); // See if the callback can be executed immediately
jiffClient.socketEvent.execute_wait_callbacks(); // See if the callback can be executed immediately
};

/**
Expand Down
4 changes: 2 additions & 2 deletions lib/client/handlers/initialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ module.exports = function (jiffClient) {
}

// Resolve any pending messages that were received before the sender's public key was known
jiffClient.resolve_messages_waiting_for_keys();
jiffClient.socketEvent.resolve_messages_waiting_for_keys();

// Resolve any pending waits that have satisfied conditions
jiffClient.execute_wait_callbacks();
jiffClient.socketEvent.execute_wait_callbacks();

// Check if all keys have been received
if (jiffClient.keymap['s1'] == null) {
Expand Down
111 changes: 58 additions & 53 deletions lib/client/socket/events.js
Original file line number Diff line number Diff line change
@@ -1,103 +1,106 @@
module.exports = function (JIFFClient) {
class SocketEvent {
constructor(JIFFClient) {
this.jiffClient = JIFFClient;
}
/**
* Initialize socket listeners and events
* @memberof module:jiff-client.JIFFClient
* @method
*/
JIFFClient.prototype.initSocket = function () {
const jiffClient = this;
initSocket = function () {
const jiffClient = this.jiffClient;

// set on('connect') handler once!
this.socket.on('connect', jiffClient.handlers.connected);
this.jiffClient.socket.on('connect', jiffClient.handlers.connected);

// Store the id when server sends it back
this.socket.on('initialization', jiffClient.handlers.initialized);
this.jiffClient.socket.on('initialization', jiffClient.handlers.initialized);

// Public keys were updated on the server, and it sent us the updates
jiffClient.socket.on('public_keys', function (msg, callback) {
this.jiffClient.socket.on('public_keys', (msg, callback) => {
callback(true);

msg = JSON.parse(msg);
msg = jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'public_keys', msg], 2);
msg = this.jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'public_keys', msg], 2);

jiffClient.handlers.store_public_keys(msg.public_keys);
this.jiffClient.handlers.store_public_keys(msg.public_keys);
});

// Setup receiving matching shares
this.socket.on('share', function (msg, callback) {
this.jiffClient.socket.on('share', (msg, callback) => {
callback(true); // send ack to server

// parse message
const json_msg = JSON.parse(msg);
const sender_id = json_msg['party_id'];

if (jiffClient.keymap[sender_id] != null) {
jiffClient.handlers.receive_share(json_msg);
if (this.jiffClient.keymap[sender_id] != null) {
this.jiffClient.handlers.receive_share(json_msg);
} else {
if (jiffClient.messagesWaitingKeys[sender_id] == null) {
jiffClient.messagesWaitingKeys[sender_id] = [];
if (this.jiffClient.messagesWaitingKeys[sender_id] == null) {
this.jiffClient.messagesWaitingKeys[String(sender_id)] = [];
}
jiffClient.messagesWaitingKeys[sender_id].push({ label: 'share', msg: json_msg });
this.jiffClient.messagesWaitingKeys[String(sender_id)].push({ label: 'share', msg: json_msg });
}
});

this.socket.on('open', function (msg, callback) {
this.jiffClient.socket.on('open', (msg, callback) => {
callback(true); // send ack to server

// parse message
const json_msg = JSON.parse(msg);
const sender_id = json_msg['party_id'];

if (jiffClient.keymap[sender_id] != null) {
jiffClient.handlers.receive_open(json_msg);
if (this.jiffClient.keymap[sender_id] != null) {
this.jiffClient.handlers.receive_open(json_msg);
} else {
if (jiffClient.messagesWaitingKeys[sender_id] == null) {
jiffClient.messagesWaitingKeys[sender_id] = [];
if (this.jiffClient.messagesWaitingKeys[sender_id] == null) {
this.jiffClient.messagesWaitingKeys[String(sender_id)] = [];
}
jiffClient.messagesWaitingKeys[sender_id].push({ label: 'open', msg: json_msg });
this.jiffClient.messagesWaitingKeys[String(sender_id)].push({ label: 'open', msg: json_msg });
}
});

// handle custom messages
this.socket.on('custom', function (msg, callback) {
this.jiffClient.socket.on('custom', (msg, callback) => {
callback(true); // send ack to server

const json_msg = JSON.parse(msg);
const sender_id = json_msg['party_id'];
const sender_id = String(json_msg['party_id']);
const encrypted = json_msg['encrypted'];

if (jiffClient.keymap[sender_id] != null || encrypted !== true) {
jiffClient.handlers.receive_custom(json_msg);
if (this.jiffClient.keymap[String(sender_id)] != null || encrypted !== true) {
this.jiffClient.handlers.receive_custom(json_msg);
} else {
// key must not exist yet for sender_id, and encrypted must be true
if (jiffClient.messagesWaitingKeys[sender_id] == null) {
jiffClient.messagesWaitingKeys[sender_id] = [];
if (this.jiffClient.messagesWaitingKeys[sender_id] == null) {
this.jiffClient.messagesWaitingKeys[String(sender_id)] = [];
}
jiffClient.messagesWaitingKeys[sender_id].push({ label: 'custom', msg: json_msg });
this.jiffClient.messagesWaitingKeys[String(sender_id)].push({ label: 'custom', msg: json_msg });
}
});

this.socket.on('crypto_provider', function (msg, callback) {
this.jiffClient.socket.on('crypto_provider', (msg, callback) => {
callback(true); // send ack to server
jiffClient.handlers.receive_crypto_provider(JSON.parse(msg));
this.jiffClient.handlers.receive_crypto_provider(JSON.parse(msg));
});

this.socket.on('error', function (msg) {
this.jiffClient.socket.on('error', (msg) => {
try {
msg = JSON.parse(msg);
jiffClient.handlers.error(msg['label'], msg['error']);
this.jiffClient.handlers.error(msg['label'], msg['error']);
} catch (error) {
jiffClient.handlers.error('socket.io', msg);
this.jiffClient.handlers.error('socket.io', msg);
}
});

this.socket.on('disconnect', function (reason) {
this.jiffClient.socket.on('disconnect', (reason) => {
if (reason !== 'io client disconnect') {
// check that the reason is an error and not a user initiated disconnect
console.log('Disconnected!', jiffClient.id, reason);
}

jiffClient.hooks.execute_array_hooks('afterOperation', [jiffClient, 'disconnect', reason], -1);
this.jiffClient.hooks.execute_array_hooks('afterOperation', [this.jiffClient, 'disconnect', reason], -1);
});
};

Expand All @@ -107,63 +110,65 @@ module.exports = function (JIFFClient) {
* @memberof module:jiff-client.JIFFClient
* @method
*/
JIFFClient.prototype.execute_wait_callbacks = function () {
const copy_callbacks = this.wait_callbacks;
this.wait_callbacks = [];
execute_wait_callbacks() {
const copy_callbacks = this.jiffClient.wait_callbacks;
this.jiffClient.wait_callbacks = [];
for (let i = 0; i < copy_callbacks.length; i++) {
const wait = copy_callbacks[i];
const parties = wait.parties;
const callback = wait.callback;
const initialization = wait.initialization;

// Check if the parties to wait for are now known
let parties_satisfied = this.__initialized || !initialization;
let parties_satisfied = this.jiffClient.__initialized || !initialization;
for (let j = 0; j < parties.length; j++) {
const party_id = parties[j];
if (this.keymap == null || this.keymap[party_id] == null) {
const party_id = parties[parseInt(j, 10)];
if (this.jiffClient.keymap == null || this.jiffClient.keymap[String(party_id)] == null) {
parties_satisfied = false;
break;
}
}

if (parties_satisfied) {
callback(this);
callback(this.jiffClient);
} else {
this.wait_callbacks.push(wait);
this.jiffClient.wait_callbacks.push(wait);
}
}
};
}

/**
* Resolves all messages that were pending because their senders primary key was previously unknown.
* These messages are decrypted and verified and handled appropriatly before being removed from the wait queue.
* @memberof module:jiff-client.JIFFClient
* @method
*/
JIFFClient.prototype.resolve_messages_waiting_for_keys = function () {
for (let party_id in this.keymap) {
if (!this.keymap.hasOwnProperty(party_id)) {
resolve_messages_waiting_for_keys() {
for (let party_id in this.jiffClient.keymap) {
if (!Object.prototype.hasOwnProperty.call(this.jiffClient.keymap, String(party_id))) {
continue;
}

const messageQueue = this.messagesWaitingKeys[party_id];
const messageQueue = this.jiffClient.messagesWaitingKeys[String(party_id)];
if (messageQueue == null) {
continue;
}
for (let i = 0; i < messageQueue.length; i++) {
const msg = messageQueue[i];
if (msg.label === 'share') {
this.handlers.receive_share(msg.msg);
this.jiffClient.handlers.receive_share(msg.msg);
} else if (msg.label === 'open') {
this.handlers.receive_open(msg.msg);
this.jiffClient.handlers.receive_open(msg.msg);
} else if (msg.label === 'custom') {
this.handlers.receive_custom(msg.msg);
this.jiffClient.handlers.receive_custom(msg.msg);
} else {
throw new Error('Error resolving pending message: unknown label ' + msg.label);
}
}

this.messagesWaitingKeys[party_id] = null;
this.jiffClient.messagesWaitingKeys[String(party_id)] = null;
}
};
};
}
}

module.exports = SocketEvent;
Loading