From 3e2f43e178962c060518483f5f8da353a101f4b6 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 20 May 2016 17:11:40 -0700 Subject: [PATCH] use bloom filter for addresses in wallet db. --- lib/bcoin/txdb.js | 55 +++++++++++++++++++++++++++++++++++++++++++ lib/bcoin/walletdb.js | 29 ++++++++++++++++------- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index 07851982..d8845fb3 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -59,6 +59,9 @@ function TXDB(db, options) { this.busy = false; this.jobs = []; this.locker = new bcoin.locker(this); + this.filter = this.options.useFilter + ? new bcoin.bloom.rolling(800000, 0.01) + : null; if (this.options.mapAddress) this.options.indexAddress = true; @@ -70,6 +73,43 @@ TXDB.prototype._lock = function _lock(func, args, force) { return this.locker.lock(func, args, force); }; +TXDB.prototype._loadFilter = function loadFilter(callback) { + var self = this; + + if (!this.filter) + return callback(); + + this.db.iterate({ + gte: 'W', + lte: 'W~', + transform: function(key) { + return key.split('/')[1]; + } + }, function(err, keys) { + if (err) + return callback(err); + + for (i = 0; i < keys.length; i++) + self.filter.add(keys[i], 'hex'); + + return callback(); + }); +}; + +TXDB.prototype._testFilter = function _testFilter(addresses) { + var i; + + if (!this.filter) + return true; + + for (i = 0; i < addresses.length; i++) { + if (this.filter.test(addresses[i], 'hex')) + return true; + } + + return false; +}; + /** * Map a transactions' addresses to wallet IDs. * @param {TX} tx @@ -86,6 +126,9 @@ TXDB.prototype.getMap = function getMap(tx, callback) { output = tx.getOutputHashes(); addresses = utils.uniq(input.concat(output)); + if (!this._testFilter(addresses)) + return callback(); + function cb(err, table) { if (err) return callback(err); @@ -267,6 +310,9 @@ TXDB.prototype.add = function add(tx, callback, force) { if (err) return callback(err); + if (!map) + return callback(null, false); + if (self.options.mapAddress) { if (map.all.length === 0) return callback(null, false); @@ -757,6 +803,9 @@ TXDB.prototype.remove = function remove(hash, callback, force) { if (err) return callback(err); + if (!map) + return callback(null, false); + if (self.options.mapAddress) { if (map.all.length === 0) return callback(null, false); @@ -788,6 +837,9 @@ TXDB.prototype.lazyRemove = function lazyRemove(tx, callback, force) { if (err) return callback(err); + if (!map) + return callback(null, false); + if (self.options.mapAddress) { if (map.all.length === 0) return callback(null, false); @@ -938,6 +990,9 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) { if (err) return callback(err); + if (!map) + return callback(null, false); + if (self.options.mapAddress) { if (map.all.length === 0) return callback(null, false); diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index 08b8a409..84b47d3d 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -107,20 +107,26 @@ WalletDB.prototype._init = function _init() { writeBufferSize: 4 << 20 }); - this.db.open(function(err) { - if (err) - return self.emit('error', err); - - self.emit('open'); - self.loaded = true; - }); - this.tx = new bcoin.txdb(this.db, { network: this.network, indexExtra: true, indexAddress: true, mapAddress: true, - verify: this.options.verify + verify: this.options.verify, + useFilter: true + }); + + this.db.open(function(err) { + if (err) + return self.emit('error', err); + + self.tx._loadFilter(function(err) { + if (err) + return self.emit('error', err); + + self.emit('open'); + self.loaded = true; + }); }); this.tx.on('error', function(err) { @@ -373,9 +379,14 @@ WalletDB.prototype.saveJSON = function saveJSON(id, json, callback) { if (json) { batch = self.db.batch(); + Object.keys(json.addressMap).forEach(function(address) { + if (self.tx.filter) + self.tx.filter.add(address, 'hex'); + batch.put('W/' + address + '/' + json.id, DUMMY); }); + return batch.write(function(err) { if (err) return callback(err);