Rip the worker logic out of message_receiver and add the functionality for it to work with pow. Fix pow tests to work with those changes

pull/104/head
Beaudan 7 years ago
parent 37abdc6a4e
commit 6113f13d3a

1
.gitignore vendored

@ -22,6 +22,7 @@ js/libtextsecure.js
js/libloki.js js/libloki.js
libtextsecure/components.js libtextsecure/components.js
libtextsecure/test/test.js libtextsecure/test/test.js
libloki/test/components.js
libloki/test/test.js libloki/test/test.js
stylesheets/*.css stylesheets/*.css
test/test.js test/test.js

@ -25,6 +25,12 @@ module.exports = grunt => {
libtextsecurecomponents.push(bower.concat.libtextsecure[i]); libtextsecurecomponents.push(bower.concat.libtextsecure[i]);
} }
const liblokicomponents = [];
// eslint-disable-next-line guard-for-in, no-restricted-syntax
for (const i in bower.concat.libloki) {
liblokicomponents.push(bower.concat.libloki[i]);
}
grunt.loadNpmTasks('grunt-sass'); grunt.loadNpmTasks('grunt-sass');
grunt.initConfig({ grunt.initConfig({
@ -37,6 +43,8 @@ module.exports = grunt => {
util_worker: { util_worker: {
src: [ src: [
'components/bytebuffer/dist/ByteBufferAB.js', 'components/bytebuffer/dist/ByteBufferAB.js',
'components/JSBI/dist/jsbi.mjs',
'libloki/proof-of-work.js',
'components/long/dist/Long.js', 'components/long/dist/Long.js',
'js/util_worker_tasks.js', 'js/util_worker_tasks.js',
], ],
@ -46,6 +54,10 @@ module.exports = grunt => {
src: libtextsecurecomponents, src: libtextsecurecomponents,
dest: 'libtextsecure/components.js', dest: 'libtextsecure/components.js',
}, },
liblokicomponents: {
src: liblokicomponents,
dest: 'libloki/test/components.js',
},
test: { test: {
src: [ src: [
'node_modules/mocha/mocha.js', 'node_modules/mocha/mocha.js',
@ -141,6 +153,16 @@ module.exports = grunt => {
files: ['./libtextsecure/*.js', './libtextsecure/storage/*.js'], files: ['./libtextsecure/*.js', './libtextsecure/storage/*.js'],
tasks: ['concat:libtextsecure'], tasks: ['concat:libtextsecure'],
}, },
utilworker: {
files: [
'components/bytebuffer/dist/ByteBufferAB.js',
'components/JSBI/dist/jsbi.mjs',
'libloki/proof-of-work.js',
'components/long/dist/Long.js',
'js/util_worker_tasks.js',
],
tasks: ['concat:util_worker'],
},
libloki: { libloki: {
files: ['./libloki/*.js'], files: ['./libloki/*.js'],
tasks: ['concat:libloki'], tasks: ['concat:libloki'],

@ -64,6 +64,11 @@
"components/long/**/*.js", "components/long/**/*.js",
"components/bytebuffer/**/*.js", "components/bytebuffer/**/*.js",
"components/protobuf/**/*.js" "components/protobuf/**/*.js"
],
"libloki": [
"components/long/**/*.js",
"components/bytebuffer/**/*.js",
"components/JSBI/dist/jsbi.mjs"
] ]
} }
} }

File diff suppressed because it is too large Load Diff

