Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion demos/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if [ "$1" == "*" ]; then
EXIT_CODE=0
for i in demos/*; do
if [ -f "$i/test.js" ]; then
if ! [[ "$i" =~ ^demos/(pca|mpc-web|template|mpc-as-a-service)$ ]]; then
if ! [[ "$i" =~ ^demos/(pca|restAPI|template|mpc-as-a-service)$ ]]; then
sleep 2
npm run-script test-demo -- "$i"
CODE=$?
Expand Down
21 changes: 13 additions & 8 deletions lib/jiff-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -859,14 +859,19 @@
jiff.emit(share_id + 'length', receivers_list, array.length.toString(10));
}

jiff.listen(share_id + 'length', function (sender, message) {
lengths[sender] = parseInt(message, 10);
total++;
if (total === senders_list.length) {
jiff.remove_listener(share_id + 'length');
share_array_deferred.resolve(lengths);
}
});
if (receivers_list.indexOf(jiff.id) > -1) {
jiff.listen(share_id + 'length', function (sender, message) {
lengths[sender] = parseInt(message, 10);
total++;
if (total === senders_list.length) {
jiff.remove_listener(share_id + 'length');
share_array_deferred.resolve(lengths);
}
});
} else if (senders_list[0] === jiff.id && senders_list.length === 1) {
lengths[jiff.id] = array.length;
share_array_deferred.resolve(lengths);
}
} else if (typeof(lengths) === 'number') {
// All arrays are of the same length
var l = lengths;
Expand Down
2 changes: 1 addition & 1 deletion lib/jiff-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ exports.make_jiff = function (http, options) {
};

jiff.custom = function (computation_id, from_id, msg) {
jiff.hooks.log(jiff, 'custom from ' + computation_id + '-' + from_id + ' : ' + msg);
jiff.hooks.log(jiff, 'custom from ' + computation_id + '-' + from_id + ' : ' + JSON.stringify(msg));

try {
msg = jiff.execute_array_hooks('beforeOperation', [jiff, 'custom', computation_id, from_id, msg], 4);
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"jsdoc": "^3.5.5",
"marked": "^0.3.9",
"minimist": "^1.2.0",
"mocha": "^4.0.1"
"mocha": "^4.0.1",
"nunjucks": "^3.1.7"
}
}
52 changes: 52 additions & 0 deletions presentation/least-squares/analyst/analyst.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!-- Basic UI for running the demo in the browser -->

<html>
<head>
<title>Linear Least Squares</title>
<style>
.error {
color: #FF0000;
}

td, th {
border: solid 1px darkgray;
}

th input, td input {
width: 70px;
}
</style>

<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>

<script src="/socket.io/socket.io.js"></script>
<script src="/bignumber.js/bignumber.min.js"></script>
<script src="/lib/sodium.js"></script>
<script src="/lib/jiff-client.js"></script>
<script src="/lib/ext/jiff-client-bignumber.js"></script>
<script src="/lib/ext/jiff-client-fixedpoint.js"></script>
<script src="/lib/ext/jiff-client-negativenumber.js"></script>

<!-- Contains UI Handlers and Input Checks -->
<script type="text/javascript" src="/static/analyst/analyst.js"></script>

<!-- Contains the MPC implementation -->
<script type="text/javascript" src="/static/analyst/mpc.js"></script>
</head>
<body>
<h1>Analyst</h1>
<h3>Analysis:</h3> <button onclick="submit();" id="submit">Linear Least Squares</button>
<br/>
<h3>Output:</h3>
<div id="output" style="display: none;">
<div style="width:900px; height:900px;">
<canvas id="myChart" width="900" height="900"></canvas>
</div>
</div>
</body>

<script type="text/javascript">
connect({{config.compute + 1}}, {{config.total}}, {{config.compute}}, '{{ config.computation_id }}');
</script>
</html>
103 changes: 103 additions & 0 deletions presentation/least-squares/analyst/analyst.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* Do not modify this file unless you have to.
* This file has UI handlers.
*/

