diff --git a/lib/bcoin/hd.js b/lib/bcoin/hd.js index 551bbdb1..080f616f 100644 --- a/lib/bcoin/hd.js +++ b/lib/bcoin/hd.js @@ -259,9 +259,9 @@ HDPrivateKey.prototype.scan44 = function scan44(options, txByAddress, callback) assert(accounts[accountIndex] == null || chainConstant === 1); if (chainConstant === 0) - accounts[accountIndex] = { addressDepth: addressIndex }; + accounts[accountIndex] = { addressDepth: addressIndex - gap }; else - accounts[accountIndex].changeDepth = addressIndex; + accounts[accountIndex].changeDepth = addressIndex - gap; // 4. if no transactions are found on the // external chain, stop discovery @@ -410,9 +410,9 @@ HDPrivateKey.prototype.scan45 = function scan45(options, txByAddress, callback) assert(cosigners[cosignerIndex] == null || chainConstant === 1); if (chainConstant === 0) - cosigners[cosignerIndex] = { addressDepth: addressIndex }; + cosigners[cosignerIndex] = { addressDepth: addressIndex - gap }; else - cosigners[cosginerIndex].changeDepth = addressIndex; + cosigners[cosginerIndex].changeDepth = addressIndex - gap; if (total === 0) { if (chainConstant === 0) diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index d9b6e841..d6d12faf 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -636,149 +636,54 @@ Wallet.prototype.getOutputPaths = function getOutputPaths(tx) { Wallet.prototype.getOutputDepth = function getOutputDepth(tx) { var paths = this.getOutputPaths(tx); - var depth = { change: -1, receive: -1 }; + var depth = { changeDepth: -1, receiveDepth: -1 }; var i, path; for (i = 0; i < paths.length; i++) { path = this.parsePath(paths[i]); if (path.change) { - if (path.index > depth.change) - depth.change = path.index; + if (path.index > depth.changeDepth) + depth.changeDepth = path.index; } else { - if (path.index > depth.receive) - depth.receive = path.index; + if (path.index > depth.receiveDepth) + depth.receiveDepth = path.index; } } - depth.change++; - depth.receive++; + depth.changeDepth++; + depth.receiveDepth++; return depth; }; Wallet.prototype.syncOutputDepth = function syncOutputDepth(tx) { var depth = this.getOutputDepth(tx); - if (depth.change >= this.changeDepth) - this.setChangeDepth(depth.change + 1); - if (depth.receive >= this.receiveDepth) - this.setReceiveDepth(depth.receive + 1); + if (depth.changeDepth >= this.changeDepth) + this.setChangeDepth(depth.changeDepth + 1); + if (depth.receiveDepth >= this.receiveDepth) + this.setReceiveDepth(depth.receiveDepth + 1); }; Wallet.prototype.scan = function scan(txByAddress, callback) { - function done(err, depths) { + var self = this; + + return this._scan({}, txByAddress, function(err, depth) { if (err) return callback(err); - if (depths.changeDepth >= this.changeDepth) - this.setChangeDepth(depths.changeDepth + 1); + if (depth.changeDepth >= this.changeDepth) + this.setChangeDepth(depth.changeDepth + 1); - if (depths.receiveDepth >= this.receiveDepth) - this.setReceiveDepth(depths.receiveDepth + 1); - } + if (depth.receiveDepth >= this.receiveDepth) + this.setReceiveDepth(depth.receiveDepth + 1); - if (this.derivation === 'bip44') - return this._scan44({ current: true }, txByAddress, done); - - if (this.derivation === 'bip45') - return this._scan45({}, txByAddress, done); + return callback(null, self); + }); }; -Wallet.prototype._scan44 = function scan44(options, txByAddress, callback) { +Wallet.prototype._scan = function _scan(options, txByAddress, callback) { var self = this; - var accounts = []; - var isAccount = this.master.isAccount44(); - var _accountKey = this.accountKey; - - assert(this._initialized); - - return (function chainCheck(change) { - return (function scanner(accountIndex) { - var addressIndex = 0; - var total = 0; - var gap = 0; - - if (options.current) - accountIndex = self.accountIndex; - - // 1. derive the first account's node (index = 0) - self.accountKey = isAccount - ? self.master - : self.master.deriveAccount44(accountIndex); - - if (isAccount) - accountIndex = new bn(self.master.childIndex).toNumber() - constants.hd.hardened; - - // 2. derive the external chain node of this account - // 3. scan addresses of the external chain; - // respect the gap limit described below - return (function next() { - var address = self.deriveAddress(change, addressIndex++); - var addr = address.getAddress(); - - return txByAddress(addr, function(err, txs) { - var result; - - if (err) { - self.accountKey = _accountKey; - return callback(err); - } - - if (txs) { - if (typeof txs === 'boolean') - result = txs; - else if (typeof txs === 'number') - result = txs > 0; - else if (Array.isArray(txs)) - result = txs.length > 0; - else - result = false; - } - - if (result) { - total++; - gap = 0; - return next(); - } - - if (++gap < 20) - return next(); - - assert(accounts[accountIndex] == null || change === true); - - if (change === false) - accounts[accountIndex] = { receiveDepth: addressIndex }; - else - accounts[accountIndex].changeDepth = addressIndex; - - // 4. if no transactions are found on the - // external chain, stop discovery - if (total === 0) { - if (change === false) - return chainCheck(true); - self.accountKey = _accountKey; - if (isAccount || options.current) - return callback(null, accounts[accountIndex]); - return callback(null, accounts); - } - - // 5. if there are some transactions, increase - // the account index and go to step 1 - if (isAccount || options.current) { - if (change === false) - return chainCheck(true); - self.accountKey = _accountKey; - return callback(null, accounts[accountIndex]); - } - - return scanner(accountIndex + 1); - }); - })(); - })(0); - })(false); -}; - -Wallet.prototype._scan45 = function scan45(options, txByAddress, callback) { - var depths = { changeDepth: 0, receiveDepth: 0 }; + var depth = { changeDepth: 0, receiveDepth: 0 }; assert(this._initialized); @@ -789,9 +694,8 @@ Wallet.prototype._scan45 = function scan45(options, txByAddress, callback) { return (function next() { var address = self.deriveAddress(change, addressIndex++); - var addr = address.getAddress(); - return txByAddress(addr, function(err, txs) { + return txByAddress(address.getAddress(), function(err, txs) { var result; if (err) @@ -806,6 +710,9 @@ Wallet.prototype._scan45 = function scan45(options, txByAddress, callback) { result = txs.length > 0; else result = false; + + if (Array.isArray(txs) && (txs[0] instanceof bcoin.tx)) + txs.forEach(function(tx) { self.addTX(tx); }); } if (result) { @@ -817,41 +724,53 @@ Wallet.prototype._scan45 = function scan45(options, txByAddress, callback) { if (++gap < 20) return next(); - assert(depths.receiveDepth === 0 || change === true); + assert(depth.receiveDepth === 0 || change === true); if (change === false) - depths.receiveDepth = addressIndex; + depth.receiveDepth = addressIndex - gap; else - depths.changeDepth = addressIndex; + depth.changeDepth = addressIndex - gap; if (change === false) return chainCheck(true); - return callback(null, depths); + return callback(null, depth); }); })(); })(false); }; Wallet.prototype.scriptInputs = function scriptInputs(tx, index) { + var addresses; + this.fillPrevout(tx); - var addresses = this.deriveInputs(tx); + + addresses = this.deriveInputs(tx); + return addresses.reduce(function(total, address) { return total + address.scriptInputs(tx, index); }, 0); }; Wallet.prototype.signInputs = function signInputs(tx, type, index) { + var addresses; + this.fillPrevout(tx); - var addresses = this.deriveInputs(tx); + + addresses = this.deriveInputs(tx); + return addresses.reduce(function(total, address) { return total + address.signInputs(tx, type, index); }, 0); }; Wallet.prototype.sign = function sign(tx, type, index) { + var addresses; + this.fillPrevout(tx); - var addresses = this.deriveInputs(tx); + + addresses = this.deriveInputs(tx); + return addresses.reduce(function(total, address) { return total + address.sign(tx, type, index); }, 0);