@ -1,41 +1,7 @@
/* global log, dcodeIO, window */ /* global log, dcodeIO, window, callWorker */
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const is = require('@sindresorhus/is'); const is = require('@sindresorhus/is');
const { fork } = require('child_process');
const development = (window.getEnvironment() !== 'production');
function getPoWNonce(timestamp, ttl, pubKey, data) {
return new Promise((resolve, reject) => {
// Create forked node process to calculate PoW without blocking main process
const child = fork('./libloki/proof-of-work.js');
// Send data required for PoW to child process
child.send({
timestamp,
ttl,
pubKey,
data,
development,
});
// Handle child process error (should never happen)
child.on('error', err => {
reject(err);
});
// Callback to receive PoW result
child.on('message', msg => {
if (msg.err) {
reject(msg.err);
} else {
child.kill();
resolve(msg.nonce);
}
});
});
}
class LokiServer { class LokiServer {
@ -62,11 +28,12 @@ class LokiServer {
pubKey, pubKey,
timestamp: messageTimeStamp, timestamp: messageTimeStamp,
}); });
nonce = await getPoWNonce(timestamp, ttl, pubKey, data64); const development = window.getEnvironment() !== 'production';
nonce = await callWorker('calcPoW', timestamp, ttl, pubKey, data64, development);
} catch (err) { } catch (err) {
// Something went horribly wrong // Something went horribly wrong
// TODO: Handle gracefully // TODO: Handle gracefully
log.error('Error computing PoW'); throw err;
} }
const options = { const options = {

@ -0,0 +1,124 @@
/* global Worker, window, setTimeout */
const WORKER_TIMEOUT = 60 * 1000; // one minute
class TimedOutError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = (new Error(message)).stack;
}
}
}
class WorkerInterface {
constructor(path) {
this._utilWorker = new Worker(path);
this._jobs = Object.create(null);
this._DEBUG = false;
this._jobCounter = 0;
this._utilWorker.onmessage = e => {
const [jobId, errorForDisplay, result] = e.data;
const job = this._getJob(jobId);
if (!job) {
throw new Error(
`Received worker reply to job ${jobId}, but did not have it in our registry!`
);
}
const { resolve, reject, fnName } = job;
if (errorForDisplay) {
return reject(
new Error(
`Error received from worker job ${jobId} (${fnName}): ${errorForDisplay}`
)
);
}
return resolve(result);
};
}
_makeJob (fnName) {
this._jobCounter += 1;
const id = this._jobCounter;
if (this._DEBUG) {
window.log.info(`Worker job ${id} (${fnName}) started`);
}
this._jobs[id] = {
fnName,
start: Date.now(),
};
return id;
};
_updateJob(id, data) {
const { resolve, reject } = data;
const { fnName, start } = this._jobs[id];
this._jobs[id] = {
...this._jobs[id],
...data,
resolve: value => {
this._removeJob(id);
const end = Date.now();
window.log.info(
`Worker job ${id} (${fnName}) succeeded in ${end - start}ms`
);
return resolve(value);
},
reject: error => {
this._removeJob(id);
const end = Date.now();
window.log.info(
`Worker job ${id} (${fnName}) failed in ${end - start}ms`
);
return reject(error);
},
};
};
_removeJob(id) {
if (this._DEBUG) {
this._jobs[id].complete = true;
} else {
delete this._jobs[id];
}
}
_getJob(id) {
return this._jobs[id];
};
callWorker(fnName, ...args) {
const jobId = this._makeJob(fnName);
return new Promise((resolve, reject) => {
this._utilWorker.postMessage([jobId, fnName, ...args]);
this._updateJob(jobId, {
resolve,
reject,
args: this._DEBUG ? args : null,
});
setTimeout(
() => reject(new TimedOutError(`Worker job ${jobId} (${fnName}) timed out`)),
WORKER_TIMEOUT
);
});
};
}
module.exports = {
WorkerInterface,
TimedOutError,
};