// eslint-disable-next-line no-unused-vars
var computes = [];
function connect(party_id, party_count, compute_count, computation_id) {
// Compute parties ids
for (var c = 1; c <= compute_count; c++) {
computes.push(c);
}

// jiff options
var options = { party_count: party_count, party_id: party_id };
options.onError = function (error) {
$('#output').append('<p class=\'error\'>'+error+'</p>');
};
options.onConnect = function () {
$('#output').append('<p>Connected!</p>');
};

// host name
var hostname = window.location.hostname.trim();
var port = window.location.port;
if (port == null || port === '') {
port = '80';
}
if (!(hostname.startsWith('http://') || hostname.startsWith('https://'))) {
hostname = 'http://' + hostname;
}
if (hostname.endsWith('/')) {
hostname = hostname.substring(0, hostname.length-1);
}
if (hostname.indexOf(':') > -1 && hostname.lastIndexOf(':') > hostname.indexOf(':')) {
hostname = hostname.substring(0, hostname.lastIndexOf(':'));
}

hostname = hostname + ':' + port;

// eslint-disable-next-line no-undef
mpc.connect(hostname, computation_id, options, computes, function (id, cols) {
var schema = 'Party ' + (id - computes.length - 1) + ': ' + cols.join(' | ') + '<br/>';
document.getElementById('schema').innerHTML += schema;
});
}

// eslint-disable-next-line no-unused-vars
function submit() {
$('#output').append('<p>Starting...</p>');
$('#submit').attr('disabled', true);

// eslint-disable-next-line no-undef
mpc.compute().then(plot);
}

/**
* Helpers for drawing lines in a chart
*/
// The limits of the graph. The minimum and maximum X and Y values.
var minX = -60;
var maxX = 60;
var minY = -60;
var maxY = 60;

// Chart for drawing
function initChart(line) {
var ctx = document.getElementById('myChart').getContext('2d');

var scales = {
yAxes: [{ ticks: { min: minY, max: maxY, maxTicksLimit: 5 } }],
xAxes: [{ type: 'linear', position: 'bottom', ticks: { min: minX, max: maxX, maxTicksLimit: 20 } }]
};

// eslint-disable-next-line no-undef
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{ id: 'least-line', label: '', data: line, fill: false, pointBackgroundColor: '#000099', borderColor: '#000099', pointRadius: 0 }
]
},
options: {
elements: { line: { tension: 1 } },
scales: scales
}
});
myChart.update();
}

function plot(data) {
console.log(data.slope.toString(), data.yIntercept.toString());
var m = data.slope;
var p = data.yIntercept;

var points = [];
for (var i = minX; i <= maxX; i+=1) {
points.push({x: i, y: m.times(i).plus(p).toNumber()});
}

$('#output').show();
initChart(points);
}
36 changes: 36 additions & 0 deletions presentation/least-squares/analyst/mpc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
(function (exports) {
var jiff_instance;
var computes;

/**
* Connect to the server and initialize the jiff instance
*/
exports.connect = function (hostname, computation_id, options, _computes, schema_callback) {
computes = _computes;
var opt = Object.assign({}, options);
opt.Zp = '4503599627370449';
opt.integer_digits = 9;
opt.decimal_digits = 3;

// eslint-disable-next-line no-undef
jiff_instance = jiff.make_jiff(hostname, computation_id, opt);
// eslint-disable-next-line no-undef
jiff_instance.apply_extension(jiff_bignumber, opt);
// eslint-disable-next-line no-undef
jiff_instance.apply_extension(jiff_fixedpoint, opt);
// eslint-disable-next-line no-undef
jiff_instance.apply_extension(jiff_negativenumber, opt);
};

/**
* The MPC computation
*/
exports.compute = function () {
var promise1 = jiff_instance.receive_open(computes);
var promise2 = jiff_instance.receive_open(computes);

return Promise.all([promise1, promise2]).then(function (res) {
return {slope: res[0], yIntercept: res[1]};
});
};
}(this.mpc = {}));
96 changes: 96 additions & 0 deletions presentation/least-squares/compute/mpc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Configurations
var decimal_digits = 3;

