diff --git a/browser/index.html b/browser/index.html index 89fa039f..4915fd27 100644 --- a/browser/index.html +++ b/browser/index.html @@ -121,47 +121,50 @@ more bitcoin magic). floating.style.display = 'block'; } - logger = { - debug: function(args) { - if (++scrollback > 1000) { - log.innerHTML = ''; - scrollback = 1; - } - var msg = utils.format(args, false); - log.innerHTML += '' + utils.now() + ' '; - log.innerHTML += escape(msg) + '\n'; - log.scrollTop = log.scrollHeight; - }, - error: function(err) { - if (++scrollback > 1000) { - log.innerHTML = ''; - scrollback = 1; - } - var msg = (err.message + '').replace(/^ *Error: */, ''); - log.innerHTML += '' + utils.now() + ' '; - log.innerHTML += '[Error] '; - log.innerHTML += escape(msg) + '\n'; - log.scrollTop = log.scrollHeight; + logger = new bcoin.logger({ level: 'debug' }); + logger.writeConsole = function(level, args) { + var msg = utils.format(args, false); + if (++scrollback > 1000) { + log.innerHTML = ''; + scrollback = 1; } + log.innerHTML += '' + utils.now() + ' '; + if (level === 'error') + log.innerHTML += '[' + level + '] '; + else + log.innerHTML += '[' + level + '] '; + log.innerHTML += escape(msg) + '\n'; + log.scrollTop = log.scrollHeight; }; send.onsubmit = function(ev) { var value = document.getElementById('amount').value; var address = document.getElementById('address').value; - value = utils.satoshi(value); - node.wallet.createTX({}, [{address: address,value:value}], function(err, tx) { + + var options = { + outputs: [{ + address: address, + value: utils.satoshi(value) + }] + }; + + node.wallet.createTX(options, function(err, tx) { if (err) - return bcoin.error(err); + return node.logger.error(err); + node.wallet.sign(tx, function(err) { if (err) - return bcoin.error(err); + return node.logger.error(err); + node.sendTX(tx, function(err) { if (err) - return bcoin.error(err); + return node.logger.error(err); + show(tx); }); }); }); + ev.preventDefault(); ev.stopPropagation(); return false; @@ -220,16 +223,16 @@ more bitcoin magic). function formatWallet(wallet) { var html = ''; - var key = wallet.master.toJSON(); + var key = wallet.master.toJSON().key; html += 'Wallet
'; - if (bcoin.networkType === 'segnet4') { + if (bcoin.network.get().type === 'segnet4') { html += 'Current Address (p2wpkh): ' + wallet.getAddress() + '
'; html += 'Current Address (p2wpkh behind p2sh): ' + wallet.getProgramAddress() + '
'; } else { html += 'Current Address: ' + wallet.getAddress() + '
'; } html += 'Extended Private Key: ' + key.xprivkey + '
'; - html += 'Mnemonic: ' + key.phrase + '
'; + html += 'Mnemonic: ' + key.mnemonic.phrase + '
'; wallet.getBalance(function(err, balance) { if (balance) { html += 'Confirmed Balance: ' + utils.btc(balance.confirmed) + '
'; @@ -271,21 +274,21 @@ more bitcoin magic). bcoin.set({ network: query.network || 'segnet4', - debug: true, - db: query.db || null, - logger: logger, useWorkers: true }); node = new bcoin.fullnode({ - prune: query.prune === 'true' || query.prune === '1' + prune: query.prune === 'true' || query.prune === '1', + logger: logger, + db: query.db || 'leveldb', + coinCache: true }); node.on('error', function(err) { - bcoin.error(err); + ; }); - node.on('block', addItem); + node.chain.on('block', addItem); node.mempool.on('tx', addItem); node.open(function(err) { diff --git a/browser/ldb.js b/browser/ldb.js new file mode 100644 index 00000000..81dd82f2 --- /dev/null +++ b/browser/ldb.js @@ -0,0 +1,120 @@ +var level = require('level-js'); + +function DB(file) { + this.level = new level(file); + this.bufferKeys = false; +} + +DB.prototype.open = function open(options, callback) { + this.level.open(options, callback); +}; + +DB.prototype.close = function close(callback) { + this.level.close(callback); +}; + +DB.prototype.get = function get(key, options, callback) { + if (this.bufferKeys && Buffer.isBuffer(key)) + key = key.toString('hex'); + this.level.get(key, options, callback); +}; + +DB.prototype.put = function get(key, value, options, callback) { + if (this.bufferKeys && Buffer.isBuffer(key)) + key = key.toString('hex'); + this.level.put(key, value, options, callback); +}; + +DB.prototype.del = function del(key, options, callback) { + if (this.bufferKeys && Buffer.isBuffer(key)) + key = key.toString('hex'); + this.level.del(key, options, callback); +}; + +DB.prototype.batch = function batch(ops, options, callback) { + if (!ops) + return new Batch(this); + return this.level.batch(ops, options, callback); +}; + +DB.prototype.iterator = function iterator(options) { + options.keyAsBuffer = false; + return new Iterator(this, options); +}; + +DB.prototype.approximateSize = function approximateSize(start, end, callback) { + return this.level.approximateSize(start, end, callback); +}; + +DB.prototype.getProperty = function getProperty(name) { + return this.level.getProperty(name); +}; + +function Batch(db) { + this.db = db; + this.batch = db.level.batch(); +} + +Batch.prototype.put = function(key, value) { + if (this.db.bufferKeys && Buffer.isBuffer(key)) + key = key.toString('hex'); + this.batch.put(key, value); + return this; +}; + +Batch.prototype.del = function del(key) { + if (this.db.bufferKeys && Buffer.isBuffer(key)) + key = key.toString('hex'); + this.batch.del(key); + return this; +}; + +Batch.prototype.write = function write(callback) { + this.batch.write(callback); + return this; +}; + +Batch.prototype.clear = function clear() { + this.batch.clear(); + return this; +}; + +function Iterator(db, options) { + this.db = db; + this.iter = db.level.iterator(options); +} + +Iterator.prototype.next = function(callback) { + var self = this; + this.iter.next(function(err, key, value) { + if (err) { + callback(err); + return; + } + + if (key === undefined) { + callback(err, key, value); + return; + } + + if (self.db.bufferKeys) + key = new Buffer(key, 'hex'); + + if (!Buffer.isBuffer(value)) + value = new Buffer(value.buffer); + + callback(err, key, value); + }); +}; + +Iterator.prototype.seek = function seek(key) { + if (this.db.bufferKeys && Buffer.isBuffer(key)) + key = key.toString('hex'); + this.iter.seek(key); +}; + +Iterator.prototype.end = function end(callback) { + this.iter.end(callback); +}; + +module.exports = DB; diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index 9ffe5be8..e9479699 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -35,9 +35,7 @@ var BufferReader = require('./reader'); */ var layout = { - R: !utils.isBrowser - ? new Buffer([0x52]) - : '52', + R: new Buffer([0x52]), e: function e(hash) { return pair(0x65, hash); }, @@ -84,9 +82,6 @@ var layout = { write(key, hash, 21); } - if (utils.isBrowser) - key = key.toString('hex'); - return key; }, C: function C(address, hash, index) { @@ -110,17 +105,11 @@ var layout = { key.writeUInt32LE(index, 53, true); } - if (utils.isBrowser) - key = key.toString('hex'); - return key; }, Cc: function Cc(key) { var hash, index; - if (utils.isBrowser) - key = new Buffer(key, 'hex'); - if (key.length === 69) { hash = key.slice(33, 65).toString('hex'); index = key.readUInt32LE(65, 0); @@ -132,9 +121,6 @@ var layout = { return [hash, index]; }, Tt: function Tt(key) { - if (utils.isBrowser) - key = new Buffer(key, 'hex'); - return key.length === 65 ? key.slice(33).toString('hex') : key.slice(21).toString('hex'); @@ -182,7 +168,8 @@ function ChainDB(chain, options) { db: this.options.db, compression: true, cacheSize: 16 << 20, - writeBufferSize: 8 << 20 + writeBufferSize: 8 << 20, + bufferKeys: true }); this.keepBlocks = options.keepBlocks || 288; @@ -1255,7 +1242,7 @@ ChainDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, call self.db.iterate({ gte: layout.C(address, constants.ZERO_HASH, 0), lte: layout.C(address, constants.MAX_HASH, 0xffffffff), - keyAsBuffer: !utils.isBrowser, + keyAsBuffer: true, transform: layout.Cc }, function(err, keys) { if (err) @@ -1303,7 +1290,7 @@ ChainDB.prototype.getTXByAddress = function getTXByAddress(addresses, callback) self.db.lookup({ gte: layout.T(address, constants.ZERO_HASH), lte: layout.T(address, constants.MAX_HASH), - keyAsBuffer: !utils.isBrowser, + keyAsBuffer: true, transform: function(key) { var hash = layout.Tt(key); @@ -1561,8 +1548,6 @@ function pair(prefix, hash) { var key = new Buffer(33); key[0] = prefix; write(key, hash, 1); - if (utils.isBrowser) - key = key.toString('hex'); return key; } @@ -1570,8 +1555,6 @@ function ipair(prefix, num) { var key = new Buffer(5); key[0] = prefix; key.writeUInt32LE(num, 1, true); - if (utils.isBrowser) - key = key.toString('hex'); return key; } diff --git a/lib/bcoin/ldb.js b/lib/bcoin/ldb.js index a4cf0705..61eb310e 100644 --- a/lib/bcoin/ldb.js +++ b/lib/bcoin/ldb.js @@ -51,6 +51,9 @@ function ldb(options) { mapSize: options.mapSize || 300 * (1024 << 20), writeMap: options.writeMap || false, + // For browser buffer keys + bufferKeys: options.bufferKeys, + db: options.db }); } @@ -113,7 +116,7 @@ ldb.parseOptions = function parseOptions(options) { if (backend.name === 'rbt') db = require('./rbt'); else if (utils.isBrowser) - db = require('level-js'); + db = require('../../browser/ldb'); else db = require(backend.name); diff --git a/lib/bcoin/lowlevelup.js b/lib/bcoin/lowlevelup.js index 3f6a9d56..d8c0e9e4 100644 --- a/lib/bcoin/lowlevelup.js +++ b/lib/bcoin/lowlevelup.js @@ -40,6 +40,9 @@ function LowlevelUp(file, options) { this.db = new options.db(file); + if (utils.isBrowser) + this.db.bufferKeys = options.bufferKeys; + // Stay as close to the metal as possible. // We want to make calls to C++ directly. while (this.db.db && this.db.db.put && this.db.db !== this.db) @@ -268,6 +271,7 @@ LowlevelUp.prototype.iterate = function iterate(options, callback) { values: options.values || false, fillCache: options.fillCache || false, keyAsBuffer: options.keyAsBuffer || false, + valueAsBuffer: true, reverse: options.reverse || false }; diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 9b8815be..39a10e18 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -132,7 +132,7 @@ function Pool(options) { : this.network.port; this.address = new NetworkAddress({ - ts: utils.now() - (process.uptime() | 0), + ts: utils.now(), services: this.services, host: '0.0.0.0', port: this.port