diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index 86b53a2b..7576418d 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -34,6 +34,75 @@ var BufferReader = require('./reader'); * q[height] -> block hash to be pruned */ +/* String keys +var layout = { + R: 'R', + e: function e(hash) { + return 'e' + hash; + }, + h: function h(hash) { + return 'h' + hash; + }, + H: function H(height) { + return 'H' + pad32(height); + }, + n: function n(hash) { + return 'n' + hash; + }, + b: function b(hash) { + return 'b' + hash; + }, + t: function t(hash) { + return 't' + hash; + }, + c: function c(hash) { + return 'c' + hash; + }, + u: function u(hash) { + return 'u' + hash; + }, + q: function q(height) { + return 'q' + pad32(height); + }, + T: function T(address, hash) { + var len = address.length; + var key; + + if (address.length === 64) + return 'W' + address + hash; + + return 'T' + address + hash; + }, + C: function C(address, hash, index) { + var len = address.length; + var key; + + if (address.length === 64) + return 'X' + address + hash + pad32(index); + + return 'C' + address + hash + pad32(index); + }, + Cc: function Cc(key) { + var hash, index; + + if (key.length === 139) { + hash = key.slice(65, 129); + index = +key.slice(129); + } else { + hash = key.slice(41, 105).toString('hex'); + index = +key.slice(105); + } + + return [hash, index]; + }, + Tt: function Tt(key) { + return key.length === 129 + ? key.slice(64) + : key.slice(41); + } +}; +*/ + var layout = { R: new Buffer([0x52]), e: function e(hash) { @@ -96,12 +165,16 @@ var layout = { key[0] = 0x9a; // W + C write(key, address, 1); write(key, hash, 33); + // TODO: Change this to big + // endian for saner sorting. key.writeUInt32LE(index, 65, true); } else { key = new Buffer(57); key[0] = 0x43; // C write(key, address, 1); write(key, hash, 21); + // TODO: Change this to big + // endian for saner sorting. key.writeUInt32LE(index, 53, true); } @@ -1253,7 +1326,6 @@ 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: true, transform: layout.Cc }, function(err, keys) { if (err) @@ -1289,7 +1361,6 @@ ChainDB.prototype.getEntries = function getEntries(callback) { gte: layout.e(constants.ZERO_HASH), lte: layout.e(constants.MAX_HASH), values: true, - keyAsBuffer: true, parse: function(data) { return bcoin.chainentry.fromRaw(self.chain, data); } @@ -1319,7 +1390,6 @@ 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: true, transform: function(key) { var hash = layout.Tt(key); @@ -1583,6 +1653,8 @@ function pair(prefix, hash) { function ipair(prefix, num) { var key = new Buffer(5); key[0] = prefix; + // TODO: Change this to big + // endian for saner sorting. key.writeUInt32LE(num, 1, true); return key; } diff --git a/lib/bcoin/lowlevelup.js b/lib/bcoin/lowlevelup.js index 08e7e598..bb0ac7e1 100644 --- a/lib/bcoin/lowlevelup.js +++ b/lib/bcoin/lowlevelup.js @@ -37,6 +37,7 @@ function LowlevelUp(file, options) { this.options = options; this.backend = options.db; this.location = file; + this.bufferKeys = options.bufferKeys === true; this.db = new options.db(file); @@ -268,7 +269,7 @@ LowlevelUp.prototype.each = function each(options, handler, callback) { keys: true, values: options.values || false, fillCache: options.fillCache || false, - keyAsBuffer: options.keyAsBuffer || false, + keyAsBuffer: options.keyAsBuffer || this.bufferKeys, valueAsBuffer: true, reverse: options.reverse || false }; @@ -328,7 +329,7 @@ LowlevelUp.prototype.iterate = function iterate(options, callback) { keys: true, values: options.values || false, fillCache: options.fillCache || false, - keyAsBuffer: options.keyAsBuffer || false, + keyAsBuffer: options.keyAsBuffer || this.bufferKeys, valueAsBuffer: true, reverse: options.reverse || false }; diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index 342f583f..93871e03 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -37,6 +37,7 @@ function Layout(wallet) { this.wallet = wallet; } +/* String Keys Layout.prototype.prefix = function prefix(key) { assert(this.wallet.wid); return 't' + pad32(this.wallet.wid) + key; @@ -86,8 +87,92 @@ Layout.prototype.haa = function haa(key) { key = key.slice(12); return key; }; +*/ + +Layout.prototype.prefix = function prefix(key) { + var out = new Buffer(5 + key.length); + assert(this.wallet.wid); + out[0] = 0x74; + out.writeUInt32BE(this.wallet.wid, 1); + key.copy(out, 5); + return out; +}; + +Layout.prototype.hi = function hi(ch, hash, index) { + var key = new Buffer(37); + key[0] = ch.charCodeAt(0); + key.write(hash, 1, 'hex'); + key.writeUInt32BE(index, 33, true); + return this.prefix(key); +}; + +Layout.prototype.hii = function hii(key) { + key = key.slice(6); + return [key.toString('hex', 0, 32), key.readUInt32BE(32, true)]; +}; + +Layout.prototype.ih = function ih(ch, index, hash) { + var key = new Buffer(37); + key[0] = ch.charCodeAt(0); + key.writeUInt32BE(index, 1, true); + key.write(hash, 5, 'hex'); + return this.prefix(key); +}; + +Layout.prototype.ihh = function ihh(key) { + key = key.slice(6); + return [key.readUInt32BE(0, true), key.toString('hex', 4, 36)]; +}; + +Layout.prototype.iih = function iih(ch, index, num, hash) { + var key = new Buffer(41); + key[0] = ch.charCodeAt(0); + key.writeUInt32BE(index, 1, true); + key.writeUInt32BE(num, 5, true); + key.write(hash, 9, 'hex'); + return this.prefix(key); +}; + +Layout.prototype.iihh = function iihh(key) { + key = key.slice(6); + return [ + key.readUInt32BE(0, true), + key.readUInt32BE(4, true), + key.toString('hex', 8, 40) + ]; +}; + +Layout.prototype.ihi = function ihi(ch, index, hash, num) { + var key = new Buffer(41); + key[0] = ch.charCodeAt(0); + key.writeUInt32BE(index, 1, true); + key.write(hash, 5, 'hex'); + key.writeUInt32BE(num, 37, true); + return this.prefix(key); +}; + +Layout.prototype.ihii = function ihii(key) { + key = key.slice(6); + return [ + key.readUInt32BE(0, true), + key.toString('hex', 4, 36), + key.readUInt32BE(36, true) + ]; +}; + +Layout.prototype.ha = function ha(ch, hash) { + var key = new Buffer(33); + key[0] = ch.charCodeAt(0); + key.write(hash, 1, 'hex'); + return this.prefix(key); +}; + +Layout.prototype.haa = function haa(key) { + return key.toString('hex', 1); +}; Layout.prototype.t = function t(hash) { + // 0x74 return this.ha('t', hash); }; @@ -96,6 +181,7 @@ Layout.prototype.tt = function tt(key) { }; Layout.prototype.c = function c(hash, index) { + // 0x63 return this.hi('c', hash, index); }; @@ -104,6 +190,7 @@ Layout.prototype.cc = function cc(key) { }; Layout.prototype.d = function d(hash, index) { + // 0x64 return this.hi('d', hash, index); }; @@ -112,6 +199,7 @@ Layout.prototype.dd = function dd(key) { }; Layout.prototype.s = function s(hash, index) { + // 0x73 return this.hi('s', hash, index); }; @@ -120,6 +208,7 @@ Layout.prototype.ss = function ss(key) { }; Layout.prototype.o = function o(hash, index) { + // 0x6f return this.hi('o', hash, index); }; @@ -128,6 +217,7 @@ Layout.prototype.oo = function oo(key) { }; Layout.prototype.p = function p(hash) { + // 0x70 return this.ha('p', hash); }; @@ -136,6 +226,7 @@ Layout.prototype.pp = function pp(key) { }; Layout.prototype.m = function m(time, hash) { + // 0x6d return this.ih('m', time, hash); }; @@ -144,6 +235,7 @@ Layout.prototype.mm = function mm(key) { }; Layout.prototype.h = function h(height, hash) { + // 0x68 return this.ih('h', height, hash); }; @@ -152,6 +244,7 @@ Layout.prototype.hh = function hh(key) { }; Layout.prototype.T = function T(account, hash) { + // 0x54 return this.ih('T', account, hash); }; @@ -160,6 +253,7 @@ Layout.prototype.Tt = function Tt(key) { }; Layout.prototype.P = function P(account, hash) { + // 0x50 return this.ih('P', account, hash); }; @@ -168,6 +262,7 @@ Layout.prototype.Pp = function Pp(key) { }; Layout.prototype.M = function M(account, time, hash) { + // 0x4d return this.iih('M', account, time, hash); }; @@ -176,6 +271,7 @@ Layout.prototype.Mm = function Mm(key) { }; Layout.prototype.H = function H(account, height, hash) { + // 0x48 return this.iih('H', account, height, hash); }; @@ -184,6 +280,7 @@ Layout.prototype.Hh = function Hh(key) { }; Layout.prototype.C = function C(account, hash, index) { + // 0x43 return this.ihi('C', account, hash, index); }; diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index d2c730c3..ef5691ba 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -2410,10 +2410,9 @@ utils._paths = {}; utils.isAlpha = function isAlpha(key) { if (typeof key !== 'string') return false; - // We allow /-~ (exclusive), 0-} (inclusive) return key.length >= 1 && key.length <= 40 - && /^[\u0030-\u007d]+$/.test(key); + && /^[\u0020-\u007e]+$/.test(key); }; /** diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index 2c46f00a..0f4cbf80 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -31,6 +31,7 @@ var BufferWriter = require('./writer'); var TXDB = require('./txdb'); var keyTypes = bcoin.keyring.types; +/* String Keys var layout = { p: function(hash) { return 'p' + hash; @@ -67,6 +68,68 @@ var layout = { return 'e' + hash; } }; +*/ + +var layout = { + p: function(hash) { + var key = new Buffer(1 + (hash.length / 2)); + key[0] = 0x70; + key.write(hash, 1, 'hex'); + return key; + }, + pp: function(key) { + return key.toString('hex', 1); + }, + w: function(wid) { + var key = new Buffer(5); + key[0] = 0x77; + key.writeUInt32BE(wid, 1, true); + return key; + }, + ww: function(key) { + return key.readUInt32BE(1, true); + }, + l: function(id) { + var key = new Buffer(1 + id.length); + key[0] = 0x6c; + key.write(id, 1, 'ascii'); + return key; + }, + ll: function(key) { + return key.toString('ascii', 1); + }, + a: function a(wid, index) { + var key = new Buffer(9); + key[0] = 0x61; + key.writeUInt32BE(wid, 1, true); + key.writeUInt32BE(index, 5, true); + return key; + }, + i: function i(wid, name) { + var key = new Buffer(5 + name.length); + key[0] = 0x69; + key.writeUInt32BE(wid, 1, true); + key.write(name, 5, 'ascii'); + return key; + }, + ii: function ii(key) { + return [+key.readUInt32BE(1, true), key.toString('ascii', 5)]; + }, + R: 'R', + b: function b(hash) { + var key = new Buffer(33); + key[0] = 0x62; + key.write(hash, 1, 'hex'); + return key; + }, + e: function e(hash) { + var key = new Buffer(33); + key[0] = 0x65; + key.write(hash, 1, 'hex'); + return key; + } +}; + /** * WalletDB @@ -126,7 +189,8 @@ function WalletDB(options) { location: this.options.location, db: this.options.db, cacheSize: 8 << 20, - writeBufferSize: 4 << 20 + writeBufferSize: 4 << 20, + bufferKeys: true }); if (bcoin.useWorkers) @@ -235,10 +299,7 @@ WalletDB.prototype.getDepth = function getDepth(callback) { lte: layout.w(0xffffffff), reverse: true, keys: true, - values: false, - fillCache: false, - keyAsBuffer: false, - valueAsBuffer: true + fillCache: false }); iter.next(function(err, key, value) { @@ -701,7 +762,7 @@ WalletDB.prototype.getAccounts = function getAccounts(wid, callback) { this.db.iterate({ gte: layout.i(wid, ''), - lte: layout.i(wid, '~'), + lte: layout.i(wid, '\xff'), values: true, parse: function(value, key) { var name = layout.ii(key)[1]; @@ -983,7 +1044,7 @@ WalletDB.prototype.getAddresses = function getAddresses(wid, callback) { WalletDB.prototype.getWallets = function getWallets(callback) { this.db.iterate({ gte: layout.l(''), - lte: layout.l('~'), + lte: layout.l('\xff'), transform: function(key) { return layout.ll(key); }