Skip to content

Commit 18ffda1

Browse files
feat(sync): prune mempool transactions and coins when conflicting ones come in
1 parent e9f816d commit 18ffda1

3 files changed

Lines changed: 48 additions & 3 deletions

File tree

packages/bitcore-node/src/models/coin.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ export enum SpentHeightIndicators {
3434
/**
3535
* The coin is unspent, and no transactions spending it have been seen.
3636
*/
37-
unspent = -2
37+
unspent = -2,
38+
/**
39+
* The coin was minted by a transaction which can no longer confirm.
40+
*/
41+
conflicting = -3,
3842
}
3943

4044
@LoggifyClass
@@ -72,7 +76,7 @@ class Coin extends BaseModel<ICoin> {
7276

7377
getBalance(params: { query: any }) {
7478
let { query } = params;
75-
query = Object.assign(query, { spentHeight: { $lt: 0 } });
79+
query = Object.assign(query, { spentHeight: { $lt: SpentHeightIndicators.minimum }, mintHeight: { $gt: SpentHeightIndicators.conflicting } });
7680
return this.collection
7781
.aggregate<{ balance: number }>([
7882
{ $match: query },

packages/bitcore-node/src/models/transaction.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export class Transaction extends BaseModel<ITransaction> {
6262
}) {
6363
const mintOps = await this.getMintOps(params);
6464
const spendOps = this.getSpendOps({ ...params, mintOps });
65+
this.pruneMempool({...params, mintOps, spendOps});
6566

6667
logger.debug('Minting Coins', mintOps.length);
6768
if (mintOps.length) {
@@ -383,6 +384,46 @@ export class Transaction extends BaseModel<ITransaction> {
383384
return spendOps;
384385
}
385386

387+
async pruneMempool(params: {
388+
txs: Array<Bitcoin.Transaction>;
389+
height: number;
390+
parentChain?: string;
391+
forkHeight?: number;
392+
chain: string;
393+
network: string;
394+
mintOps: Array<any>;
395+
spendOps: Array<any>;
396+
initialSyncComplete: boolean;
397+
[rest: string]: any;
398+
}) {
399+
const { chain, network, spendOps, initialSyncComplete } = params;
400+
if (!initialSyncComplete || !spendOps.length) {
401+
return;
402+
}
403+
const spentCoinsQuery = {
404+
chain, network, spentHeight: SpentHeightIndicators.pending, $or: spendOps.map(spendOp => {
405+
return {
406+
mintTxid: spendOp.updateOne.filter.mintTxid,
407+
mintIndex: spendOp.updateOne.filter.mintIndex,
408+
spentTxid: { $ne: spendOp.updateOne.update.$set.spentTxid }
409+
}
410+
})
411+
};
412+
const spendingCoins = await CoinModel.collection.find(spentCoinsQuery).toArray();
413+
if (spendingCoins.length) {
414+
let prunedTxs = {};
415+
for (const coin of spendingCoins) {
416+
prunedTxs[coin.spentTxid] = true;
417+
}
418+
prunedTxs = Object.keys(prunedTxs);
419+
await Promise.all([
420+
this.collection.update({ txid: { $in: prunedTxs } }, { $set: { blockHeight: SpentHeightIndicators.conflicting } }, { w: 0, j: false, multi: true }),
421+
CoinModel.collection.update({ mintTxid: { $in: prunedTxs } }, { $set: { mintHeight: SpentHeightIndicators.conflicting } }, { w: 0, j: false, multi: true })
422+
]);
423+
}
424+
return;
425+
}
426+
386427
getTransactions(params: { query: any; options: StreamingFindOptions<ITransaction> }) {
387428
let originalQuery = params.query;
388429
const { query, options } = Storage.getFindOptions(this, params.options);

packages/bitcore-node/src/providers/chain-state/internal/internal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ export class InternalStateProvider implements CSP.IChainStateService {
330330

331331
async streamWalletUtxos(params: CSP.StreamWalletUtxosParams) {
332332
const { wallet, limit, args = {}, stream } = params;
333-
let query: any = { wallets: wallet._id };
333+
let query: any = { wallets: wallet._id, mintHeight: { $gt: SpentHeightIndicators.conflicting } };
334334
if (args.includeSpent !== 'true') {
335335
query.spentHeight = { $lt: SpentHeightIndicators.pending };
336336
}

0 commit comments

Comments
 (0)