perf: start using bcoin-native.
This commit is contained in:
parent
27ba246027
commit
7f31a41e84
@ -7,6 +7,7 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var native = require('../utils/native');
|
||||
|
||||
var BIG_ENDIAN = new Int8Array(Int16Array.of(1).buffer)[0] === 0;
|
||||
|
||||
@ -176,6 +177,9 @@ ChaCha20.prototype.getCounter = function getCounter() {
|
||||
return lo;
|
||||
};
|
||||
|
||||
if (native)
|
||||
ChaCha20 = native.ChaCha20;
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
@ -489,6 +493,9 @@ Poly1305.verify = function verify(mac1, mac2) {
|
||||
return (dif & 1) !== 0;
|
||||
};
|
||||
|
||||
if (native)
|
||||
Poly1305 = native.Poly1305;
|
||||
|
||||
/**
|
||||
* AEAD (used for bip151)
|
||||
* @exports AEAD
|
||||
@ -527,7 +534,7 @@ AEAD.prototype.init = function init(key, iv) {
|
||||
this.chacha20.encrypt(new Buffer(32));
|
||||
|
||||
// Counter should be one.
|
||||
assert(this.chacha20.state[12] === 1);
|
||||
assert(this.chacha20.getCounter() === 1);
|
||||
|
||||
// Expose for debugging.
|
||||
this.polyKey = polyKey;
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
var assert = require('assert');
|
||||
var random = require('./random');
|
||||
var native = require('../utils/native');
|
||||
var nativeCrypto, supersha, hash, aes;
|
||||
|
||||
var isBrowser =
|
||||
@ -17,11 +18,6 @@ var isBrowser =
|
||||
|
||||
if (!isBrowser) {
|
||||
nativeCrypto = require('crypto');
|
||||
try {
|
||||
supersha = require('supersha');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
} else {
|
||||
hash = require('hash.js');
|
||||
aes = require('./aes');
|
||||
@ -47,6 +43,9 @@ crypto.hash = function _hash(alg, data) {
|
||||
return nativeCrypto.createHash(alg).update(data).digest();
|
||||
};
|
||||
|
||||
if (native)
|
||||
crypto.hash = native.hash;
|
||||
|
||||
/**
|
||||
* Hash with ripemd160.
|
||||
* @param {Buffer} data
|
||||
@ -74,11 +73,12 @@ crypto.sha1 = function sha1(data) {
|
||||
*/
|
||||
|
||||
crypto.sha256 = function sha256(data) {
|
||||
if (supersha)
|
||||
return supersha.sha256(data);
|
||||
return crypto.hash('sha256', data);
|
||||
};
|
||||
|
||||
if (native)
|
||||
crypto.sha256 = native.sha256;
|
||||
|
||||
/**
|
||||
* Hash with sha256 and ripemd160 (OP_HASH160).
|
||||
* @param {Buffer} data
|
||||
@ -89,6 +89,9 @@ crypto.hash160 = function hash160(data) {
|
||||
return crypto.ripemd160(crypto.sha256(data));
|
||||
};
|
||||
|
||||
if (native)
|
||||
crypto.hash160 = native.hash160;
|
||||
|
||||
/**
|
||||
* Hash with sha256 twice (OP_HASH256).
|
||||
* @param {Buffer} data
|
||||
@ -96,11 +99,12 @@ crypto.hash160 = function hash160(data) {
|
||||
*/
|
||||
|
||||
crypto.hash256 = function hash256(data) {
|
||||
if (supersha)
|
||||
return supersha.hash256(data);
|
||||
return crypto.sha256(crypto.sha256(data));
|
||||
};
|
||||
|
||||
if (native)
|
||||
crypto.hash256 = native.hash256;
|
||||
|
||||
/**
|
||||
* Create a sha256 checksum (common in bitcoin).
|
||||
* @param {Buffer} data
|
||||
@ -122,6 +126,14 @@ crypto.checksum = function checksum(data) {
|
||||
crypto.hmac = function hmac(alg, data, salt) {
|
||||
var hmac;
|
||||
|
||||
if (native) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, 'utf8');
|
||||
if (typeof salt === 'string')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
return native.hmac(alg, data, salt);
|
||||
}
|
||||
|
||||
if (!nativeCrypto) {
|
||||
hmac = hash.hmac(hash[alg], salt);
|
||||
return new Buffer(hmac.update(data).digest());
|
||||
@ -472,6 +484,9 @@ crypto.buildMerkleTree = function buildMerkleTree(leaves) {
|
||||
return tree;
|
||||
};
|
||||
|
||||
if (native)
|
||||
crypto.buildMerkleTree = native.buildMerkleTree;
|
||||
|
||||
/**
|
||||
* Calculate merkle root from leaves.
|
||||
* @param {Buffer[]} leaves
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('./crypto');
|
||||
var native = require('../utils/native');
|
||||
var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
|
||||
|
||||
/**
|
||||
* Javascript scrypt implementation. Scrypt is
|
||||
@ -58,6 +60,9 @@ function scrypt(passwd, salt, N, r, p, len, callback) {
|
||||
if (typeof salt === 'string')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
|
||||
if (native)
|
||||
return native.scryptAsync(passwd, salt, N, r, p, len, callback);
|
||||
|
||||
if (r * p >= (1 << 30))
|
||||
return callback(new Error('EFBIG'));
|
||||
|
||||
@ -86,8 +91,8 @@ function scrypt(passwd, salt, N, r, p, len, callback) {
|
||||
}
|
||||
|
||||
function salsa20_8(B) {
|
||||
var B32 = new Array(16);
|
||||
var x = new Array(16);
|
||||
var B32 = new U32Array(16);
|
||||
var x = new U32Array(16);
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
'use strict';
|
||||
|
||||
var crypto = require('./crypto');
|
||||
var native = require('../utils/native');
|
||||
var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array;
|
||||
|
||||
/**
|
||||
* Javascript scrypt implementation. Scrypt is
|
||||
@ -57,6 +59,9 @@ function scrypt(passwd, salt, N, r, p, len) {
|
||||
if (typeof salt === 'string')
|
||||
salt = new Buffer(salt, 'utf8');
|
||||
|
||||
if (native)
|
||||
return native.scrypt(passwd, salt, N, r, p, len);
|
||||
|
||||
if (r * p >= (1 << 30))
|
||||
throw new Error('EFBIG');
|
||||
|
||||
@ -78,8 +83,8 @@ function scrypt(passwd, salt, N, r, p, len) {
|
||||
}
|
||||
|
||||
function salsa20_8(B) {
|
||||
var B32 = new Array(16);
|
||||
var x = new Array(16);
|
||||
var B32 = new U32Array(16);
|
||||
var x = new U32Array(16);
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var native = require('../utils/native');
|
||||
|
||||
/**
|
||||
* Javascript siphash implementation. Used for compact block relay.
|
||||
* @param {Buffer} data
|
||||
@ -16,16 +18,17 @@
|
||||
* @returns {Buffer} uint64le
|
||||
*/
|
||||
|
||||
function siphash(data, key) {
|
||||
var blocks = Math.ceil(data.length / 8);
|
||||
function siphash24(data, key, shift) {
|
||||
var blocks = Math.floor(data.length / 8);
|
||||
var c0 = U64(0x736f6d65, 0x70736575);
|
||||
var c1 = U64(0x646f7261, 0x6e646f6d);
|
||||
var c2 = U64(0x6c796765, 0x6e657261);
|
||||
var c3 = U64(0x74656462, 0x79746573);
|
||||
var f0 = U64(blocks << 27, 0);
|
||||
var f0 = U64(blocks << (shift - 32), 0);
|
||||
var f1 = U64(0, 0xff);
|
||||
var k0 = U64.fromRaw(key, 0);
|
||||
var k1 = U64.fromRaw(key, 8);
|
||||
var p = 0;
|
||||
var i, d, v0, v1, v2, v3;
|
||||
|
||||
// Init
|
||||
@ -36,13 +39,38 @@ function siphash(data, key) {
|
||||
|
||||
// Blocks
|
||||
for (i = 0; i < blocks; i++) {
|
||||
d = U64.fromRaw(data, i * 8);
|
||||
d = U64.fromRaw(data, p);
|
||||
p += 8;
|
||||
v3.xor(d);
|
||||
sipround(v0, v1, v2, v3);
|
||||
sipround(v0, v1, v2, v3);
|
||||
v0.xor(d);
|
||||
}
|
||||
|
||||
switch (data.length & 7) {
|
||||
case 7:
|
||||
f0.hi |= data[p + 6] << 16;
|
||||
case 6:
|
||||
f0.hi |= data[p + 5] << 8;
|
||||
case 5:
|
||||
f0.hi |= data[p + 4] << 0;
|
||||
case 4:
|
||||
f0.lo |= data[p + 3] << 24;
|
||||
case 3:
|
||||
f0.lo |= data[p + 2] << 16;
|
||||
case 2:
|
||||
f0.lo |= data[p + 1] << 8;
|
||||
case 1:
|
||||
f0.lo |= data[p + 0] << 0;
|
||||
if (f0.lo < 0)
|
||||
f0.lo += 0x100000000;
|
||||
if (f0.hi < 0)
|
||||
f0.hi += 0x100000000;
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
// Finalization
|
||||
v3.xor(f0);
|
||||
sipround(v0, v1, v2, v3);
|
||||
@ -82,6 +110,19 @@ function sipround(v0, v1, v2, v3) {
|
||||
v2.rotl(32);
|
||||
}
|
||||
|
||||
function siphash(data, key) {
|
||||
return siphash24(data, key, 56);
|
||||
}
|
||||
|
||||
function siphash256(data, key) {
|
||||
return siphash24(data, key, 59);
|
||||
}
|
||||
|
||||
if (native) {
|
||||
siphash = native.siphash;
|
||||
siphash256 = native.siphash256;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
@ -186,7 +227,9 @@ U64.fromRaw = function fromRaw(data, off) {
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports = siphash;
|
||||
exports = siphash256;
|
||||
exports.siphash = siphash;
|
||||
exports.siphash256 = siphash256;
|
||||
exports.U64 = U64;
|
||||
|
||||
module.exports = exports;
|
||||
|
||||
@ -11,6 +11,9 @@ var constants = require('../protocol/constants');
|
||||
var assert = require('assert');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var murmur3 = require('../utils/murmur3');
|
||||
var sum32 = murmur3.sum32;
|
||||
var mul32 = murmur3.mul32;
|
||||
|
||||
/*
|
||||
* Constants
|
||||
@ -408,94 +411,10 @@ RollingFilter.prototype.added = function added(val, enc) {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Murmur3 hash.
|
||||
* @memberof Bloom
|
||||
* @param {Buffer} data
|
||||
* @param {Number} seed
|
||||
* @returns {Number}
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function murmur3(data, seed) {
|
||||
var tail = data.length - (data.length % 4);
|
||||
var c1 = 0xcc9e2d51;
|
||||
var c2 = 0x1b873593;
|
||||
var h1 = seed;
|
||||
var i, k1;
|
||||
|
||||
for (i = 0; i < tail; i += 4) {
|
||||
k1 = (data[i + 3] << 24)
|
||||
| (data[i + 2] << 16)
|
||||
| (data[i + 1] << 8)
|
||||
| data[i];
|
||||
k1 = mul32(k1, c1);
|
||||
k1 = rotl32(k1, 15);
|
||||
k1 = mul32(k1, c2);
|
||||
h1 ^= k1;
|
||||
h1 = rotl32(h1, 13);
|
||||
h1 = sum32(mul32(h1, 5), 0xe6546b64);
|
||||
}
|
||||
|
||||
k1 = 0;
|
||||
switch (data.length & 3) {
|
||||
case 3:
|
||||
k1 ^= data[tail + 2] << 16;
|
||||
case 2:
|
||||
k1 ^= data[tail + 1] << 8;
|
||||
case 1:
|
||||
k1 ^= data[tail + 0];
|
||||
k1 = mul32(k1, c1);
|
||||
k1 = rotl32(k1, 15);
|
||||
k1 = mul32(k1, c2);
|
||||
h1 ^= k1;
|
||||
}
|
||||
|
||||
h1 ^= data.length;
|
||||
h1 ^= h1 >>> 16;
|
||||
h1 = mul32(h1, 0x85ebca6b);
|
||||
h1 ^= h1 >>> 13;
|
||||
h1 = mul32(h1, 0xc2b2ae35);
|
||||
h1 ^= h1 >>> 16;
|
||||
|
||||
if (h1 < 0)
|
||||
h1 += 0x100000000;
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
function mul32(a, b) {
|
||||
var alo = a & 0xffff;
|
||||
var blo = b & 0xffff;
|
||||
var ahi = a >>> 16;
|
||||
var bhi = b >>> 16;
|
||||
var r, lo, hi;
|
||||
|
||||
lo = alo * blo;
|
||||
hi = (ahi * blo + bhi * alo) & 0xffff;
|
||||
|
||||
hi += lo >>> 16;
|
||||
lo &= 0xffff;
|
||||
r = (hi << 16) | lo;
|
||||
|
||||
if (r < 0)
|
||||
r += 0x100000000;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
function sum32(a, b) {
|
||||
var r = (a + b) & 0xffffffff;
|
||||
|
||||
if (r < 0)
|
||||
r += 0x100000000;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
function rotl32(w, b) {
|
||||
return (w << b) | (w >>> (32 - b));
|
||||
}
|
||||
|
||||
function read(data, off) {
|
||||
return {
|
||||
hi: data.readUInt32LE(off + 4, true),
|
||||
|
||||
112
lib/utils/murmur3.js
Normal file
112
lib/utils/murmur3.js
Normal file
@ -0,0 +1,112 @@
|
||||
/*!
|
||||
* murmur3.js - murmur3 hash for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var native = require('./native');
|
||||
|
||||
/**
|
||||
* Murmur3 hash.
|
||||
* @memberof Bloom
|
||||
* @param {Buffer} data
|
||||
* @param {Number} seed
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
function murmur3(data, seed) {
|
||||
var tail = data.length - (data.length % 4);
|
||||
var c1 = 0xcc9e2d51;
|
||||
var c2 = 0x1b873593;
|
||||
var h1 = seed;
|
||||
var i, k1;
|
||||
|
||||
for (i = 0; i < tail; i += 4) {
|
||||
k1 = (data[i + 3] << 24)
|
||||
| (data[i + 2] << 16)
|
||||
| (data[i + 1] << 8)
|
||||
| data[i];
|
||||
k1 = mul32(k1, c1);
|
||||
k1 = rotl32(k1, 15);
|
||||
k1 = mul32(k1, c2);
|
||||
h1 ^= k1;
|
||||
h1 = rotl32(h1, 13);
|
||||
h1 = sum32(mul32(h1, 5), 0xe6546b64);
|
||||
}
|
||||
|
||||
k1 = 0;
|
||||
switch (data.length & 3) {
|
||||
case 3:
|
||||
k1 ^= data[tail + 2] << 16;
|
||||
case 2:
|
||||
k1 ^= data[tail + 1] << 8;
|
||||
case 1:
|
||||
k1 ^= data[tail + 0];
|
||||
k1 = mul32(k1, c1);
|
||||
k1 = rotl32(k1, 15);
|
||||
k1 = mul32(k1, c2);
|
||||
h1 ^= k1;
|
||||
}
|
||||
|
||||
h1 ^= data.length;
|
||||
h1 ^= h1 >>> 16;
|
||||
h1 = mul32(h1, 0x85ebca6b);
|
||||
h1 ^= h1 >>> 13;
|
||||
h1 = mul32(h1, 0xc2b2ae35);
|
||||
h1 ^= h1 >>> 16;
|
||||
|
||||
if (h1 < 0)
|
||||
h1 += 0x100000000;
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
if (native)
|
||||
murmur3 = native.murmur3;
|
||||
|
||||
function mul32(a, b) {
|
||||
var alo = a & 0xffff;
|
||||
var blo = b & 0xffff;
|
||||
var ahi = a >>> 16;
|
||||
var bhi = b >>> 16;
|
||||
var r, lo, hi;
|
||||
|
||||
lo = alo * blo;
|
||||
hi = (ahi * blo + bhi * alo) & 0xffff;
|
||||
|
||||
hi += lo >>> 16;
|
||||
lo &= 0xffff;
|
||||
r = (hi << 16) | lo;
|
||||
|
||||
if (r < 0)
|
||||
r += 0x100000000;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
function sum32(a, b) {
|
||||
var r = (a + b) & 0xffffffff;
|
||||
|
||||
if (r < 0)
|
||||
r += 0x100000000;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
function rotl32(w, b) {
|
||||
return (w << b) | (w >>> (32 - b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
exports = murmur3;
|
||||
exports.murmur3 = murmur3;
|
||||
exports.mul32 = mul32;
|
||||
exports.sum32 = sum32;
|
||||
exports.rotl32 = rotl32;
|
||||
module.exports = exports;
|
||||
21
lib/utils/native.js
Normal file
21
lib/utils/native.js
Normal file
@ -0,0 +1,21 @@
|
||||
/*!
|
||||
* native.js - native bindings for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var isBrowser =
|
||||
(typeof process !== 'undefined' && process.browser)
|
||||
|| typeof window !== 'undefined';
|
||||
|
||||
module.exports = null;
|
||||
|
||||
if (!isBrowser && +process.env.BCOIN_NO_NATIVE !== 1) {
|
||||
try {
|
||||
module.exports = require('bcoin-native');
|
||||
} catch (e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,7 @@
|
||||
var utils = exports;
|
||||
|
||||
var assert = require('assert');
|
||||
var native = require('./native');
|
||||
var bn = require('bn.js');
|
||||
var util = require('util');
|
||||
var Number, Math, Date;
|
||||
@ -165,6 +166,9 @@ utils.toBase58 = function toBase58(data) {
|
||||
return str;
|
||||
};
|
||||
|
||||
if (native)
|
||||
utils.toBase58 = native.toBase58;
|
||||
|
||||
/**
|
||||
* Decode a base58 string.
|
||||
* @see https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp
|
||||
@ -217,6 +221,9 @@ utils.fromBase58 = function fromBase58(str) {
|
||||
return out;
|
||||
};
|
||||
|
||||
if (native)
|
||||
utils.fromBase58 = native.fromBase58;
|
||||
|
||||
/**
|
||||
* Test whether a string is base58 (note that you
|
||||
* may get a false positive on a hex string).
|
||||
|
||||
@ -40,11 +40,11 @@
|
||||
"elliptic": "6.3.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcoin-native": "0.0.2",
|
||||
"leveldown": "git://github.com/Level/leveldown.git#leveldb-1.19",
|
||||
"secp256k1": "3.2.0",
|
||||
"socket.io": "1.4.8",
|
||||
"socket.io-client": "1.4.8",
|
||||
"supersha": "0.0.1"
|
||||
"socket.io-client": "1.4.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "13.1.0",
|
||||
@ -67,7 +67,7 @@
|
||||
"child_process": "./browser/empty.js",
|
||||
"os": "./browser/empty.js",
|
||||
"net": "./browser/empty.js",
|
||||
"supersha": "./browser/empty.js",
|
||||
"bcoin-native": "./browser/empty.js",
|
||||
"secp256k1": "./browser/empty.js"
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ describe('ChaCha20 / Poly1305 / AEAD', function() {
|
||||
|
||||
var aead = new AEAD();
|
||||
aead.init(key, nonce);
|
||||
assert.equal(aead.chacha20.state[12], 1);
|
||||
assert.equal(aead.chacha20.getCounter(), 1);
|
||||
assert.deepEqual(aead.polyKey, pk);
|
||||
aead.aad(aad);
|
||||
var plainenc = new Buffer(plain);
|
||||
@ -60,7 +60,7 @@ describe('ChaCha20 / Poly1305 / AEAD', function() {
|
||||
|
||||
var aead = new AEAD();
|
||||
aead.init(key, nonce);
|
||||
assert.equal(aead.chacha20.state[12], 1);
|
||||
assert.equal(aead.chacha20.getCounter(), 1);
|
||||
assert.deepEqual(aead.polyKey, pk);
|
||||
aead.aad(aad);
|
||||
aead.decrypt(ciphertext);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user