Merge pull request #641 from nodar-chkuaselidze/fix/mempool-index

mempool: reflect spent coins in mempool coinview.
This commit is contained in:
Javed Khan 2019-01-21 18:52:34 +05:30 committed by GitHub
commit 6f1a561db5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 2 deletions

View File

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

View File

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