@ -1,11 +1,10 @@
/* global dcodeIO */ /* global dcodeIO, pow */
/* eslint-disable strict */ /* eslint-disable strict */
'use strict';
const functions = { const functions = {
stringToArrayBufferBase64, stringToArrayBufferBase64,
arrayBufferToStringBase64, arrayBufferToStringBase64,
calcPoW,
}; };
onmessage = async e => { onmessage = async e => {
@ -42,3 +41,6 @@ function stringToArrayBufferBase64(string) {
function arrayBufferToStringBase64(arrayBuffer) { function arrayBufferToStringBase64(arrayBuffer) {
return dcodeIO.ByteBuffer.wrap(arrayBuffer).toString('base64'); return dcodeIO.ByteBuffer.wrap(arrayBuffer).toString('base64');
} }
function calcPoW(timestamp, ttl, pubKey, data, development) {
return pow.calcPoW(timestamp, ttl, pubKey, data, development);
}

@ -1,23 +1,12 @@
const hash = require('js-sha512'); /* global dcodeIO, crypto, JSBI */
const bb = require('bytebuffer');
const { BigInteger } = require('jsbn');
module.exports = {
calcTarget,
incrementNonce,
bufferToBase64,
bigIntToUint8Array,
greaterThan,
};
const NONCE_LEN = 8; const NONCE_LEN = 8;
// Modify this value for difficulty scaling // Modify this value for difficulty scaling
const DEV_NONCE_TRIALS = 10; const DEV_NONCE_TRIALS = 10;
const PROD_NONCE_TRIALS = 1000; const PROD_NONCE_TRIALS = 1000;
let development = true;
const pow = {
// Increment Uint8Array nonce by 1 with carrying // Increment Uint8Array nonce by 1 with carrying
function incrementNonce(nonce) { incrementNonce(nonce) {
let idx = NONCE_LEN - 1; let idx = NONCE_LEN - 1;
const newNonce = new Uint8Array(nonce); const newNonce = new Uint8Array(nonce);
newNonce[idx] += 1; newNonce[idx] += 1;
@ -27,35 +16,38 @@ function incrementNonce(nonce) {
newNonce[idx] += 1; newNonce[idx] += 1;
} }
return newNonce; return newNonce;
} },
// Convert a Uint8Array to a base64 string // Convert a Uint8Array to a base64 string
function bufferToBase64(buf) { bufferToBase64(buf) {
function mapFn(ch) { function mapFn(ch) {
return String.fromCharCode(ch); return String.fromCharCode(ch);
} }
const binaryString = Array.prototype.map.call(buf, mapFn).join(''); const binaryString = Array.prototype.map.call(buf, mapFn).join('');
return bb.btoa(binaryString); return dcodeIO.ByteBuffer.btoa(binaryString);
} },
// Convert BigInteger to Uint8Array of length NONCE_LEN // Convert BigInteger to Uint8Array of length NONCE_LEN
function bigIntToUint8Array(bigInt) { bigIntToUint8Array(bigInt) {
const arr = new Uint8Array(NONCE_LEN); const arr = new Uint8Array(NONCE_LEN);
let n; let n;
for (let idx = NONCE_LEN - 1; idx >= 0; idx -= 1) { for (let idx = NONCE_LEN - 1; idx >= 0; idx -= 1) {
n = NONCE_LEN - (idx + 1); n = NONCE_LEN - (idx + 1);
// 256 ** n is the value of one bit in arr[idx], modulus to carry over // 256 ** n is the value of one bit in arr[idx], modulus to carry over
// (bigInt / 256**n) % 256; // (bigInt / 256**n) % 256;
const uint8Val = bigInt const denominator = JSBI.exponentiate(
.divide(new BigInteger('256').pow(n)) JSBI.BigInt('256'),
.mod(new BigInteger('256')); JSBI.BigInt(n)
arr[idx] = uint8Val.intValue(); );
const fraction = JSBI.divide(bigInt, denominator);
const uint8Val = JSBI.remainder(fraction, JSBI.BigInt(256));
arr[idx] = JSBI.toNumber(uint8Val);
} }
return arr; return arr;
} },
// Compare two Uint8Arrays, return true if arr1 is > arr2 // Compare two Uint8Arrays, return true if arr1 is > arr2
function greaterThan(arr1, arr2) { greaterThan(arr1, arr2) {
// Early exit if lengths are not equal. Should never happen // Early exit if lengths are not equal. Should never happen
if (arr1.length !== arr2.length) return false; if (arr1.length !== arr2.length) return false;
@ -64,71 +56,77 @@ function greaterThan(arr1, arr2) {
if (arr1[i] < arr2[i]) return false; if (arr1[i] < arr2[i]) return false;
} }
return false; return false;
} },
// Return nonce that hashes together with payload lower than the target // Return nonce that hashes together with payload lower than the target
function calcPoW(timestamp, ttl, pubKey, data) { async calcPoW(timestamp, ttl, pubKey, data, development = false) {
const payload = new Uint8Array( const payload = new Uint8Array(
bb.wrap(timestamp.toString() + ttl.toString() + pubKey + data, 'binary').toArrayBuffer() dcodeIO.ByteBuffer.wrap(
timestamp.toString() + ttl.toString() + pubKey + data,
'binary'
).toArrayBuffer()
); );
const target = calcTarget(ttl, payload.length); const nonceTrials = development ? DEV_NONCE_TRIALS : PROD_NONCE_TRIALS;
const target = pow.calcTarget(ttl, payload.length, nonceTrials);
let nonce = new Uint8Array(NONCE_LEN); let nonce = new Uint8Array(NONCE_LEN);
let trialValue = bigIntToUint8Array( let trialValue = pow.bigIntToUint8Array(
new BigInteger(Number.MAX_SAFE_INTEGER.toString()) JSBI.BigInt(Number.MAX_SAFE_INTEGER)
); );
const initialHash = new Uint8Array( const initialHash = new Uint8Array(
bb.wrap(hash(payload), 'hex').toArrayBuffer() await crypto.subtle.digest('SHA-512', payload)
); );
const innerPayload = new Uint8Array(initialHash.length + NONCE_LEN); const innerPayload = new Uint8Array(initialHash.length + NONCE_LEN);
innerPayload.set(initialHash, NONCE_LEN); innerPayload.set(initialHash, NONCE_LEN);
let resultHash; let resultHash;
while (greaterThan(trialValue, target)) { while (pow.greaterThan(trialValue, target)) {
nonce = incrementNonce(nonce); nonce = pow.incrementNonce(nonce);
innerPayload.set(nonce); innerPayload.set(nonce);
resultHash = hash(innerPayload); // eslint-disable-next-line no-await-in-loop
resultHash = await crypto.subtle.digest('SHA-512', innerPayload);
trialValue = new Uint8Array( trialValue = new Uint8Array(
bb.wrap(resultHash, 'hex').toArrayBuffer() dcodeIO.ByteBuffer.wrap(resultHash, 'hex').toArrayBuffer()
).slice(0, NONCE_LEN); ).slice(0, NONCE_LEN);
} }
return bufferToBase64(nonce); return pow.bufferToBase64(nonce);
} },
function calcTarget(ttl, payloadLen) { calcTarget(ttl, payloadLen, nonceTrials = PROD_NONCE_TRIALS) {
// payloadLength + NONCE_LEN // payloadLength + NONCE_LEN
const totalLen = new BigInteger(payloadLen.toString()).add( const totalLen = JSBI.add(
new BigInteger(NONCE_LEN.toString()) JSBI.BigInt(payloadLen),
JSBI.BigInt(NONCE_LEN)
); );
// ttl * totalLen // ttl * totalLen
const ttlMult = new BigInteger(ttl.toString()).multiply(totalLen); const ttlMult = JSBI.multiply(
// ttlMult / (2^16 - 1) JSBI.BigInt(ttl),
const innerFrac = ttlMult.divide( JSBI.BigInt(totalLen)
new BigInteger('2').pow(16).subtract(new BigInteger('1')) );
// 2^16 - 1
const two16 = JSBI.subtract(
JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(16)), // 2^16
JSBI.BigInt(1)
);
// ttlMult / two16
const innerFrac = JSBI.divide(
ttlMult,
two16
); );
// totalLen + innerFrac // totalLen + innerFrac
const lenPlusInnerFrac = totalLen.add(innerFrac); const lenPlusInnerFrac = JSBI.add(totalLen, innerFrac);
// nonceTrials * lenPlusInnerFrac // nonceTrials * lenPlusInnerFrac
const nonceTrials = development ? DEV_NONCE_TRIALS : PROD_NONCE_TRIALS; const denominator = JSBI.multiply(
const denominator = new BigInteger(nonceTrials.toString()).multiply( JSBI.BigInt(nonceTrials),
lenPlusInnerFrac lenPlusInnerFrac
); );
// 2^64 - 1 // 2^64 - 1
const two64 = new BigInteger('2').pow(64).subtract(new BigInteger('1')); const two64 = JSBI.subtract(
JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(64)), // 2^64
JSBI.BigInt(1)
);
// two64 / denominator // two64 / denominator
const targetNum = two64.divide(denominator); const targetNum = JSBI.divide(two64, denominator);
return bigIntToUint8Array(targetNum); return pow.bigIntToUint8Array(targetNum);
} },
};
// Start calculation in child process when main process sends message data
process.on('message', msg => {
({ development } = msg);
process.send({
nonce: calcPoW(
msg.timestamp,
msg.ttl,
msg.pubKey,
msg.data
),
});
});

