diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index 73cb36d9..8f76af4f 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -36,74 +36,131 @@ var Parser = bcoin.protocol.parser; var layout = { R: function R() { var p = new BufferWriter(); - p.writeString('R', 'ascii'); + p.writeU8(0x52); // R + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, e: function e(hash) { var p = new BufferWriter(); - p.writeString('e', 'ascii'); + p.writeU8(0x65); // e p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, h: function h(hash) { var p = new BufferWriter(); - p.writeString('h', 'ascii'); + p.writeU8(0x68); // h p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, H: function H(height) { var p = new BufferWriter(); - p.writeString('H', 'ascii'); + p.writeU8(0x48); // H p.writeU32(height); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, n: function n(hash) { var p = new BufferWriter(); - p.writeString('n', 'ascii'); + p.writeU8(0x6e); // n p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, b: function b(hash) { var p = new BufferWriter(); - p.writeString('b', 'ascii'); + p.writeU8(0x62); // b p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, t: function t(hash) { var p = new BufferWriter(); - p.writeString('t', 'ascii'); + p.writeU8(0x74); // t p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, c: function c(hash) { var p = new BufferWriter(); - p.writeString('c', 'ascii'); + p.writeU8(0x63); // c p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, u: function u(hash) { var p = new BufferWriter(); - p.writeString('u', 'ascii'); + p.writeU8(0x75); // u p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); + return p.render(); + }, + q: function q(height) { + var p = new BufferWriter(); + p.writeU8(0x71); // q + p.writeU32(height); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, T: function T(address, hash) { var p = new BufferWriter(); - p.writeString('T', 'ascii'); - p.writeString(address, 'hex'); - p.writeString('\0', 'binary'); + if (address.length === 64) + p.writeU8(0x41); // A + else + p.writeU8(0x54); // T + p.writeHash(address); p.writeHash(hash); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); }, C: function C(address, hash, index) { var p = new BufferWriter(); - p.writeString('C', 'ascii'); - p.writeString(address, 'hex'); - p.writeString('\0', 'binary'); + if (address.length === 64) + p.writeU8(0x42); // B + else + p.writeU8(0x43); // C + p.writeHash(address); p.writeHash(hash); - p.writeString('\0', 'binary'); p.writeU32(index); + if (utils.isBrowser) + return p.render().toString('hex'); return p.render(); + }, + 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); + } else { + hash = key.slice(21, 53).toString('hex'); + index = key.readUInt32LE(53, 0); + } + + 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'); } }; @@ -1082,7 +1139,7 @@ ChainDB.prototype.getCoin = function getCoin(hash, index, callback) { return callback(null, coins); } - this.db.fetch('c/' + hash, function(data) { + this.db.fetch(layout.c(hash), function(data) { self.coinCache.set(hash, data); return bcoin.coins.parseCoin(data, hash, index); }, callback); @@ -1175,12 +1232,10 @@ ChainDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, call return next(); self.db.iterate({ - gte: 'C/' + address, - lte: 'C/' + address + '~', - transform: function(key) { - key = key.split('/'); - return [key[2], +key[3]]; - } + gte: layout.C(address, constants.NULL_HASH, 0), + lte: layout.C(address, constants.MAX_HASH, 0xffffffff), + keyAsBuffer: !utils.isBrowser, + transform: layout.Cc }, function(err, keys) { if (err) return next(err); @@ -1222,29 +1277,28 @@ ChainDB.prototype.getTXByAddress = function getTXByAddress(addresses, callback) utils.forEachSerial(addresses, function(address, next) { address = bcoin.address.getHash(address); + if (!address) return next(); + self.db.lookup({ - gte: 'T/' + address, - lte: 'T/' + address + '~', + gte: layout.T(address, constants.NULL_HASH), + lte: layout.T(address, constants.MAX_HASH), + keyAsBuffer: !utils.isBrowser, transform: function(key) { - var hash = key.split('/')[2]; - if (addresses.length > 1) { - if (have[hash]) - return false; - have[hash] = true; - } - return 't/' + hash; + var hash = layout.Tt(key); + + if (have[hash]) + return; + + have[hash] = true; + + return layout.t(hash); }, parse: function(data, key) { - return bcoin.tx.fromRaw(data); + txs.push(bcoin.tx.fromRaw(data)); } - }, function(err, tx) { - if (err) - return next(err); - txs = txs.concat(tx); - next(); - }); + }, next); }, function(err) { if (err) return callback(err); @@ -1468,11 +1522,11 @@ ChainDB.prototype._pruneBlock = function _pruneBlock(block, batch, callback) { if (block.height <= this.network.block.pruneAfterHeight) return callback(); - futureHeight = pad32(block.height + this.keepBlocks); + futureHeight = block.height + this.keepBlocks; - batch.put('q/' + futureHeight, block.hash()); + batch.put(layout.q(futureHeight), block.hash()); - key = 'q/' + pad32(block.height); + key = layout.q(block.height); this.db.fetch(key, function(data) { assert(data.length === 32, 'Database corruption.'); diff --git a/lib/bcoin/lowlevelup.js b/lib/bcoin/lowlevelup.js index 8d1ff60c..e62a4d48 100644 --- a/lib/bcoin/lowlevelup.js +++ b/lib/bcoin/lowlevelup.js @@ -245,7 +245,7 @@ LowlevelUp.prototype.iterate = function iterate(options, callback) { keys: true, values: options.values, fillCache: false, - keyAsBuffer: false, + keyAsBuffer: options.keyAsBuffer || false, limit: options.limit, reverse: options.reverse }; diff --git a/lib/bcoin/protocol/constants.js b/lib/bcoin/protocol/constants.js index 654daee5..8fcf5481 100644 --- a/lib/bcoin/protocol/constants.js +++ b/lib/bcoin/protocol/constants.js @@ -597,6 +597,15 @@ exports.ZERO_HASH = new Buffer( exports.NULL_HASH = '0000000000000000000000000000000000000000000000000000000000000000'; +/** + * A hash of all 0xff. + * @const {String} + * @default + */ + +exports.MAX_HASH = + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; + /** * BCoin version. * @const {String}