var config = require('../config.json');
var computes = [];
for (var c = 1; c <= config.compute; c++) {
computes.push(c);
}
var analyst = computes.length + 1;
var inputs = [];
for (var i = config.compute + 2; i <= config.total; i++) {
inputs.push(i);
}

/**
* Connect to the server and initialize the jiff instance
*/
exports.connect = function (hostname, computation_id, options) {
var opt = Object.assign({}, options);
opt.Zp = '4503599627370449';
opt.integer_digits = 9;
opt.decimal_digits = decimal_digits;

var jiff = require('../../../lib/jiff-client');
var jiff_bignumber = require('../../../lib/ext/jiff-client-bignumber');
var jiff_fixedpoint = require('../../../lib/ext/jiff-client-fixedpoint');
var jiff_negativenumber = require('../../../lib/ext/jiff-client-negativenumber');

var jiff_instance = jiff.make_jiff(hostname, computation_id, opt);
jiff_instance.apply_extension(jiff_bignumber, opt);
jiff_instance.apply_extension(jiff_fixedpoint, opt);
jiff_instance.apply_extension(jiff_negativenumber, opt);
jiff_instance.wait_for(computes, function () {
compute(jiff_instance);
});
jiff_instance.wait_for(['s1'], function () {
console.log('This is compute party ', jiff_instance.id);
})
};

/**
* The MPC computation
*/
function compute(jiff_instance) {
var avgs = jiff_instance.share(null, computes.length, computes, inputs);
var xAvg = avgs[inputs[0]];
var yAvg = avgs[inputs[1]];

var xBar = jiff_instance.share_array([], null, computes.length, computes, [inputs[0]]);
var yBar = jiff_instance.share_array([], null, computes.length, computes, [inputs[1]]);
xBar.then(function (arr) {
console.log('First input party secret shared their data!');
var share = arr[inputs[0]][0];
if (share.value != null) {
console.log('First secret share value ', share.value.toString());
} else {
share.promise.then(function () {
console.log('First secret share value ', share.value.toString());
});
}
});
yBar.then(function (arr) {
console.log('Second input party secret shared their data!');
var share = arr[inputs[1]][0];
if (share.value != null) {
console.log('First secret share value ', share.value.toString());
} else {
share.promise.then(function () {
console.log('First secret share value ', share.value.toString());
});
}
});

var xBarSquare = jiff_instance.share(null, computes.length, computes, [inputs[0]])[inputs[0]];

Promise.all([xBar, yBar]).then(function (res) {
xBar = res[0][inputs[0]];
yBar = res[1][inputs[1]];

var numerator = xBar[0].smult(yBar[0], null, false);
for (var i = 1; i < xBar.length; i++) {
numerator = numerator.sadd(xBar[i].smult(yBar[i], null, false));
}
var denumerator = xBarSquare.cmult(jiff_instance.helpers.magnitude(decimal_digits));

// Compute slope and y Intercept of line
var slope = numerator.sdiv(denumerator);
var yIntercept = yAvg.ssub(slope.smult(xAvg, 'main-smult'));

// Done
jiff_instance.wait_for([analyst], function () {
jiff_instance.open(slope, [analyst]);
jiff_instance.open(yIntercept, [analyst]);
});
});
}
16 changes: 16 additions & 0 deletions presentation/least-squares/compute/party.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Do not change this unless you have to.
* This code parses input command line arguments,
* and calls the appropriate initialization and MPC protocol from ./mpc.js
*/
var mpc = require('./mpc');
var config = require('../config.json');

// JIFF options
var options = {
initialization: {role: 'compute'},
party_count: config.total
};

// Connect
mpc.connect('http://localhost:8080', config.computation_id, options);
5 changes: 5 additions & 0 deletions presentation/least-squares/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"computation_id": "test",
"compute": 2,
"total": 5
}
Loading