Cleaned up newNonce stuff. Now doing target calculation with BigIntegers

pull/21/head
Beaudan 7 years ago
parent 7f12746d8c
commit 4598fd222a

@ -30,7 +30,7 @@ function initialize({ url }) {
timestamp, timestamp,
ttl, ttl,
pubKey, pubKey,
data, data: Array.from(data),
}); });
// Handle child process error (should never happen) // Handle child process error (should never happen)

@ -1,19 +1,22 @@
const hash = require('js-sha512'); const hash = require('js-sha512');
const bb = require('bytebuffer'); const bb = require('bytebuffer');
const BigInteger = require('jsbn').BigInteger;
const NONCE_LEN = 8; const NONCE_LEN = 8;
// Modify this value for difficulty scaling
const NONCE_TRIALS = 1000;
// Increment Uint8Array nonce by 1 with carrying // Increment Uint8Array nonce by 1 with carrying
function incrementNonce(nonce) { function incrementNonce(nonce) {
let idx = NONCE_LEN - 1; let idx = NONCE_LEN - 1;
const newNonce = nonce; const newNonce = new Uint8Array(nonce);
newNonce[idx] += 1; newNonce[idx] += 1;
// Nonce will just reset to 0 if all values are 255 causing infinite loop // Nonce will just reset to 0 if all values are 255 causing infinite loop
while (nonce[idx] === 0 && idx > 0) { while (newNonce[idx] === 0 && idx > 0) {
idx -= 1; idx -= 1;
newNonce[idx] += 1; newNonce[idx] += 1;
} }
return nonce; return newNonce;
} }
// Convert a Uint8Array to a base64 string // Convert a Uint8Array to a base64 string
@ -25,27 +28,27 @@ function bufferToBase64(buf) {
return bb.btoa(binaryString); return bb.btoa(binaryString);
} }
// Convert javascript number to Uint8Array of length 8 // Convert BigInteger to Uint8Array of length NONCE_LEN
function numberToUintArr(numberVal) { function 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
arr[idx] = (numberVal / 256**n) % 256; // (bigInt / 256**n) % 256;
const uint8Val = (bigInt.divide((new BigInteger('256')).pow(n))).mod(new BigInteger('256'));
arr[idx] = uint8Val.intValue();
} }
return arr; return arr;
} }
// Compare two Uint8Arrays, return true if arr1 is > arr2 // Compare two Uint8Arrays, return true if arr1 is > arr2
function compareUint8Arrays(arr1, arr2) { function 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) if (arr1.length !== arr2.length)
return false; return false;
const len = arr1.length for (let i = 0, len = arr1.length; i < len; i += 1) {
for (let i = 0; i < len; i += 1) {
if (arr1[i] > arr2[i]) if (arr1[i] > arr2[i])
return true; return true;
if (arr1[i] < arr2[i]) if (arr1[i] < arr2[i])
@ -63,40 +66,39 @@ function calcPoW(timestamp, ttl, pubKey, data) {
const payload = new Uint8Array(leadingArray.length + data.length); const payload = new Uint8Array(leadingArray.length + data.length);
payload.set(leadingArray); payload.set(leadingArray);
payload.set(data, leadingArray.length); payload.set(data, leadingArray.length);
// Modify this value for difficulty scaling
const nonceTrialsPerByte = 1000; // payloadLength + NONCE_LEN
const totalLen = (new BigInteger(payload.length.toString())).add(new BigInteger(NONCE_LEN.toString()));
// ttl * totalLen
const ttlMult = (new BigInteger(ttl.toString())).multiply(totalLen);
// ttlMult / (2^16 - 1)
const innerFrac = ttlMult.divide((new BigInteger('2').pow(16)).subtract(new BigInteger('1')));
// totalLen + innerFrac
const lenPlusInnerFrac = totalLen.add(innerFrac);
// NONCE_TRIALS * lenPlusInnerFrac
const denominator = (new BigInteger(NONCE_TRIALS.toString())).multiply(lenPlusInnerFrac);
// 2^64 - 1
const two64 = (new BigInteger('2').pow(64)).subtract(new BigInteger('1'));
// two64 / denominator
const targetNum = two64.divide(denominator);
const target = bigIntToUint8Array(targetNum);
let nonce = new Uint8Array(NONCE_LEN); let nonce = new Uint8Array(NONCE_LEN);
let trialValue = numberToUintArr(Number.MAX_SAFE_INTEGER); let trialValue = bigIntToUint8Array(new BigInteger(Number.MAX_SAFE_INTEGER.toString()));
// Target is converted to Uint8Array for simple comparison with trialValue
const targetNum = Math.floor(2**64 / (
nonceTrialsPerByte * (
payload.length + NONCE_LEN + (
(ttl * ( payload.length + NONCE_LEN )) /
2**16
)
)
));
const target = numberToUintArr(targetNum);
const initialHash = new Uint8Array(bb.wrap(hash(payload), 'hex').toArrayBuffer()); const initialHash = new Uint8Array(bb.wrap(hash(payload), 'hex').toArrayBuffer());
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 (compareUint8Arrays(trialValue, target)) { while (greaterThan(trialValue, target)) {
nonce = incrementNonce(nonce); nonce = incrementNonce(nonce);
innerPayload.set(nonce); innerPayload.set(nonce);
resultHash = hash(innerPayload); resultHash = hash(innerPayload);
trialValue = (new Uint8Array(bb.wrap(resultHash, 'hex').toArrayBuffer())).slice(0, 8); trialValue = (new Uint8Array(bb.wrap(resultHash, 'hex').toArrayBuffer())).slice(0, NONCE_LEN);
} }
return bufferToBase64(nonce); return bufferToBase64(nonce);
} }
// Start calculation in child process when main process sends message data // Start calculation in child process when main process sends message data
process.on('message', (msg) => { process.on('message', (msg) => {
// Convert data back to Uint8Array after IPC has serialised to JSON process.send({nonce: calcPoW(msg.timestamp, msg.ttl, msg.pubKey, new Uint8Array(msg.data))});
const msgLen = Object.keys(msg.data).length;
const msgData = new Uint8Array(msgLen);
for (let i = 0; i < msgLen; i += 1) {
msgData[i] = msg.data[i];
}
process.send({nonce: calcPoW(msg.timestamp, msg.ttl, msg.pubKey, msgData)});
}); });

Loading…
Cancel
Save