chain: refactor input spending.
This commit is contained in:
parent
967449b0d5
commit
b37b99a86e
@ -619,12 +619,12 @@ Chain.prototype.verifyDuplicates = co(function* verifyDuplicates(block, prev, st
|
||||
*/
|
||||
|
||||
Chain.prototype.verifyInputs = co(function* verifyInputs(block, prev, state) {
|
||||
var ret = new VerifyResult();
|
||||
var view = new CoinView();
|
||||
var height = prev.height + 1;
|
||||
var historical = prev.isHistorical();
|
||||
var sigops = 0;
|
||||
var jobs = [];
|
||||
var ret = new VerifyResult();
|
||||
var view = new CoinView();
|
||||
var i, tx, valid;
|
||||
|
||||
if (this.options.spv)
|
||||
@ -639,15 +639,13 @@ Chain.prototype.verifyInputs = co(function* verifyInputs(block, prev, state) {
|
||||
|
||||
// Ensure tx is not double spending an output.
|
||||
if (i > 0) {
|
||||
if (!(yield view.hasInputs(this.db, tx))) {
|
||||
if (!(yield view.spendInputs(this.db, tx))) {
|
||||
assert(!historical, 'BUG: Spent inputs in historical data!');
|
||||
throw new VerifyError(block,
|
||||
'invalid',
|
||||
'bad-txns-inputs-missingorspent',
|
||||
100);
|
||||
}
|
||||
|
||||
view.spendCoins(tx);
|
||||
}
|
||||
|
||||
// Skip everything if we're
|
||||
|
||||
@ -1708,7 +1708,7 @@ ChainDB.prototype.connectBlock = co(function* connectBlock(block, view) {
|
||||
|
||||
// Write undo coins (if there are any).
|
||||
if (!view.undo.isEmpty())
|
||||
this.put(layout.u(block.hash()), view.undo.toRaw());
|
||||
this.put(layout.u(block.hash()), view.undo.commit());
|
||||
|
||||
// Prune height-288 if pruning is enabled.
|
||||
yield this.pruneBlock(block);
|
||||
|
||||
@ -105,12 +105,23 @@ CoinView.prototype.has = function has(hash, index) {
|
||||
|
||||
CoinView.prototype.spend = function spend(hash, index) {
|
||||
var coins = this.unspent[hash];
|
||||
var entry, undo;
|
||||
|
||||
if (!coins)
|
||||
return null;
|
||||
|
||||
entry = coins.spend(index);
|
||||
return this.spendFrom(coins, index);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a coin and return it.
|
||||
* @param {Coins} coins
|
||||
* @param {Number} index
|
||||
* @returns {Coin}
|
||||
*/
|
||||
|
||||
CoinView.prototype.spendFrom = function spendFrom(coins, index) {
|
||||
var entry = coins.spend(index);
|
||||
var undo;
|
||||
|
||||
if (!entry)
|
||||
return null;
|
||||
@ -191,7 +202,7 @@ CoinView.prototype.ensureInputs = co(function* ensureInputs(db, tx) {
|
||||
/**
|
||||
* Spend coins for transaction.
|
||||
* @param {TX} tx
|
||||
* @throws on missing coin
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
CoinView.prototype.spendCoins = function spendCoins(tx) {
|
||||
@ -200,11 +211,42 @@ CoinView.prototype.spendCoins = function spendCoins(tx) {
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
prevout = input.prevout;
|
||||
|
||||
input.coin = this.spend(prevout.hash, prevout.index);
|
||||
assert(input.coin, 'Not all coins available.');
|
||||
|
||||
if (!input.coin)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Spend coins for transaction.
|
||||
* @param {TX} tx
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
CoinView.prototype.spendInputs = co(function* spendInputs(db, tx) {
|
||||
var i, input, prevout, coins;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
prevout = input.prevout;
|
||||
coins = yield this.getCoins(db, prevout.hash);
|
||||
|
||||
if (!coins)
|
||||
return false;
|
||||
|
||||
input.coin = this.spendFrom(coins, prevout.index);
|
||||
|
||||
if (!input.coin)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* Convert collection to an array.
|
||||
* @returns {Coins[]}
|
||||
|
||||
@ -99,6 +99,17 @@ UndoCoins.prototype.isEmpty = function isEmpty() {
|
||||
return this.items.length === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the undo coins.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
UndoCoins.prototype.commit = function commit() {
|
||||
var raw = this.toRaw();
|
||||
this.items.length = 0;
|
||||
return raw;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the last undo coin.
|
||||
* @returns {UndoCoin}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user