From 97f69173b641ee46402c7a40006691e3c398eab6 Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Tue, 4 Jun 2024 15:46:04 -0400 Subject: [PATCH] preprocess/api done --- lib/client/preprocessing/api.js | 95 ++++++++++++---------- lib/client/preprocessing/daemon.js | 2 +- lib/client/preprocessing/handlers.js | 4 +- lib/client/protocols/bits/protocols.js | 8 +- lib/client/protocols/numbers/arithmetic.js | 10 +-- lib/client/protocols/numbers/comparison.js | 2 +- lib/client/protocols/numbers/protocols.js | 4 +- lib/jiff-client.js | 4 +- tests/regr-tests/preprocess.test.ts | 6 +- 9 files changed, 71 insertions(+), 64 deletions(-) diff --git a/lib/client/preprocessing/api.js b/lib/client/preprocessing/api.js index fdefda9d4..1e46e8c11 100644 --- a/lib/client/preprocessing/api.js +++ b/lib/client/preprocessing/api.js @@ -1,9 +1,12 @@ const LinkedList = require('../../../build/linkedlist.js'); -module.exports = function (jiffClient) { - let isRunning = false; - const userCallbacks = []; - const preprocessingTasks = [new LinkedList()]; +class PreprocessingAPI { + constructor(jiffClient) { + this.jiffClient = jiffClient; + this.isRunning = false; + this.userCallbacks = []; + this.preprocessingTasks = [new LinkedList()]; + } /** * Checks if the given operation uses preprocessed values @@ -13,15 +16,15 @@ module.exports = function (jiffClient) { * @param {string} op - name of the operation to check * @return {boolean} true if the op uses preprocessing, false otherwise */ - jiffClient.has_preprocessing = function (op) { - for (let i = 0; i < jiffClient.extensions.length; i++) { - if (jiffClient.preprocessing_function_map[jiffClient.extensions[i]][op] != null) { + has_preprocessing(op) { + for (let i = 0; i < this.jiffClient.extensions.length; i++) { + if (this.jiffClient.preprocessing_function_map[this.jiffClient.extensions[i]][op] != null) { return true; } } return false; - }; + } /** * Get a preprocessed share/value by associated op_id. If value does not exist @@ -32,16 +35,16 @@ module.exports = function (jiffClient) { * @param {string} op_id - the op_id associated with the preprocessed value/share * @return {object} the preprocessed share(s) */ - jiffClient.get_preprocessing = function (op_id) { - const values = jiffClient.preprocessing_table[op_id]; + get_preprocessing(op_id) { + const values = this.jiffClient.preprocessing_table[op_id]; if (values != null) { return values; } - if (jiffClient.crypto_provider === true) { + if (this.jiffClient.crypto_provider === true) { return null; } throw new Error('No preprocessed value(s) that correspond to the op_id "' + op_id + '"'); - }; + } /** * Store a pair of op_id and associated pre-processed value/share @@ -52,11 +55,11 @@ module.exports = function (jiffClient) { * @param {string} op_id - the op_id associated with the preprocessed value/share * @param {SecretShare} share - the share/value to store */ - jiffClient.store_preprocessing = function (op_id, share) { + store_preprocessing(op_id, share) { if (share != null) { - jiffClient.preprocessing_table[op_id] = share; + this.jiffClient.preprocessing_table[op_id] = share; } - }; + } /** * Generate values used for JIFF operations in advance of the computation. @@ -81,39 +84,39 @@ module.exports = function (jiffClient) { * @return {promise} a promise that is resolved when preprocessing is completed, null if this is called by a party that is neither a compute nor receiver party * @see {@link module:jiff-client~JIFFClient#executePreprocessing} */ - jiffClient.preprocessing = function (dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, id_list, params) { + preprocessing(dependent_op, count, protocols, threshold, receivers_list, compute_list, Zp, id_list, params) { // defaults! if (receivers_list == null) { receivers_list = []; - for (let p = 1; p <= jiffClient.party_count; p++) { + for (let p = 1; p <= this.jiffClient.party_count; p++) { receivers_list.push(p); } } else { - jiffClient.helpers.sort_ids(receivers_list); + this.jiffClient.helpers.sort_ids(receivers_list); } if (compute_list == null) { compute_list = []; - for (let c = 1; c <= jiffClient.party_count; c++) { + for (let c = 1; c <= this.jiffClient.party_count; c++) { compute_list.push(c); } } else { - jiffClient.helpers.sort_ids(compute_list); + this.jiffClient.helpers.sort_ids(compute_list); } // not a receiver nor a sender - if (receivers_list.indexOf(jiffClient.id) === -1 && compute_list.indexOf(jiffClient.id) === -1) { + if (receivers_list.indexOf(this.jiffClient.id) === -1 && compute_list.indexOf(this.jiffClient.id) === -1) { return null; } // more defaults if (Zp == null) { - Zp = jiffClient.Zp; + Zp = this.jiffClient.Zp; } if (threshold == null) { threshold = receivers_list.length; } if (protocols == null) { - protocols = jiffClient.default_preprocessing_protocols; + protocols = this.jiffClient.default_preprocessing_protocols; } // actual preprocessing @@ -124,7 +127,7 @@ module.exports = function (jiffClient) { params = {}; } if (params['namespace'] == null) { - params['namespace'] = jiffClient.extensions[jiffClient.extensions.length - 1]; + params['namespace'] = this.jiffClient.extensions[this.jiffClient.extensions.length - 1]; } // Create preprocessing tasks @@ -139,13 +142,13 @@ module.exports = function (jiffClient) { id: null, params: params, protocols: protocols, - deferred: new jiffClient.helpers.Deferred() + deferred: new this.jiffClient.helpers.Deferred() }; - preprocessingTasks[preprocessingTasks.length - 1].add(task); + this.preprocessingTasks[this.preprocessingTasks.length - 1].add(task); return task.deferred.promise; - }; + } /** * Ask JIFF to start executing preprocessing for tasks previously added by {@link module:jiff-client~JIFFClient#preprocessing}. @@ -158,34 +161,38 @@ module.exports = function (jiffClient) { * @param callback {!Function} - the callback to execute when preprocessing is finished. * {@link module:jiff-client~JIFFClient#preprocessing} */ - jiffClient.executePreprocessing = function (callback) { - userCallbacks.push(callback); - preprocessingTasks.push(new LinkedList()); + executePreprocessing(callback) { + this.userCallbacks.push(callback); + this.preprocessingTasks.push(new LinkedList()); - if (!isRunning) { - __executePreprocessing(); + if (!this.isRunning) { + this.__executePreprocessing(); } - }; + } // called only when preprocessing can run RIGHT NOW - const __executePreprocessing = function () { - isRunning = true; + __executePreprocessing() { + this.isRunning = true; - jiffClient.currentPreprocessingTasks = preprocessingTasks.shift(); - const currentCallback = userCallbacks.shift(); + this.jiffClient.currentPreprocessingTasks = this.preprocessingTasks.shift(); + const currentCallback = this.userCallbacks.shift(); - jiffClient.preprocessingCallback = function () { + const preproApi = this; + + this.jiffClient.preprocessingCallback = function () { + //Check if (currentCallback != null) { currentCallback.apply(null, currentCallback); } - if (userCallbacks.length > 0) { - __executePreprocessing(); + if (preproApi.userCallbacks.length > 0) { + preproApi.__executePreprocessing(); } else { - isRunning = false; + preproApi.isRunning = false; } }; - jiffClient.preprocessingDaemon(); - }; -}; + this.jiffClient.preprocessingDaemon(); + } +} +module.exports = PreprocessingAPI; diff --git a/lib/client/preprocessing/daemon.js b/lib/client/preprocessing/daemon.js index 4aef700a6..a824f5053 100644 --- a/lib/client/preprocessing/daemon.js +++ b/lib/client/preprocessing/daemon.js @@ -86,7 +86,7 @@ module.exports = function (jiffClient) { currentBatchLoad--; if (task.receivers_list.indexOf(jiffClient.id) > -1) { - jiffClient.store_preprocessing(task.id, result.share); + jiffClient.preprocess.store_preprocessing(task.id, result.share); } task.deferred.resolve(); jiffClient.preprocessingDaemon(); diff --git a/lib/client/preprocessing/handlers.js b/lib/client/preprocessing/handlers.js index 2304c4c49..9d0a93a07 100644 --- a/lib/client/preprocessing/handlers.js +++ b/lib/client/preprocessing/handlers.js @@ -139,7 +139,7 @@ module.exports = { if (previousPreprocessing == null || previousPreprocessing === 'RETRY' || (previousPreprocessing[0] != null && previousPreprocessing[0].value === 'RETRY')) { if (!params.defaultBounds && (params.lower_bound == null || params.upper_bound == null)) { - jiff.store_preprocessing(task.id, { ondemand: true }); + jiff.preprocess.store_preprocessing(task.id, { ondemand: true }); return []; } @@ -223,7 +223,7 @@ module.exports = { ]; if (constantNotProvided) { - jiff.store_preprocessing(task_id, { ondemand: true }); + jiff.preprocess.store_preprocessing(task_id, { ondemand: true }); return dependent_ops; } diff --git a/lib/client/protocols/bits/protocols.js b/lib/client/protocols/bits/protocols.js index 46373ab3c..53118d5a0 100644 --- a/lib/client/protocols/bits/protocols.js +++ b/lib/client/protocols/bits/protocols.js @@ -30,7 +30,7 @@ module.exports = { } // try to get preprocessed samples - const result = jiff.get_preprocessing(op_id); + const result = jiff.preprocess.get_preprocessing(op_id); if (result != null && result.ondemand !== true) { return result; } @@ -66,12 +66,12 @@ module.exports = { } else { // preprocess on demand delete jiff.preprocessing_table[op_id]; - jiff.preprocessing('rejection_sampling', 1, null, threshold, parties, parties, Zp, [op_id], { + jiff.preprocess.preprocessing('rejection_sampling', 1, null, threshold, parties, parties, Zp, [op_id], { lower_bound: lower_bound, upper_bound: upper_bound }); - jiff.executePreprocessing(function () { - jiff.utils.resolve_many_secrets(final_deferreds, jiff.get_preprocessing(op_id)); + jiff.preprocess.executePreprocessing(function () { + jiff.utils.resolve_many_secrets(final_deferreds, jiff.preprocess.get_preprocessing(op_id)); }); } diff --git a/lib/client/protocols/numbers/arithmetic.js b/lib/client/protocols/numbers/arithmetic.js index 976f6a086..8a28ef029 100644 --- a/lib/client/protocols/numbers/arithmetic.js +++ b/lib/client/protocols/numbers/arithmetic.js @@ -220,7 +220,7 @@ module.exports = function (SecretShare) { }; // Get shares of triplets. - const triplet = this.jiff.get_preprocessing(op_id + ':triplet'); + const triplet = this.jiff.preprocess.get_preprocessing(op_id + ':triplet'); if (triplet == null) { const promise = this.jiff.from_crypto_provider('triplet', this.holders, Math.max(this.threshold, o.threshold), this.Zp, op_id + ':triplet'); promise.then(function (msg) { @@ -386,7 +386,7 @@ module.exports = function (SecretShare) { }; // Preprocessing cases - const quotient = this.jiff.get_preprocessing(op_id + ':quotient'); + const quotient = this.jiff.preprocess.get_preprocessing(op_id + ':quotient'); if (quotient == null) { // case 1: no preprocessing with crypto provider! const promise = this.jiff.from_crypto_provider('quotient', this.holders, this.threshold, this.Zp, op_id + ':quotient', { constant: cst }); @@ -395,9 +395,9 @@ module.exports = function (SecretShare) { }); } else if (quotient.ondemand === true) { // case 2: constant was not available at preprocessing time, must do it now! - this.jiff.preprocessing('quotient', 1, null, this.threshold, this.holders, this.holders, this.Zp, [op_id + ':quotient'], { constant: cst, namespace: 'base' }); - this.jiff.executePreprocessing(function () { - const quotient = self.jiff.get_preprocessing(op_id + ':quotient'); + this.jiff.preprocess.preprocessing('quotient', 1, null, this.threshold, this.holders, this.holders, this.Zp, [op_id + ':quotient'], { constant: cst, namespace: 'base' }); + this.jiff.preprocess.executePreprocessing(function () { + const quotient = self.jiff.preprocess.get_preprocessing(op_id + ':quotient'); ready_quotient(quotient.r, quotient.q); }); } else { diff --git a/lib/client/protocols/numbers/comparison.js b/lib/client/protocols/numbers/comparison.js index a5af111de..bdd3d2067 100644 --- a/lib/client/protocols/numbers/comparison.js +++ b/lib/client/protocols/numbers/comparison.js @@ -428,7 +428,7 @@ module.exports = function (SecretShare) { }; // generate the bits of a random number less than our prime - const bits = this.jiff.get_preprocessing(op_id + ':sampling'); + const bits = this.jiff.preprocess.get_preprocessing(op_id + ':sampling'); if (bits == null) { const promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id + ':sampling', { bitLength: bitLength, diff --git a/lib/client/protocols/numbers/protocols.js b/lib/client/protocols/numbers/protocols.js index 6795643f3..5243fbd06 100644 --- a/lib/client/protocols/numbers/protocols.js +++ b/lib/client/protocols/numbers/protocols.js @@ -27,7 +27,7 @@ module.exports = function (SecretShare) { }; // get shares of zero - const zero = this.jiff.get_preprocessing(op_id); + const zero = this.jiff.preprocess.get_preprocessing(op_id); if (zero == null) { const promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id, { number: 0, @@ -90,7 +90,7 @@ module.exports = function (SecretShare) { }; // generate the bits of a random number less than our prime - const bits = this.jiff.get_preprocessing(op_id + ':sampling'); + const bits = this.jiff.preprocess.get_preprocessing(op_id + ':sampling'); if (bits == null) { const promise = this.jiff.from_crypto_provider('numbers', this.holders, this.threshold, this.Zp, op_id + ':sampling', { bitLength: bitLength, diff --git a/lib/jiff-client.js b/lib/jiff-client.js index 49465b968..0ab18b233 100644 --- a/lib/jiff-client.js +++ b/lib/jiff-client.js @@ -59,7 +59,7 @@ const api = require('./client/api.js'); // preprocessing const preprocessingMap = require('./client/preprocessing/map.js'); -const preprocessingAPI = require('./client/preprocessing/api.js'); +const PreprocessingAPI = require('./client/preprocessing/api.js'); const preprocessingDaemon = require('./client/preprocessing/daemon.js'); /** @@ -421,7 +421,7 @@ function JIFFClient(hostname, computation_id, options) { // Preprocessing preprocessingMap(this); - preprocessingAPI(this); + this.preprocess = new PreprocessingAPI(this); preprocessingDaemon(this); // set up counters for op_ids diff --git a/tests/regr-tests/preprocess.test.ts b/tests/regr-tests/preprocess.test.ts index c44451ac1..3063956d2 100644 --- a/tests/regr-tests/preprocess.test.ts +++ b/tests/regr-tests/preprocess.test.ts @@ -46,13 +46,13 @@ describe('JIFF Preprocessing Operations', () => { it('should correctly preprocess inner product of the input array and return 329.59', async () => { function innerprod(jiffClient: any, id: number) { - jiffClient.preprocessing('smult', entries[id].length, null, null, null, null, null, null, { div: false }); - jiffClient.preprocessing('open', 1); + jiffClient.preprocess.preprocessing('smult', entries[id].length, null, null, null, null, null, null, { div: false }); + jiffClient.preprocess.preprocessing('open', 1); return new Promise((resolve, reject) => { jiffClient.wait_for([1, 2, 3], async () => { try { let sec_ttl: any = 0; - await jiffClient.executePreprocessing(async function () { + await jiffClient.preprocess.executePreprocessing(async function () { const input = await jiffClient.share_array(entries[id], null, 3, [1, 2, 3], [1, 2]); const array1 = input[1]; const array2 = input[2];