Use minfee node to limit gbt input size
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import config from '../config';
|
||||
import bitcoinApi from './bitcoin/bitcoin-api-factory';
|
||||
import { MempoolTransactionExtended, TransactionExtended, VbytesPerSecond } from '../mempool.interfaces';
|
||||
import { MempoolTransactionExtended, TransactionExtended, VbytesPerSecond, GbtCandidates } from '../mempool.interfaces';
|
||||
import logger from '../logger';
|
||||
import { Common } from './common';
|
||||
import transactionUtils from './transaction-utils';
|
||||
@@ -11,18 +11,21 @@ import bitcoinSecondClient from './bitcoin/bitcoin-second-client';
|
||||
import rbfCache from './rbf-cache';
|
||||
import { Acceleration } from './services/acceleration';
|
||||
import redisCache from './redis-cache';
|
||||
import blocks from './blocks';
|
||||
|
||||
class Mempool {
|
||||
private inSync: boolean = false;
|
||||
private mempoolCacheDelta: number = -1;
|
||||
private mempoolCache: { [txId: string]: MempoolTransactionExtended } = {};
|
||||
private mempoolCandidates: { [txid: string ]: boolean } = {};
|
||||
private minFeeMempool: { [txId: string]: boolean } = {};
|
||||
private spendMap = new Map<string, MempoolTransactionExtended>();
|
||||
private mempoolInfo: IBitcoinApi.MempoolInfo = { loaded: false, size: 0, bytes: 0, usage: 0, total_fee: 0,
|
||||
maxmempool: 300000000, mempoolminfee: Common.isLiquid() ? 0.00000100 : 0.00001000, minrelaytxfee: Common.isLiquid() ? 0.00000100 : 0.00001000 };
|
||||
private mempoolChangedCallback: ((newMempool: {[txId: string]: MempoolTransactionExtended; }, newTransactions: MempoolTransactionExtended[],
|
||||
deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => void) | undefined;
|
||||
private $asyncMempoolChangedCallback: ((newMempool: {[txId: string]: MempoolTransactionExtended; }, mempoolSize: number, newTransactions: MempoolTransactionExtended[],
|
||||
deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => Promise<void>) | undefined;
|
||||
deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[], candidates?: GbtCandidates) => Promise<void>) | undefined;
|
||||
|
||||
private accelerations: { [txId: string]: Acceleration } = {};
|
||||
|
||||
@@ -40,6 +43,8 @@ class Mempool {
|
||||
private missingTxCount = 0;
|
||||
private mainLoopTimeout: number = 120000;
|
||||
|
||||
public limitGBT = config.MEMPOOL.USE_SECOND_NODE_FOR_MINFEE && config.MEMPOOL.LIMIT_GBT;
|
||||
|
||||
constructor() {
|
||||
setInterval(this.updateTxPerSecond.bind(this), 1000);
|
||||
}
|
||||
@@ -74,7 +79,8 @@ class Mempool {
|
||||
}
|
||||
|
||||
public setAsyncMempoolChangedCallback(fn: (newMempool: { [txId: string]: MempoolTransactionExtended; }, mempoolSize: number,
|
||||
newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => Promise<void>): void {
|
||||
newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[],
|
||||
candidates?: GbtCandidates) => Promise<void>): void {
|
||||
this.$asyncMempoolChangedCallback = fn;
|
||||
}
|
||||
|
||||
@@ -117,7 +123,7 @@ class Mempool {
|
||||
this.mempoolChangedCallback(this.mempoolCache, [], [], []);
|
||||
}
|
||||
if (this.$asyncMempoolChangedCallback) {
|
||||
await this.$asyncMempoolChangedCallback(this.mempoolCache, count, [], [], []);
|
||||
await this.$asyncMempoolChangedCallback(this.mempoolCache, count, [], [], [], this.limitGBT ? { txs: {}, added: [], removed: [] } : undefined);
|
||||
}
|
||||
this.addToSpendMap(Object.values(this.mempoolCache));
|
||||
}
|
||||
@@ -160,6 +166,10 @@ class Mempool {
|
||||
return newTransactions;
|
||||
}
|
||||
|
||||
public getMempoolCandidates(): { [txid: string]: boolean } {
|
||||
return this.mempoolCandidates;
|
||||
}
|
||||
|
||||
public async $updateMemPoolInfo() {
|
||||
this.mempoolInfo = await this.$getMempoolInfo();
|
||||
}
|
||||
@@ -189,7 +199,7 @@ class Mempool {
|
||||
return txTimes;
|
||||
}
|
||||
|
||||
public async $updateMempool(transactions: string[], accelerations: Acceleration[] | null, pollRate: number): Promise<void> {
|
||||
public async $updateMempool(transactions: string[], accelerations: Acceleration[] | null, minFeeMempool: string[], minFeeTip: number, pollRate: number): Promise<void> {
|
||||
logger.debug(`Updating mempool...`);
|
||||
|
||||
// warn if this run stalls the main loop for more than 2 minutes
|
||||
@@ -311,6 +321,8 @@ class Mempool {
|
||||
}, 1000 * 60 * config.MEMPOOL.CLEAR_PROTECTION_MINUTES);
|
||||
}
|
||||
|
||||
const candidates = await this.getNextCandidates(minFeeMempool, minFeeTip);
|
||||
|
||||
const deletedTransactions: MempoolTransactionExtended[] = [];
|
||||
|
||||
if (this.mempoolProtection !== 1) {
|
||||
@@ -341,12 +353,14 @@ class Mempool {
|
||||
|
||||
this.mempoolCacheDelta = Math.abs(transactions.length - newMempoolSize);
|
||||
|
||||
const candidatesChanged = candidates?.added?.length || candidates?.removed?.length;
|
||||
|
||||
if (this.mempoolChangedCallback && (hasChange || deletedTransactions.length)) {
|
||||
this.mempoolChangedCallback(this.mempoolCache, newTransactions, deletedTransactions, accelerationDelta);
|
||||
}
|
||||
if (this.$asyncMempoolChangedCallback && (hasChange || deletedTransactions.length)) {
|
||||
if (this.$asyncMempoolChangedCallback && (hasChange || deletedTransactions.length || candidatesChanged)) {
|
||||
this.updateTimerProgress(timer, 'running async mempool callback');
|
||||
await this.$asyncMempoolChangedCallback(this.mempoolCache, newMempoolSize, newTransactions, deletedTransactions, accelerationDelta);
|
||||
await this.$asyncMempoolChangedCallback(this.mempoolCache, newMempoolSize, newTransactions, deletedTransactions, accelerationDelta, candidates);
|
||||
this.updateTimerProgress(timer, 'completed async mempool callback');
|
||||
}
|
||||
|
||||
@@ -432,6 +446,48 @@ class Mempool {
|
||||
}
|
||||
}
|
||||
|
||||
public async getNextCandidates(minFeeTransactions: string[], blockHeight: number): Promise<GbtCandidates | undefined> {
|
||||
if (this.limitGBT) {
|
||||
const newCandidateTxMap = {};
|
||||
this.minFeeMempool = {};
|
||||
for (const txid of minFeeTransactions) {
|
||||
if (this.mempoolCache[txid]) {
|
||||
newCandidateTxMap[txid] = true;
|
||||
}
|
||||
this.minFeeMempool[txid] = true;
|
||||
}
|
||||
const removed: MempoolTransactionExtended[] = [];
|
||||
const added: MempoolTransactionExtended[] = [];
|
||||
// don't prematurely remove txs included in a new block
|
||||
if (blockHeight > blocks.getCurrentBlockHeight()) {
|
||||
for (const txid of Object.keys(this.mempoolCandidates)) {
|
||||
newCandidateTxMap[txid] = true;
|
||||
}
|
||||
} else {
|
||||
for (const txid of Object.keys(this.mempoolCandidates)) {
|
||||
if (!newCandidateTxMap[txid]) {
|
||||
const tx = this.mempoolCache[txid];
|
||||
removed.push(tx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const txid of Object.keys(newCandidateTxMap)) {
|
||||
if (!this.mempoolCandidates[txid]) {
|
||||
const tx = this.mempoolCache[txid];
|
||||
added.push(tx);
|
||||
}
|
||||
}
|
||||
|
||||
this.mempoolCandidates = newCandidateTxMap;
|
||||
return {
|
||||
txs: this.mempoolCandidates,
|
||||
added,
|
||||
removed
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private startTimer() {
|
||||
const state: any = {
|
||||
start: Date.now(),
|
||||
|
||||
Reference in New Issue
Block a user