From da6a575469c26c2d04917f106c427afcec93097e Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Tue, 18 Oct 2016 06:38:41 -0700 Subject: [PATCH] walletdb: better mapping. --- lib/wallet/browser.js | 25 ++++++--- lib/wallet/walletdb.js | 119 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 122 insertions(+), 22 deletions(-) diff --git a/lib/wallet/browser.js b/lib/wallet/browser.js index 22f2fa45..c7d1935c 100644 --- a/lib/wallet/browser.js +++ b/lib/wallet/browser.js @@ -11,28 +11,28 @@ var pad32 = utils.pad32; var layout = exports; layout.walletdb = { - p: function(hash) { + p: function p(hash) { return 'p' + hash; }, - pp: function(key) { + pp: function pp(key) { return key.slice(1); }, - P: function(wid, hash) { + P: function P(wid, hash) { return 'p' + pad32(wid) + hash; }, - Pp: function(key) { + Pp: function Pp(key) { return key.slice(11); }, - w: function(wid) { + w: function w(wid) { return 'w' + pad32(wid); }, - ww: function(key) { + ww: function ww(key) { return +key.slice(1); }, - l: function(id) { + l: function l(id) { return 'l' + id; }, - ll: function(key) { + ll: function ll(key) { return key.slice(1); }, a: function a(wid, index) { @@ -50,6 +50,9 @@ layout.walletdb = { }, e: function e(hash) { return 'e' + hash; + }, + ee: function ee(key) { + return key.slice(1); } }; @@ -120,6 +123,12 @@ layout.txdb = { ss: function ss(key) { return this.hii(key); }, + S: function S(hash, index) { + return this.hi('S', hash, index); + }, + Ss: function Ss(key) { + return this.hii(key); + }, p: function p(hash) { return this.ha('p', hash); }, diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js index f5b880e6..be8a8001 100644 --- a/lib/wallet/walletdb.js +++ b/lib/wallet/walletdb.js @@ -42,35 +42,35 @@ var TXDB = require('./txdb'); */ var layout = { - p: function(hash) { + p: function p(hash) { var key = new Buffer(1 + (hash.length / 2)); key[0] = 0x70; key.write(hash, 1, 'hex'); return key; }, - pp: function(key) { + pp: function pp(key) { return key.toString('hex', 1); }, - P: function(wid, hash) { + P: function P(wid, hash) { var key = new Buffer(1 + 4 + (hash.length / 2)); key[0] = 0x50; key.writeUInt32BE(wid, 1, true); key.write(hash, 5, 'hex'); return key; }, - Pp: function(key) { + Pp: function Pp(key) { return key.toString('hex', 5); }, - w: function(wid) { + w: function w(wid) { var key = new Buffer(5); key[0] = 0x77; key.writeUInt32BE(wid, 1, true); return key; }, - ww: function(key) { + ww: function ww(key) { return key.readUInt32BE(1, true); }, - l: function(id) { + l: function l(id) { var len = Buffer.byteLength(id, 'ascii'); var key = new Buffer(1 + len); key[0] = 0x6c; @@ -78,7 +78,7 @@ var layout = { key.write(id, 1, 'ascii'); return key; }, - ll: function(key) { + ll: function ll(key) { return key.toString('ascii', 1); }, a: function a(wid, index) { @@ -112,7 +112,10 @@ var layout = { key[0] = 0x65; key.write(hash, 1, 'hex'); return key; - } + }, + ee: function ee(key) { + return key.toString('hex', 1); + }, }; if (utils.isBrowser) @@ -370,6 +373,21 @@ WalletDB.prototype.loadFilter = co(function* loadFilter() { hash = layout.pp(item.key); this.filter.add(hash, 'hex'); } + + iter = this.db.iterator({ + gte: layout.e(constants.NULL_HASH), + lte: layout.e(constants.HIGH_HASH) + }); + + for (;;) { + item = yield iter.next(); + + if (!item) + break; + + hash = layout.ee(item.key); + this.filter.add(hash, 'hex'); + } }); /** @@ -1183,8 +1201,9 @@ WalletDB.prototype.resend = co(function* resend() { * @returns {Promise} */ -WalletDB.prototype.getWalletsByHashes = co(function* getWalletsByHashes(hashes) { +WalletDB.prototype.getWalletsByHashes = co(function* getWalletsByHashes(tx) { var result = []; + var hashes = tx.getHashes('hex'); var i, j, hash, wids; for (i = 0; i < hashes.length; i++) { @@ -1208,6 +1227,53 @@ WalletDB.prototype.getWalletsByHashes = co(function* getWalletsByHashes(hashes) return result; }); +/** + * Get all wallet ids by multiple address hashes. + * @param {Hash[]} hashes + * @returns {Promise} + */ + +WalletDB.prototype.getWalletsByInsert = co(function* getWalletsByInsert(tx) { + var result = []; + var hashes = tx.getOutputHashes('hex'); + var i, j, input, hash, wids; + + for (i = 0; i < tx.inputs.length; i++) { + input = tx.inputs[i]; + + if (!this.testFilter(input.prevout.hash)) + continue; + + wids = yield this.getWalletsByTX(input.prevout.hash); + + if (!wids) + continue; + + for (j = 0; j < wids.length; j++) + utils.binaryInsert(result, wids[j], cmp, true); + } + + for (i = 0; i < hashes.length; i++) { + hash = hashes[i]; + + if (!this.testFilter(hash)) + continue; + + wids = yield this.getWalletsByHash(hash); + + if (!wids) + continue; + + for (j = 0; j < wids.length; j++) + utils.binaryInsert(result, wids[j], cmp, true); + } + + if (result.length === 0) + return; + + return result; +}); + /** * Write the genesis block as the best hash. * @returns {Promise} @@ -1371,12 +1437,15 @@ WalletDB.prototype._addBlock = co(function* addBlock(entry, txs) { for (i = 0; i < txs.length; i++) { tx = txs[i]; - wallets = yield this._addTX(tx); + wallets = yield this._insertTX(tx); if (!wallets) continue; hash = tx.hash('hex'); + + this.filter.add(hash, 'hex'); + block.hashes.push(hash); matches.push(wallets); } @@ -1469,12 +1538,34 @@ WalletDB.prototype.addTX = co(function* addTX(tx) { */ WalletDB.prototype._addTX = co(function* addTX(tx) { - var i, hashes, wallets, wid, wallet; + var wallets = yield this._insertTX(tx); + var hash; + + if (!wallets) + return; + + hash = tx.hash('hex'); + + yield this.db.put(layout.e(hash), serializeWallets(wallets)); + + this.filter.add(hash, 'hex'); + + return wallets; +}); + +/** + * Add a transaction to the database without a lock. + * @private + * @param {TX} tx + * @returns {Promise} + */ + +WalletDB.prototype._insertTX = co(function* insertTX(tx) { + var i, wallets, wid, wallet; assert(!tx.mutable, 'Cannot add mutable TX to wallet.'); - hashes = tx.getHashes('hex'); - wallets = yield this.getWalletsByHashes(hashes); + wallets = yield this.getWalletsByInsert(tx); if (!wallets) return;