txdb: handle spent coins better.

This commit is contained in:
Christopher Jeffrey 2016-08-17 16:25:45 -07:00
parent 841cb290d8
commit 4203999b81
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -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;