@ -13,9 +13,10 @@
</div> </div>
<script type="text/javascript" src="test.js"></script> <script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../../libtextsecure/test/in_memory_signal_protocol_store.js"></script> <script type="text/javascript" src="components.js"></script>
<script type="text/javascript" src="../../libtextsecure/components.js"></script> <script type="text/javascript" src="../../libtextsecure/test/in_memory_signal_protocol_store.js"></script>
<script type="text/javascript" src="../../libloki/proof-of-work.js"></script>
<script type="text/javascript" src="../../libtextsecure/helpers.js" data-cover></script> <script type="text/javascript" src="../../libtextsecure/helpers.js" data-cover></script>
<script type="text/javascript" src="../../libtextsecure/storage.js" data-cover></script> <script type="text/javascript" src="../../libtextsecure/storage.js" data-cover></script>
<script type="text/javascript" src="../../libtextsecure/libsignal-protocol.js"></script> <script type="text/javascript" src="../../libtextsecure/libsignal-protocol.js"></script>
@ -25,6 +26,7 @@
<script type="text/javascript" src="../libloki-protocol.js" data-cover></script> <script type="text/javascript" src="../libloki-protocol.js" data-cover></script>
<script type="text/javascript" src="proof-of-work_test.js"></script>
<script type="text/javascript" src="libloki-protocol_test.js"></script> <script type="text/javascript" src="libloki-protocol_test.js"></script>
<!-- Comment out to turn off code coverage. Useful for getting real callstacks. --> <!-- Comment out to turn off code coverage. Useful for getting real callstacks. -->

