diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index de04d1ff..bed36121 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -572,16 +572,14 @@ TXDB.prototype._verify = function _verify(tx, info, callback) { if (!spent) return next(); - self.getTX(prevout.hash, function(err, prev) { + self.getSpentCoin(spent, prevout, function(err, coin) { if (err) return next(err); - if (!prev) + if (!coin) return callback(new Error('Could not find double-spent coin.')); - // NOTE: Could use d/spent.hash/spent.index - // here instead of getting a tx. - input.coin = bcoin.coin.fromTX(prev, prevout.index); + input.coin = coin; // Skip invalid transactions if (self.options.verify) { @@ -1035,10 +1033,9 @@ TXDB.prototype._confirm = function _confirm(tx, info, callback) { if (err) return next(err); - if (!coin) { - // TODO: Update spent coin here! - return next(); - } + // Update spent coin. + if (!coin) + return self.updateSpentCoin(tx, i, next); self.balance.confirm(coin.value); @@ -1262,10 +1259,9 @@ TXDB.prototype.unconfirm = function unconfirm(hash, callback, force) { TXDB.prototype._unconfirm = function unconfirm(tx, info, callback, force) { var self = this; var hash = tx.hash('hex'); - var height = tx.height; var i, account; - if (height !== -1) + if (tx.height === -1) return callback(null, false, info); tx.height = -1; @@ -1290,10 +1286,9 @@ TXDB.prototype._unconfirm = function unconfirm(tx, info, callback, force) { if (err) return next(err); - if (!coin) { - // TODO: Update spent coin here - return next(); - } + // Update spent coin. + if (!coin) + return self.updateSpentCoin(tx, i, next); self.balance.unconfirm(coin.value); coin.height = tx.height; @@ -2077,6 +2072,55 @@ TXDB.prototype.getCoin = function getCoin(hash, index, callback) { }, callback); }; +/** + * Get spender coin. + * @param {Outpoint} spent + * @param {Outpoint} prevout + * @param {Function} callback - Returns [Error, {@link Coin}]. + */ + +TXDB.prototype.getSpentCoin = function getSpentCoin(spent, prevout, callback) { + this.fetch(layout.d(spent.hash, spent.index), function(data) { + var coin = bcoin.coin.fromRaw(data); + coin.hash = prevout.hash; + coin.index = prevout.index; + return coin; + }, callback); +}; + +/** + * Update spent coin height in storage. + * @param {TX} tx - Sending transaction. + * @param {Number} index + * @param {Function} callback + */ + +TXDB.prototype.updateSpentCoin = function updateSpentCoin(tx, i, callback) { + var self = this; + var prevout = bcoin.outpoint.fromTX(tx, i); + this.isSpent(prevout.hash, prevout.index, function(err, spent) { + if (err) + return callback(err); + + if (!spent) + return callback(); + + self.getSpentCoin(spent, prevout, function(err, coin) { + if (err) + return callback(err); + + if (!coin) + return callback(); + + coin.height = tx.height; + + self.put(layout.d(spent.hash, spent.index), coin.toRaw()); + + callback(); + }); + }); +}; + /** * Test whether the database has a transaction. * @param {Hash} hash @@ -2296,7 +2340,7 @@ function Details(info) { this.block = info.tx.block; this.index = info.tx.index; this.confirmations = info.tx.getConfirmations(this.db.height); - this.fee = info.tx.hasCoins() ? info.tx.getFee() : 0; + this.fee = info.tx.getFee(); this.ts = info.tx.ts; this.ps = info.tx.ps; this.tx = info.tx;