mempool/chain: move some methods around.
This commit is contained in:
parent
2715e71ae8
commit
d4c2331a11
@ -973,14 +973,15 @@ ChainDB.prototype.getFullBlock = co(function* getFullBlock(hash) {
|
||||
/**
|
||||
* Fill a transaction with coins (only unspents).
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
ChainDB.prototype.fillCoins = co(function* fillCoins(tx) {
|
||||
var found = true;
|
||||
var i, input, prevout, coin;
|
||||
|
||||
if (tx.isCoinbase())
|
||||
return;
|
||||
return found;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
@ -991,27 +992,33 @@ ChainDB.prototype.fillCoins = co(function* fillCoins(tx) {
|
||||
|
||||
coin = yield this.getCoin(prevout.hash, prevout.index);
|
||||
|
||||
if (!coin)
|
||||
if (!coin) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = coin;
|
||||
}
|
||||
|
||||
return found;
|
||||
});
|
||||
|
||||
/**
|
||||
* Fill a transaction with coins (all historical coins).
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
ChainDB.prototype.fillHistory = co(function* fillHistory(tx) {
|
||||
var found = true;
|
||||
var i, input, prevout, prev;
|
||||
|
||||
if (!this.options.indexTX)
|
||||
return;
|
||||
return found;
|
||||
|
||||
if (tx.isCoinbase())
|
||||
return;
|
||||
return found;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
@ -1022,14 +1029,16 @@ ChainDB.prototype.fillHistory = co(function* fillHistory(tx) {
|
||||
|
||||
prev = yield this.getTX(prevout.hash);
|
||||
|
||||
if (!prev)
|
||||
continue;
|
||||
|
||||
if (prevout.index >= prev.outputs.length)
|
||||
if (!prev || prevout.index >= prev.outputs.length) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = Coin.fromTX(prev, prevout.index);
|
||||
}
|
||||
|
||||
return found;
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@ -290,7 +290,7 @@ Mempool.prototype._reset = function reset() {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Mempool.prototype.limitMempoolSize = function limitMempoolSize(entryHash) {
|
||||
Mempool.prototype.limitSize = function limitSize(entryHash) {
|
||||
var trimmed = false;
|
||||
var i, hashes, hash, end, entry;
|
||||
|
||||
@ -717,7 +717,7 @@ Mempool.prototype._addTX = co(function* _addTX(tx) {
|
||||
yield this.addEntry(entry);
|
||||
|
||||
// Trim size if we're too big.
|
||||
if (this.limitMempoolSize(hash)) {
|
||||
if (this.limitSize(hash)) {
|
||||
throw new VerifyError(tx,
|
||||
'insufficientfee',
|
||||
'mempool full',
|
||||
@ -911,9 +911,9 @@ Mempool.prototype.verify = co(function* verify(entry) {
|
||||
// Script verification.
|
||||
try {
|
||||
yield this.verifyInputs(tx, flags1);
|
||||
} catch (error) {
|
||||
} catch (err) {
|
||||
if (tx.hasWitness())
|
||||
throw error;
|
||||
throw err;
|
||||
|
||||
// Try without segwit and cleanstack.
|
||||
result = yield this.verifyResult(tx, flags2);
|
||||
@ -921,7 +921,7 @@ Mempool.prototype.verify = co(function* verify(entry) {
|
||||
// If it failed, the first verification
|
||||
// was the only result we needed.
|
||||
if (!result)
|
||||
throw error;
|
||||
throw err;
|
||||
|
||||
// If it succeeded, segwit may be causing the
|
||||
// failure. Try with segwit but without cleanstack.
|
||||
@ -929,11 +929,11 @@ Mempool.prototype.verify = co(function* verify(entry) {
|
||||
|
||||
// Cleanstack was causing the failure.
|
||||
if (result)
|
||||
throw error;
|
||||
throw err;
|
||||
|
||||
// Do not insert into reject cache.
|
||||
error.malleated = true;
|
||||
throw error;
|
||||
err.malleated = true;
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Paranoid checks.
|
||||
@ -1313,89 +1313,6 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, missing) {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Spend coins for transaction.
|
||||
* @param {TX} tx
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Mempool.prototype.injectCoins = function injectCoins(tx, view) {
|
||||
var missing = [];
|
||||
var i, input, prevout, coin;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
prevout = input.prevout;
|
||||
coin = view.getCoin(prevout.hash, prevout.index);
|
||||
|
||||
if (!coin) {
|
||||
missing.push(prevout.hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = coin;
|
||||
}
|
||||
|
||||
return missing;
|
||||
};
|
||||
|
||||
/**
|
||||
* Store an orphaned transaction.
|
||||
* @param {TX} tx
|
||||
*/
|
||||
|
||||
Mempool.prototype.maybeStoreOrphan = function maybeStoreOrphan(tx) {
|
||||
var missing = {};
|
||||
var i, hash, input, prev;
|
||||
|
||||
if (tx.getWeight() > constants.tx.MAX_WEIGHT) {
|
||||
this.logger.debug('Ignoring large orphan: %s', tx.txid());
|
||||
if (!tx.hasWitness())
|
||||
this.rejects.add(tx.hash());
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
|
||||
if (input.coin)
|
||||
continue;
|
||||
|
||||
if (this.hasReject(input.prevout.hash)) {
|
||||
this.logger.debug('Not storing orphan %s (rejected parents).', tx.txid());
|
||||
this.rejects.add(tx.hash());
|
||||
return;
|
||||
}
|
||||
|
||||
missing[input.prevout.hash] = true;
|
||||
}
|
||||
|
||||
hash = tx.hash('hex');
|
||||
missing = Object.keys(missing);
|
||||
|
||||
assert(missing.length > 0);
|
||||
|
||||
for (i = 0; i < missing.length; i++) {
|
||||
prev = missing[i];
|
||||
|
||||
if (!this.waiting[prev])
|
||||
this.waiting[prev] = [];
|
||||
|
||||
this.waiting[prev].push(hash);
|
||||
}
|
||||
|
||||
this.orphans[hash] = new Orphan(tx, missing.length);
|
||||
this.totalOrphans++;
|
||||
|
||||
this.logger.debug('Added orphan %s to mempool.', tx.txid());
|
||||
|
||||
this.emit('add orphan', tx);
|
||||
|
||||
this.limitOrphans();
|
||||
|
||||
return missing;
|
||||
};
|
||||
|
||||
/**
|
||||
* Potentially resolve any transactions
|
||||
* that redeem the passed-in transaction.
|
||||
@ -1521,165 +1438,6 @@ Mempool.prototype.isDoubleSpend = function isDoubleSpend(tx) {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill a transaction with all available transaction outputs
|
||||
* in the mempool. This differs from {@link Mempool#fillCoins}
|
||||
* in that it will fill with all historical coins and not
|
||||
* just unspent coins.
|
||||
* @param {TX} tx
|
||||
*/
|
||||
|
||||
Mempool.prototype.fillHistory = function fillHistory(tx) {
|
||||
var found = true;
|
||||
var i, input, prevout, prev;
|
||||
|
||||
if (tx.isCoinbase())
|
||||
return false;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
prevout = input.prevout;
|
||||
prev = this.getTX(prevout.hash);
|
||||
|
||||
if (!prev) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prevout.index >= prev.outputs.length) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = Coin.fromTX(prev, prevout.index);
|
||||
}
|
||||
|
||||
return found;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill a transaction with all available (unspent) coins
|
||||
* in the mempool.
|
||||
* @param {TX} tx
|
||||
*/
|
||||
|
||||
Mempool.prototype.fillCoins = function fillCoins(tx) {
|
||||
var found = true;
|
||||
var i, input, prevout, coin;
|
||||
|
||||
if (tx.isCoinbase())
|
||||
return false;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
prevout = input.prevout;
|
||||
coin = this.getCoin(prevout.hash, prevout.index);
|
||||
|
||||
if (!coin) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = coin;
|
||||
}
|
||||
|
||||
return found;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill transaction with all unspent _and spent_
|
||||
* coins. Similar to {@link Mempool#fillHistory}
|
||||
* except that it will also fill with coins
|
||||
* from the blockchain as well.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
Mempool.prototype.fillAllHistory = function fillAllHistory(tx) {
|
||||
this.fillHistory(tx);
|
||||
|
||||
if (tx.hasCoins())
|
||||
return Promise.resolve(tx);
|
||||
|
||||
return this.chain.db.fillHistory(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill transaction with all unspent
|
||||
* coins. Similar to {@link Mempool#fillCoins}
|
||||
* except that it will also fill with coins
|
||||
* from the blockchain as well.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
Mempool.prototype.fillAllCoins = co(function* fillAllCoins(tx) {
|
||||
var found = true;
|
||||
var i, input, hash, index, coin;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
hash = input.prevout.hash;
|
||||
index = input.prevout.index;
|
||||
|
||||
coin = this.getCoin(hash, index);
|
||||
|
||||
if (coin) {
|
||||
input.coin = coin;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.isSpent(hash, index)) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
coin = yield this.chain.db.getCoin(hash, index);
|
||||
|
||||
if (!coin) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = coin;
|
||||
}
|
||||
|
||||
return found;
|
||||
});
|
||||
|
||||
/**
|
||||
* Get coin viewpoint.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link CoinView}.
|
||||
*/
|
||||
|
||||
Mempool.prototype.getCoinViewSlow = co(function* getCoinViewSlow(tx) {
|
||||
var view = yield this.chain.db.getCoinView(tx);
|
||||
var entries = view.toArray();
|
||||
var i, coins, entry;
|
||||
|
||||
for (i = 0; i < entries.length; i++) {
|
||||
coins = entries[i];
|
||||
|
||||
if (!coins.isEmpty())
|
||||
continue;
|
||||
|
||||
entry = this.getEntry(coins.hash);
|
||||
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
view.addTX(entry.tx, -1);
|
||||
}
|
||||
|
||||
return view;
|
||||
});
|
||||
|
||||
/**
|
||||
* Get coin viewpoint.
|
||||
* @param {TX} tx
|
||||
@ -1715,6 +1473,32 @@ Mempool.prototype.getCoinView = co(function* getCoinView(tx) {
|
||||
return view;
|
||||
});
|
||||
|
||||
/**
|
||||
* Spend coins for transaction.
|
||||
* @param {TX} tx
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Mempool.prototype.injectCoins = function injectCoins(tx, view) {
|
||||
var missing = [];
|
||||
var i, input, prevout, coin;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
prevout = input.prevout;
|
||||
coin = view.getCoin(prevout.hash, prevout.index);
|
||||
|
||||
if (!coin) {
|
||||
missing.push(prevout.hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = coin;
|
||||
}
|
||||
|
||||
return missing;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a snapshot of all transaction hashes in the mempool. Used
|
||||
* for generating INV packets in response to MEMPOOL packets.
|
||||
@ -1960,6 +1744,106 @@ Mempool.prototype.getSize = function getSize() {
|
||||
return this.size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fill transaction with all unspent _and spent_
|
||||
* coins. Similar to {@link Mempool#fillHistory}
|
||||
* except that it will also fill with coins
|
||||
* from the blockchain as well.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
Mempool.prototype.fillHistory = co(function* fillHistory(tx) {
|
||||
var found = true;
|
||||
var i, input, prevout, prev;
|
||||
|
||||
if (tx.isCoinbase())
|
||||
return found;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
prevout = input.prevout;
|
||||
|
||||
if (input.coin)
|
||||
continue;
|
||||
|
||||
prev = this.getTX(prevout.hash);
|
||||
|
||||
if (prev) {
|
||||
if (prevout.index >= prev.outputs.length) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
input.coin = Coin.fromTX(prev, prevout.index);
|
||||
continue;
|
||||
}
|
||||
|
||||
prev = yield this.chain.db.getTX(prevout.hash);
|
||||
|
||||
if (!prev || prevout.index >= prev.outputs.length) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = Coin.fromTX(prev, prevout.index);
|
||||
}
|
||||
|
||||
return found;
|
||||
});
|
||||
|
||||
/**
|
||||
* Fill transaction with all unspent
|
||||
* coins. Similar to {@link Mempool#fillCoins}
|
||||
* except that it will also fill with coins
|
||||
* from the blockchain as well.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
*/
|
||||
|
||||
Mempool.prototype.fillCoins = co(function* fillCoins(tx) {
|
||||
var found = true;
|
||||
var i, input, hash, index, coin;
|
||||
|
||||
if (tx.isCoinbase())
|
||||
return found;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
hash = input.prevout.hash;
|
||||
index = input.prevout.index;
|
||||
|
||||
if (input.coin)
|
||||
continue;
|
||||
|
||||
coin = this.getCoin(hash, index);
|
||||
|
||||
if (coin) {
|
||||
input.coin = coin;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.isSpent(hash, index)) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
coin = yield this.chain.db.getCoin(hash, index);
|
||||
|
||||
if (!coin) {
|
||||
input.coin = null;
|
||||
found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
input.coin = coin;
|
||||
}
|
||||
|
||||
return found;
|
||||
});
|
||||
|
||||
/**
|
||||
* Address Index
|
||||
*/
|
||||
|
||||
@ -422,8 +422,10 @@ FullNode.prototype.getCoinsByAddress = co(function* getCoinsByAddress(addresses)
|
||||
coin = blockCoins[i];
|
||||
spent = this.mempool.isSpent(coin.hash, coin.index);
|
||||
|
||||
if (!spent)
|
||||
coins.push(coin);
|
||||
if (spent)
|
||||
continue;
|
||||
|
||||
coins.push(coin);
|
||||
}
|
||||
|
||||
return coins;
|
||||
@ -492,7 +494,7 @@ FullNode.prototype.isSpent = function isSpent(hash, index) {
|
||||
*/
|
||||
|
||||
FullNode.prototype.fillCoins = function fillCoins(tx) {
|
||||
return this.mempool.fillAllCoins(tx);
|
||||
return this.mempool.fillCoins(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -503,7 +505,7 @@ FullNode.prototype.fillCoins = function fillCoins(tx) {
|
||||
*/
|
||||
|
||||
FullNode.prototype.fillHistory = function fillHistory(tx) {
|
||||
return this.mempool.fillAllHistory(tx);
|
||||
return this.mempool.fillHistory(tx);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user