@ -1,6 +1,4 @@
/* global require */ /* global assert, JSBI, pow */
const { assert } = require('chai');
const { BigInteger } = require('jsbn');
const { const {
calcTarget, calcTarget,
@ -8,7 +6,7 @@ const {
bufferToBase64, bufferToBase64,
bigIntToUint8Array, bigIntToUint8Array,
greaterThan, greaterThan,
} = require('../../libloki/proof-of-work'); } = pow;
describe('Proof of Work Worker', () => { describe('Proof of Work Worker', () => {
it('should increment a Uint8Array nonce correctly', () => { it('should increment a Uint8Array nonce correctly', () => {
@ -42,11 +40,11 @@ describe('Proof of Work Worker', () => {
const ttl = 86400; const ttl = 86400;
let expectedTarget = new Uint8Array([0,4,119,164,35,224,222,64]); let expectedTarget = new Uint8Array([0,4,119,164,35,224,222,64]);
let actualTarget = calcTarget(ttl, payloadLen); let actualTarget = calcTarget(ttl, payloadLen, 10);
assert.deepEqual(actualTarget, expectedTarget); assert.deepEqual(actualTarget, expectedTarget);
payloadLen = 6597; payloadLen = 6597;
expectedTarget = new Uint8Array([0,0,109,145,174,146,124,3]); expectedTarget = new Uint8Array([0,0,109,145,174,146,124,3]);
actualTarget = calcTarget(ttl, payloadLen); actualTarget = calcTarget(ttl, payloadLen, 10);
assert.deepEqual(actualTarget, expectedTarget); assert.deepEqual(actualTarget, expectedTarget);
}); });
@ -81,16 +79,16 @@ describe('Proof of Work Worker', () => {
}); });
it('should correclty convert a BigInteger to a Uint8Array', () => { it('should correclty convert a BigInteger to a Uint8Array', () => {
let bigInt = new BigInteger(Number.MAX_SAFE_INTEGER.toString()); let bigInt = JSBI.BigInt(Number.MAX_SAFE_INTEGER);
let expected = new Uint8Array([0, 31, 255, 255, 255, 255, 255, 255]); let expected = new Uint8Array([0, 31, 255, 255, 255, 255, 255, 255]);
assert.deepEqual(bigIntToUint8Array(bigInt), expected); assert.deepEqual(bigIntToUint8Array(bigInt), expected);
bigInt = new BigInteger('0'); bigInt = JSBI.BigInt('0');
expected = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]); expected = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]);
assert.deepEqual(bigIntToUint8Array(bigInt), expected); assert.deepEqual(bigIntToUint8Array(bigInt), expected);
bigInt = new BigInteger('255'); bigInt = JSBI.BigInt('255');
expected = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 255]); expected = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 255]);
assert.deepEqual(bigIntToUint8Array(bigInt), expected); assert.deepEqual(bigIntToUint8Array(bigInt), expected);
bigInt = new BigInteger('256'); bigInt = JSBI.BigInt('256');
expected = new Uint8Array([0, 0, 0, 0, 0, 0, 1, 0]); expected = new Uint8Array([0, 0, 0, 0, 0, 0, 1, 0]);
assert.deepEqual(bigIntToUint8Array(bigInt), expected); assert.deepEqual(bigIntToUint8Array(bigInt), expected);
}); });

