Merge pull request #641 from nodar-chkuaselidze/fix/mempool-index
mempool: reflect spent coins in mempool coinview.
This commit is contained in:
commit
6f1a561db5
@ -502,6 +502,28 @@ class Mempool extends EventEmitter {
|
||||
return Coin.fromTX(entry.tx, index, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether coin is still unspent.
|
||||
* @param {Hash} hash
|
||||
* @param {Number} index
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
hasCoin(hash, index) {
|
||||
const entry = this.map.get(hash);
|
||||
|
||||
if (!entry)
|
||||
return false;
|
||||
|
||||
if (this.isSpent(hash, index))
|
||||
return false;
|
||||
|
||||
if (index >= entry.tx.outputs.length)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a coin has been spent. This differs from
|
||||
* {@link ChainDB#isSpent} in that it actually maintains a
|
||||
@ -1689,6 +1711,8 @@ class Mempool extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Get coin viewpoint (lock).
|
||||
* Note: this does not return
|
||||
* historical view of coins from the indexers.
|
||||
* @method
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link CoinView}.
|
||||
@ -1697,12 +1721,40 @@ class Mempool extends EventEmitter {
|
||||
async getSpentView(tx) {
|
||||
const unlock = await this.locker.lock();
|
||||
try {
|
||||
return await this.getCoinView(tx);
|
||||
return await this._getSpentView(tx);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coin viewpoint
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link CoinView}
|
||||
*/
|
||||
|
||||
async _getSpentView(tx) {
|
||||
const view = new CoinView();
|
||||
|
||||
for (const {prevout} of tx.inputs) {
|
||||
const {hash, index} = prevout;
|
||||
const tx = this.getTX(hash);
|
||||
|
||||
if (tx) {
|
||||
if (index < tx.outputs.length)
|
||||
view.addIndex(tx, index, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
const coin = await this.chain.readCoin(prevout);
|
||||
|
||||
if (coin)
|
||||
view.addEntry(prevout, coin);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coin viewpoint (no lock).
|
||||
* @method
|
||||
@ -1718,7 +1770,7 @@ class Mempool extends EventEmitter {
|
||||
const tx = this.getTX(hash);
|
||||
|
||||
if (tx) {
|
||||
if (index < tx.outputs.length)
|
||||
if (this.hasCoin(hash, index))
|
||||
view.addIndex(tx, index, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -177,6 +177,56 @@ describe('Mempool', function() {
|
||||
}));
|
||||
});
|
||||
|
||||
it('should get spend coins and reflect in coinview', async () => {
|
||||
const wallet = new MemWallet();
|
||||
const script = Script.fromAddress(wallet.getAddress());
|
||||
const dummyCoin = dummyInput(script, random.randomBytes(32));
|
||||
|
||||
// spend first output
|
||||
const mtx1 = new MTX();
|
||||
mtx1.addOutput(wallet.getAddress(), 50000);
|
||||
mtx1.addCoin(dummyCoin);
|
||||
wallet.sign(mtx1);
|
||||
|
||||
// spend second tx
|
||||
const tx1 = mtx1.toTX();
|
||||
const coin1 = Coin.fromTX(tx1, 0, -1);
|
||||
const mtx2 = new MTX();
|
||||
|
||||
mtx2.addOutput(wallet.getAddress(), 10000);
|
||||
mtx2.addOutput(wallet.getAddress(), 30000); // 10k fee..
|
||||
mtx2.addCoin(coin1);
|
||||
|
||||
wallet.sign(mtx2);
|
||||
|
||||
const tx2 = mtx2.toTX();
|
||||
|
||||
await mempool.addTX(tx1);
|
||||
|
||||
{
|
||||
const view = await mempool.getCoinView(tx2);
|
||||
assert(view.hasEntry(coin1));
|
||||
}
|
||||
|
||||
await mempool.addTX(tx2);
|
||||
|
||||
// we should not have coins available in the mempool for these txs.
|
||||
{
|
||||
const view = await mempool.getCoinView(tx1);
|
||||
const sview = await mempool.getSpentView(tx1);
|
||||
|
||||
assert(!view.hasEntry(dummyCoin));
|
||||
assert(sview.hasEntry(dummyCoin));
|
||||
}
|
||||
|
||||
{
|
||||
const view = await mempool.getCoinView(tx2);
|
||||
const sview = await mempool.getSpentView(tx2);
|
||||
assert(!view.hasEntry(coin1));
|
||||
assert(sview.hasEntry(coin1));
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle locktime', async () => {
|
||||
const key = KeyRing.generate();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user