get bcoin working in the browser again.

This commit is contained in:
Christopher Jeffrey 2016-02-08 18:06:39 -08:00
parent 8fd883b6c6
commit 72b7adc800
7 changed files with 188 additions and 63 deletions

View File

@ -10,16 +10,41 @@ var bn = require('bn.js');
var hash = require('hash.js');
var async = require('async');
bcoin.isBrowser =
(typeof process !== 'undefined' && process.browser)
|| typeof window !== 'undefined';
if (process.env.BCOIN_DEBUG) {
bcoin.debug = process.env.BCOIN_DEBUG;
if (bcoin.debug === '0' || bcoin.debug === '1')
bcoin.debug = +bcoin.debug === 1;
}
if (!bcoin.isBrowser) {
bcoin.fs = require('f' + 's');
bcoin.crypto = require('cry' + 'pto');
bcoin.net = require('n' + 'et');
}
bcoin.elliptic = elliptic;
bcoin.bn = bn;
bcoin.hash = hash;
bcoin.async = async;
bcoin.ecdsa = elliptic.ec('secp256k1');
if (bcoin.ecdsa.signature)
throw new Error;
if (bcoin.ecdsa.keypair)
throw new Error;
bcoin.ecdsa.signature = require('elliptic/lib/elliptic/ec/signature');
bcoin.ecdsa.keypair = require('elliptic/lib/elliptic/ec/key');
bcoin.utils = require('./bcoin/utils');
bcoin.bloom = require('./bcoin/bloom');
bcoin.protocol = require('./bcoin/protocol');
bcoin.bloom = require('./bcoin/bloom');
bcoin.script = require('./bcoin/script');
bcoin.input = require('./bcoin/input');
bcoin.output = require('./bcoin/output');
@ -27,6 +52,7 @@ bcoin.coin = require('./bcoin/coin');
bcoin.tx = require('./bcoin/tx');
bcoin.txPool = require('./bcoin/tx-pool');
bcoin.block = require('./bcoin/block');
bcoin.ramdisk = require('./bcoin/ramdisk');
bcoin.chain = require('./bcoin/chain');
bcoin.keypair = require('./bcoin/keypair');
bcoin.address = require('./bcoin/address');
@ -37,12 +63,3 @@ bcoin.hd = require('./bcoin/hd');
bcoin.miner = require('./bcoin/miner');
bcoin.protocol.network.set(process.env.BCOIN_NETWORK || 'main');
bcoin.bn = bn;
bcoin.elliptic = elliptic;
bcoin.utils.assert(!bcoin.ecdsa.signature);
bcoin.ecdsa.signature = require('elliptic/lib/elliptic/ec/signature');
bcoin.utils.assert(!bcoin.ecdsa.keypair);
bcoin.ecdsa.keypair = require('elliptic/lib/elliptic/ec/key');
bcoin.hash = hash;
bcoin.async = async;

View File