@ -1,6 +1,6 @@
/* global window: false */ /* global window: false */
/* global callWorker: false */
/* global textsecure: false */ /* global textsecure: false */
/* global storage: false */
/* global StringView: false */ /* global StringView: false */
/* global libloki: false */ /* global libloki: false */
/* global libsignal: false */ /* global libsignal: false */
@ -11,114 +11,11 @@
/* global HttpResource: false */ /* global HttpResource: false */
/* global ContactBuffer: false */ /* global ContactBuffer: false */
/* global GroupBuffer: false */ /* global GroupBuffer: false */
/* global Worker: false */
/* global WebSocketResource: false */ /* global WebSocketResource: false */
/* eslint-disable more/no-then */ /* eslint-disable more/no-then */
/* eslint-disable no-unreachable */ /* eslint-disable no-unreachable */
const WORKER_TIMEOUT = 60 * 1000; // one minute
const _utilWorker = new Worker('js/util_worker.js');
const _jobs = Object.create(null);
const _DEBUG = false;
let _jobCounter = 0;
function _makeJob(fnName) {
_jobCounter += 1;
const id = _jobCounter;
if (_DEBUG) {
window.log.info(`Worker job ${id} (${fnName}) started`);
}
_jobs[id] = {
fnName,
start: Date.now(),
};
return id;
}
function _updateJob(id, data) {
const { resolve, reject } = data;
const { fnName, start } = _jobs[id];
_jobs[id] = {
..._jobs[id],
...data,
resolve: value => {
_removeJob(id);
const end = Date.now();
window.log.info(
`Worker job ${id} (${fnName}) succeeded in ${end - start}ms`
);
return resolve(value);
},
reject: error => {
_removeJob(id);
const end = Date.now();
window.log.info(
`Worker job ${id} (${fnName}) failed in ${end - start}ms`
);
return reject(error);
},
};
}
function _removeJob(id) {
if (_DEBUG) {
_jobs[id].complete = true;
} else {
delete _jobs[id];
}
}
function _getJob(id) {
return _jobs[id];
}
async function callWorker(fnName, ...args) {
const jobId = _makeJob(fnName);
return new Promise((resolve, reject) => {
_utilWorker.postMessage([jobId, fnName, ...args]);
_updateJob(jobId, {
resolve,
reject,
args: _DEBUG ? args : null,
});
setTimeout(
() => reject(new Error(`Worker job ${jobId} (${fnName}) timed out`)),
WORKER_TIMEOUT
);
});
}
_utilWorker.onmessage = e => {
const [jobId, errorForDisplay, result] = e.data;
const job = _getJob(jobId);
if (!job) {
throw new Error(
`Received worker reply to job ${jobId}, but did not have it in our registry!`
);
}
const { resolve, reject, fnName } = job;
if (errorForDisplay) {
return reject(
new Error(
`Error received from worker job ${jobId} (${fnName}): ${errorForDisplay}`
)
);
}
return resolve(result);
};
function MessageReceiver(username, password, signalingKey, options = {}) { function MessageReceiver(username, password, signalingKey, options = {}) {
this.count = 0; this.count = 0;

@ -54,7 +54,6 @@
"blueimp-load-image": "^2.18.0", "blueimp-load-image": "^2.18.0",
"buffer-crc32": "^0.2.1", "buffer-crc32": "^0.2.1",
"bunyan": "^1.8.12", "bunyan": "^1.8.12",
"bytebuffer": "^5.0.1",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"config": "^1.28.1", "config": "^1.28.1",
"electron-editor-context-menu": "^1.1.1", "electron-editor-context-menu": "^1.1.1",

@ -1,6 +1,6 @@
/* global Whisper: false */ /* global Whisper: false */
/* global window: false */ /* global window: false */
const path = require('path');
const electron = require('electron'); const electron = require('electron');
const semver = require('semver'); const semver = require('semver');
@ -267,6 +267,10 @@ window.LokiAPI = new LokiServer({
}); });
window.mnemonic = require('./libloki/mnemonic'); window.mnemonic = require('./libloki/mnemonic');
const { WorkerInterface } = require('./js/modules/util_worker_interface');
const worker = new WorkerInterface(path.join(app.getAppPath(), 'js', 'util_worker.js'));
window.callWorker = (fnName, ...args) => worker.callWorker(fnName, ...args);
// Linux seems to periodically let the event loop stop, so this is a global workaround // Linux seems to periodically let the event loop stop, so this is a global workaround
setInterval(() => { setInterval(() => {

@ -385,7 +385,7 @@
<script type='text/javascript' src='../js/views/conversation_list_item_view.js' data-cover></script> <script type='text/javascript' src='../js/views/conversation_list_item_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/conversation_list_view.js' data-cover></script> <script type='text/javascript' src='../js/views/conversation_list_view.js' data-cover></script>
<script type='text/javascript' src='../js/views/contact_list_view.js' data-cover></script> <script type='text/javascript' src='../js/views/contact_list_view.js' data-cover></script>
<script type='text/javascript' src='js/views/main_header_view.js'></script> <script type='text/javascript' src='../js/views/main_header_view.js'></script>
<script type='text/javascript' src='../js/views/new_group_update_view.js' data-cover></script> <script type='text/javascript' src='../js/views/new_group_update_view.js' data-cover></script>
<script type="text/javascript" src="../js/views/group_update_view.js"></script> <script type="text/javascript" src="../js/views/group_update_view.js"></script>
<script type='text/javascript' src='../js/views/attachment_view.js' data-cover></script> <script type='text/javascript' src='../js/views/attachment_view.js' data-cover></script>

@ -1432,13 +1432,6 @@ bunyan@^1.8.12:
mv "~2" mv "~2"
safe-json-stringify "~1" safe-json-stringify "~1"
bytebuffer@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd"
integrity sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=
dependencies:
long "~3"
bytes@1: bytes@1:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8"
@ -5932,11 +5925,6 @@ long@^4.0.0:
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
long@~3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
integrity sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=
longest-streak@^2.0.1: longest-streak@^2.0.1:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e"

Loading…
Cancel
Save