Merge pull request #4515 from mempool/mononaut/faster-goggles
Faster goggles
This commit is contained in:
commit
30da419fb4
@ -222,7 +222,25 @@ export class Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getTransactionFlags(tx: TransactionExtended): number {
|
static getTransactionFlags(tx: TransactionExtended): number {
|
||||||
let flags = 0n;
|
let flags = tx.flags ? BigInt(tx.flags) : 0n;
|
||||||
|
|
||||||
|
// Update variable flags (CPFP, RBF)
|
||||||
|
if (tx.ancestors?.length) {
|
||||||
|
flags |= TransactionFlags.cpfp_child;
|
||||||
|
}
|
||||||
|
if (tx.descendants?.length) {
|
||||||
|
flags |= TransactionFlags.cpfp_parent;
|
||||||
|
}
|
||||||
|
if (tx.replacement) {
|
||||||
|
flags |= TransactionFlags.replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already processed static flags, no need to do it again
|
||||||
|
if (tx.flags) {
|
||||||
|
return Number(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process static flags
|
||||||
if (tx.version === 1) {
|
if (tx.version === 1) {
|
||||||
flags |= TransactionFlags.v1;
|
flags |= TransactionFlags.v1;
|
||||||
} else if (tx.version === 2) {
|
} else if (tx.version === 2) {
|
||||||
@ -306,15 +324,7 @@ export class Common {
|
|||||||
if (hasFakePubkey) {
|
if (hasFakePubkey) {
|
||||||
flags |= TransactionFlags.fake_pubkey;
|
flags |= TransactionFlags.fake_pubkey;
|
||||||
}
|
}
|
||||||
if (tx.ancestors?.length) {
|
|
||||||
flags |= TransactionFlags.cpfp_child;
|
|
||||||
}
|
|
||||||
if (tx.descendants?.length) {
|
|
||||||
flags |= TransactionFlags.cpfp_parent;
|
|
||||||
}
|
|
||||||
if (rbfCache.getRbfTree(tx.txid)) {
|
|
||||||
flags |= TransactionFlags.replacement;
|
|
||||||
}
|
|
||||||
// fast but bad heuristic to detect possible coinjoins
|
// fast but bad heuristic to detect possible coinjoins
|
||||||
// (at least 5 inputs and 5 outputs, less than half of which are unique amounts, with no address reuse)
|
// (at least 5 inputs and 5 outputs, less than half of which are unique amounts, with no address reuse)
|
||||||
const addressReuse = Object.values(reusedAddresses).reduce((acc, count) => Math.max(acc, count), 0) > 1;
|
const addressReuse = Object.values(reusedAddresses).reduce((acc, count) => Math.max(acc, count), 0) > 1;
|
||||||
@ -335,6 +345,7 @@ export class Common {
|
|||||||
|
|
||||||
static classifyTransaction(tx: TransactionExtended): TransactionClassified {
|
static classifyTransaction(tx: TransactionExtended): TransactionClassified {
|
||||||
const flags = this.getTransactionFlags(tx);
|
const flags = this.getTransactionFlags(tx);
|
||||||
|
tx.flags = flags;
|
||||||
return {
|
return {
|
||||||
...this.stripTransaction(tx),
|
...this.stripTransaction(tx),
|
||||||
flags,
|
flags,
|
||||||
|
@ -256,6 +256,7 @@ class DiskCache {
|
|||||||
txs: rbfData.rbf.txs.map(([txid, entry]) => ({ value: entry })),
|
txs: rbfData.rbf.txs.map(([txid, entry]) => ({ value: entry })),
|
||||||
trees: rbfData.rbf.trees,
|
trees: rbfData.rbf.trees,
|
||||||
expiring: rbfData.rbf.expiring.map(([txid, value]) => ({ key: txid, value })),
|
expiring: rbfData.rbf.expiring.map(([txid, value]) => ({ key: txid, value })),
|
||||||
|
mempool: memPool.getMempool(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -97,6 +97,8 @@ class RbfCache {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newTxExtended.replacement = true;
|
||||||
|
|
||||||
const newTx = Common.stripTransaction(newTxExtended) as RbfTransaction;
|
const newTx = Common.stripTransaction(newTxExtended) as RbfTransaction;
|
||||||
const newTime = newTxExtended.firstSeen || (Date.now() / 1000);
|
const newTime = newTxExtended.firstSeen || (Date.now() / 1000);
|
||||||
newTx.rbf = newTxExtended.vin.some((v) => v.sequence < 0xfffffffe);
|
newTx.rbf = newTxExtended.vin.some((v) => v.sequence < 0xfffffffe);
|
||||||
@ -368,14 +370,14 @@ class RbfCache {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async load({ txs, trees, expiring }): Promise<void> {
|
public async load({ txs, trees, expiring, mempool }): Promise<void> {
|
||||||
try {
|
try {
|
||||||
txs.forEach(txEntry => {
|
txs.forEach(txEntry => {
|
||||||
this.txs.set(txEntry.value.txid, txEntry.value);
|
this.txs.set(txEntry.value.txid, txEntry.value);
|
||||||
});
|
});
|
||||||
this.staleCount = 0;
|
this.staleCount = 0;
|
||||||
for (const deflatedTree of trees) {
|
for (const deflatedTree of trees) {
|
||||||
await this.importTree(deflatedTree.root, deflatedTree.root, deflatedTree, this.txs);
|
await this.importTree(mempool, deflatedTree.root, deflatedTree.root, deflatedTree, this.txs);
|
||||||
}
|
}
|
||||||
expiring.forEach(expiringEntry => {
|
expiring.forEach(expiringEntry => {
|
||||||
if (this.txs.has(expiringEntry.key)) {
|
if (this.txs.has(expiringEntry.key)) {
|
||||||
@ -413,7 +415,7 @@ class RbfCache {
|
|||||||
return deflated;
|
return deflated;
|
||||||
}
|
}
|
||||||
|
|
||||||
async importTree(root, txid, deflated, txs: Map<string, MempoolTransactionExtended>, mined: boolean = false): Promise<RbfTree | void> {
|
async importTree(mempool, root, txid, deflated, txs: Map<string, MempoolTransactionExtended>, mined: boolean = false): Promise<RbfTree | void> {
|
||||||
const treeInfo = deflated[txid];
|
const treeInfo = deflated[txid];
|
||||||
const replaces: RbfTree[] = [];
|
const replaces: RbfTree[] = [];
|
||||||
|
|
||||||
@ -426,9 +428,12 @@ class RbfCache {
|
|||||||
|
|
||||||
// recursively reconstruct child trees
|
// recursively reconstruct child trees
|
||||||
for (const childId of treeInfo.replaces) {
|
for (const childId of treeInfo.replaces) {
|
||||||
const replaced = await this.importTree(root, childId, deflated, txs, mined);
|
const replaced = await this.importTree(mempool, root, childId, deflated, txs, mined);
|
||||||
if (replaced) {
|
if (replaced) {
|
||||||
this.replacedBy.set(replaced.tx.txid, txid);
|
this.replacedBy.set(replaced.tx.txid, txid);
|
||||||
|
if (mempool[replaced.tx.txid]) {
|
||||||
|
mempool[replaced.tx.txid].replacement = true;
|
||||||
|
}
|
||||||
replaces.push(replaced);
|
replaces.push(replaced);
|
||||||
if (replaced.mined) {
|
if (replaced.mined) {
|
||||||
mined = true;
|
mined = true;
|
||||||
|
@ -222,6 +222,7 @@ class RedisCache {
|
|||||||
txs: rbfTxs,
|
txs: rbfTxs,
|
||||||
trees: rbfTrees.map(loadedTree => { loadedTree.value.key = loadedTree.key; return loadedTree.value; }),
|
trees: rbfTrees.map(loadedTree => { loadedTree.value.key = loadedTree.key; return loadedTree.value; }),
|
||||||
expiring: rbfExpirations,
|
expiring: rbfExpirations,
|
||||||
|
mempool: memPool.getMempool(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,9 @@ export interface TransactionExtended extends IEsploraApi.Transaction {
|
|||||||
vsize: number,
|
vsize: number,
|
||||||
};
|
};
|
||||||
acceleration?: boolean;
|
acceleration?: boolean;
|
||||||
|
replacement?: boolean;
|
||||||
uid?: number;
|
uid?: number;
|
||||||
|
flags?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MempoolTransactionExtended extends TransactionExtended {
|
export interface MempoolTransactionExtended extends TransactionExtended {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user