@ -9,11 +9,11 @@ var EventEmitter = require('events').EventEmitter;
var bcoin = require('../bcoin');
var bn = require('bn.js');
var fs = require('fs');
var constants = bcoin.protocol.constants;
var network = bcoin.protocol.network;
var utils = bcoin.utils;
var assert = utils.assert;
var fs = bcoin.fs;
/**
* Chain
@ -764,6 +764,12 @@ function ChainDB(chain, options) {
}
ChainDB.prototype._init = function _init() {
if (!bcoin.fs) {
utils.debug('`fs` module not available. Falling back to ramdisk.');
this.ramdisk = bcoin.ramdisk(new Buffer([]), 40 * 1024 * 1024);
return;
}
if (+process.env.BCOIN_FRESH === 1) {
try {
fs.unlinkSync(this.file);
@ -1054,6 +1060,9 @@ ChainDB.prototype._readSync = function _readSync(size, offset) {
if (offset < 0 || offset == null)
return;
if (!bcoin.fs)
return this.ramdisk.read(size, offset);
data = this._malloc(size);
try {
@ -1081,8 +1090,13 @@ ChainDB.prototype._readAsync = function _readAsync(size, offset, callback) {
var index = 0;
var data, bytes;
callback = utils.asyncify(callback);
if (offset < 0 || offset == null)
return false;
return callback();
if (!bcoin.fs)
return callback(null, this.ramdisk.read(size, offset));
data = this._malloc(size);
@ -1116,6 +1130,12 @@ ChainDB.prototype._writeSync = function _writeSync(data, offset) {
if (offset < 0 || offset == null)
return false;
if (!bcoin.fs) {
this.size += added;
this.ramdisk.write(data, offset);
return;
}
try {
while (bytes = fs.writeSync(this.fd, data, index, size, offset)) {
index += bytes;
@ -1139,10 +1159,18 @@ ChainDB.prototype._writeAsync = function _writeAsync(data, offset, callback) {
var size = data.length;
var index = 0;
if (offset < 0 || offset == null)
return false;
callback = utils.asyncify(callback);
self.size += added;
if (offset < 0 || offset == null)
return callback(null, false);
if (!bcoin.fs) {
this.size += added;
this.ramdisk.write(data, offset);
return callback(null, true);
}
this.size += added;
(function next() {
fs.write(self.fd, data, index, size, offset, function(err, bytes) {

View File

@ -558,7 +558,7 @@ HDPrivateKey.prototype._seed = function _seed(seed) {
throw new Error('entropy not in range');
}
var hash = sha512hmac(seed, 'Bitcoin seed');
var hash = utils.sha512hmac(seed, 'Bitcoin seed');
return {
version: null,
@ -671,7 +671,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
? [0].concat(this.privateKey).concat(array32(index))
: data = [].concat(this.publicKey).concat(array32(index));
hash = sha512hmac(data, this.chainCode);
hash = utils.sha512hmac(data, this.chainCode);
leftPart = new bn(hash.slice(0, 32));
chainCode = hash.slice(32, 64);
@ -973,7 +973,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
throw new Error('invalid path');
data = [].concat(this.publicKey).concat(array32(index));
hash = sha512hmac(data, this.chainCode);
hash = utils.sha512hmac(data, this.chainCode);
leftPart = new bn(hash.slice(0, 32));
chainCode = hash.slice(32, 64);
@ -1077,20 +1077,6 @@ HDPrivateKey.fromSecret = function fromSecret(privateKey) {
* Helpers
*/
var isBrowser = (typeof process !== 'undefined' && process.browser)
|| typeof window !== 'undefined';
function sha512hmac(data, salt) {
if (isBrowser) {
var hmac = hash.hmac(hash.sha512, utils.toArray(salt));
return hmac.update(utils.toArray(data)).digest();
}
var crypto = require('crypto');
var hmac = crypto.createHmac('sha512', new Buffer(salt));
var h = hmac.update(new Buffer(data)).digest();
return Array.prototype.slice.call(h);
}
function array32(data) {
var b = [];
utils.writeU32BE(b, data, 0);
@ -1141,12 +1127,12 @@ function pbkdf2(key, salt, iterations, dkLen) {
block1[salt.length + 2] = i >> 8 & 0xff;
block1[salt.length + 3] = i >> 0 & 0xff;
U = sha512hmac(block1, key);
U = utils.sha512hmac(block1, key);
utils.copy(U.slice(0, hLen), T, 0);
for (j = 1; j < iterations; j++) {
U = sha512hmac(U, key);
U = utils.sha512hmac(U, key);
for (k = 0; k < hLen; k++)
T[k] ^= U[k];

View File

@ -13,8 +13,6 @@ var bn = require('bn.js');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
var crypto = require('crypto');
/**
* Miner
*/

View File

@ -236,6 +236,11 @@ Pool.prototype._init = function _init() {
}
};
Pool.prototype.startServer = function startServer() {
bcoin.net.createServer(function(socket) {
});
};
Pool.prototype._startTimer = function _startTimer() {
var self = this;
@ -309,8 +314,9 @@ Pool.prototype.createConnection = function createConnection(peer, options) {
if (this._createSocket) {
socket = this._createSocket(addr.port, addr.host);
} else {
net = require('net');
socket = net.connect(addr.port, addr.host);
if (!bcoin.net)
throw new Error('Please include a `createSocket` callback.');
socket = bcoin.net.connect(addr.port, addr.host);
}
utils.debug(
@ -719,13 +725,14 @@ Pool.prototype.loadMempool = function loadMempool() {
});
};
Pool.prototype._createPeer = function _createPeer(priority) {
Pool.prototype._createPeer = function _createPeer(priority, socket) {
var self = this;
var peer = new bcoin.peer(this, this.createConnection, {
startHeight: this.options.startHeight,
relay: this.options.relay,
priority: priority
priority: priority,
socket: socket
});
peer.on('error', function(err) {
@ -801,23 +808,30 @@ Pool.prototype._handleTX = function _handleTX(tx, peer) {
this.emit('watched', tx, peer);
};
Pool.prototype._addPeer = function _addPeer() {
Pool.prototype._addPeer = function _addPeer(socket) {
var self = this;
var peer;
if (this.destroyed)
return;
if (!socket) {
if (this.destroyed)
return;
if (this.peers.block.length + this.peers.pending.length >= this.size)
return;
if (this.peers.block.length + this.peers.pending.length >= this.size)
return;
if (!this.getSeed()) {
setTimeout(this._addPeer.bind(this), 5000);
return;
if (!this.getSeed()) {
setTimeout(this._addPeer.bind(this), 5000);
return;
}
peer = this._createPeer(false);
} else {
if (this.destroyed)
return socket.destroy();
peer = this._createPeer(false, socket);
}
peer = this._createPeer(false);
this.peers.pending.push(peer);
this.peers.all.push(peer);

54
lib/bcoin/ramdisk.js Normal file
View File

@ -0,0 +1,54 @@
function Ramdisk(fileData, size) {
if (!(this instanceof Ramdisk))
return new Ramdisk(fileData, size);
if (size < fileData.length)
size = fileData.length + (fileData.length / 2 | 0);
this.size = fileData.length;
this.heap = new Buffer(size);
fileData.copy(this.heap, 0, 0, fileData.length);
}
Ramdisk.prototype.brk = function brk() {
var heap = new Buffer(this.heap.length + (this.heap.length / 2 | 0));
utils.debug('brk1(%d, %d)', this.heap.length, heap.length);
this.heap.copy(heap, 0, 0, this.heap.length);
utils.debug('brk2(%d, %d)', this.heap.length, heap.length);
this.heap = heap;
};
Ramdisk.prototype.write = function write(data, offset) {
var added = Math.max(0, (offset + data.length) - this.size);
while (offset + data.length > this.heap.length)
this.brk();
data.copy(this.heap, offset, 0, data.length);
this.size += added;
return data.length;
};
Ramdisk.prototype.truncate = function truncate(size) {
assert(size <= this.size);
this.size = size;
};
Ramdisk.prototype.read = function read(size, offset) {
var data, ret;
if (offset + size > this.size)
return;
data = this.heap.slice(offset, offset + size);
ret = new Buffer(size);
data.copy(ret, 0, 0, data.length);
return ret;
};
module.exports = Ramdisk;

View File

@ -10,7 +10,6 @@ var bcoin = require('../bcoin');
var bn = require('bn.js');
var hash = require('hash.js');
var util = require('util');
var crypto = require('crypto');
/**
* Utils
@ -151,21 +150,31 @@ utils.isBase58 = function isBase58(msg) {
};
utils.ripemd160 = function ripemd160(data, enc) {
// return hash.ripemd160().update(data, enc).digest();
var hash;
var result;
if (!bcoin.crypto)
return hash.ripemd160().update(data, enc).digest();
if (Array.isArray(data))
data = new Buffer(data);
hash = crypto.createHash('ripemd160').update(data, enc).digest();
return utils.toArray(hash);
result = bcoin.crypto.createHash('ripemd160').update(data, enc).digest();
return utils.toArray(result);
};
utils.sha1 = function sha1(data, enc) {
// return hash.sha1().update(data, enc).digest();
var hash;
var result;
if (!bcoin.crypto)
return hash.sha1().update(data, enc).digest();
if (Array.isArray(data))
data = new Buffer(data);
hash = crypto.createHash('sha1').update(data, enc).digest();
return utils.toArray(hash);
result = bcoin.crypto.createHash('sha1').update(data, enc).digest();
return utils.toArray(result);
};
utils.ripesha = function ripesha(data, enc) {
@ -177,18 +186,37 @@ utils.checksum = function checksum(data, enc) {
};
utils.sha256 = function sha256(data, enc) {
// return hash.sha256().update(data, enc).digest();
var hash;
var result;
if (!bcoin.crypto)
return hash.sha256().update(data, enc).digest();
if (Array.isArray(data))
data = new Buffer(data);
hash = crypto.createHash('sha256').update(data, enc).digest();
return utils.toArray(hash);
result = bcoin.crypto.createHash('sha256').update(data, enc).digest();
return utils.toArray(result);
};
utils.dsha256 = function dsha256(data, enc) {
return utils.sha256(utils.sha256(data, enc));
};
utils.sha512hmac = function sha512hmac(data, salt) {
var hmac, result;
if (!bcoin.crypto) {
hmac = hash.hmac(hash.sha512, utils.toArray(salt));
return hmac.update(utils.toArray(data)).digest();
}
hmac = bcoin.crypto.createHmac('sha512', new Buffer(salt));
result = hmac.update(new Buffer(data)).digest();
return utils.toArray(result);
};
utils.writeAscii = function writeAscii(dst, str, off) {
var i = 0;
var c;