mirror of
https://github.com/mempool/mempool.git
synced 2025-01-19 05:34:03 +01:00
Speed up RBF detection
This commit is contained in:
parent
9da9c2750d
commit
3ec676ca90
@ -61,8 +61,10 @@ export class Common {
|
|||||||
|
|
||||||
static findRbfTransactions(added: MempoolTransactionExtended[], deleted: MempoolTransactionExtended[]): { [txid: string]: MempoolTransactionExtended[] } {
|
static findRbfTransactions(added: MempoolTransactionExtended[], deleted: MempoolTransactionExtended[]): { [txid: string]: MempoolTransactionExtended[] } {
|
||||||
const matches: { [txid: string]: MempoolTransactionExtended[] } = {};
|
const matches: { [txid: string]: MempoolTransactionExtended[] } = {};
|
||||||
added
|
|
||||||
.forEach((addedTx) => {
|
// For small N, a naive nested loop is extremely fast, but it doesn't scale
|
||||||
|
if (added.length < 1000 && deleted.length < 50) {
|
||||||
|
added.forEach((addedTx) => {
|
||||||
const foundMatches = deleted.filter((deletedTx) => {
|
const foundMatches = deleted.filter((deletedTx) => {
|
||||||
// The new tx must, absolutely speaking, pay at least as much fee as the replaced tx.
|
// The new tx must, absolutely speaking, pay at least as much fee as the replaced tx.
|
||||||
return addedTx.fee > deletedTx.fee
|
return addedTx.fee > deletedTx.fee
|
||||||
@ -73,9 +75,40 @@ export class Common {
|
|||||||
addedTx.vin.some((vin) => vin.txid === deletedVin.txid && vin.vout === deletedVin.vout));
|
addedTx.vin.some((vin) => vin.txid === deletedVin.txid && vin.vout === deletedVin.vout));
|
||||||
});
|
});
|
||||||
if (foundMatches?.length) {
|
if (foundMatches?.length) {
|
||||||
matches[addedTx.txid] = foundMatches;
|
matches[addedTx.txid] = [...new Set(foundMatches)];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// for large N, build a lookup table of prevouts we can check in ~constant time
|
||||||
|
const deletedSpendMap: { [txid: string]: { [vout: number]: MempoolTransactionExtended } } = {};
|
||||||
|
for (const tx of deleted) {
|
||||||
|
for (const vin of tx.vin) {
|
||||||
|
if (!deletedSpendMap[vin.txid]) {
|
||||||
|
deletedSpendMap[vin.txid] = {};
|
||||||
|
}
|
||||||
|
deletedSpendMap[vin.txid][vin.vout] = tx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const addedTx of added) {
|
||||||
|
const foundMatches = new Set<MempoolTransactionExtended>();
|
||||||
|
for (const vin of addedTx.vin) {
|
||||||
|
const deletedTx = deletedSpendMap[vin.txid]?.[vin.vout];
|
||||||
|
if (deletedTx && deletedTx.txid !== addedTx.txid
|
||||||
|
// The new tx must, absolutely speaking, pay at least as much fee as the replaced tx.
|
||||||
|
&& addedTx.fee > deletedTx.fee
|
||||||
|
// The new transaction must pay more fee per kB than the replaced tx.
|
||||||
|
&& addedTx.adjustedFeePerVsize > deletedTx.adjustedFeePerVsize
|
||||||
|
) {
|
||||||
|
foundMatches.add(deletedTx);
|
||||||
|
}
|
||||||
|
if (foundMatches.size) {
|
||||||
|
matches[addedTx.txid] = [...foundMatches];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user