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);
|
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
|
* Check to see if a coin has been spent. This differs from
|
||||||
* {@link ChainDB#isSpent} in that it actually maintains a
|
* {@link ChainDB#isSpent} in that it actually maintains a
|
||||||
@ -1689,6 +1711,8 @@ class Mempool extends EventEmitter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get coin viewpoint (lock).
|
* Get coin viewpoint (lock).
|
||||||
|
* Note: this does not return
|
||||||
|
* historical view of coins from the indexers.
|
||||||
* @method
|
* @method
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
* @returns {Promise} - Returns {@link CoinView}.
|
* @returns {Promise} - Returns {@link CoinView}.
|
||||||
@ -1697,12 +1721,40 @@ class Mempool extends EventEmitter {
|
|||||||
async getSpentView(tx) {
|
async getSpentView(tx) {
|
||||||
const unlock = await this.locker.lock();
|
const unlock = await this.locker.lock();
|
||||||
try {
|
try {
|
||||||
return await this.getCoinView(tx);
|
return await this._getSpentView(tx);
|
||||||
} finally {
|
} finally {
|
||||||
unlock();
|
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).
|
* Get coin viewpoint (no lock).
|
||||||
* @method
|
* @method
|
||||||
@ -1718,7 +1770,7 @@ class Mempool extends EventEmitter {
|
|||||||
const tx = this.getTX(hash);
|
const tx = this.getTX(hash);
|
||||||
|
|
||||||
if (tx) {
|
if (tx) {
|
||||||
if (index < tx.outputs.length)
|
if (this.hasCoin(hash, index))
|
||||||
view.addIndex(tx, index, -1);
|
view.addIndex(tx, index, -1);
|
||||||
continue;
|
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 () => {
|
it('should handle locktime', async () => {
|
||||||
const key = KeyRing.generate();
|
const key = KeyRing.generate();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user