- Effective fee rate |
+ Accelerated fee rate |
+ Effective fee rate |
diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts
index e856f34eb..f1d218a79 100644
--- a/frontend/src/app/components/transaction/transaction.component.ts
+++ b/frontend/src/app/components/transaction/transaction.component.ts
@@ -183,6 +183,9 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
} else {
this.tx.effectiveFeePerVsize = cpfpInfo.effectiveFeePerVsize;
}
+ if (cpfpInfo.acceleration) {
+ this.tx.acceleration = cpfpInfo.acceleration;
+ }
this.cpfpInfo = cpfpInfo;
this.hasEffectiveFeeRate = hasRelatives || (this.tx.effectiveFeePerVsize && (Math.abs(this.tx.effectiveFeePerVsize - this.tx.feePerVsize) > 0.01));
diff --git a/frontend/src/app/interfaces/electrs.interface.ts b/frontend/src/app/interfaces/electrs.interface.ts
index df19f7491..5c15b0ae4 100644
--- a/frontend/src/app/interfaces/electrs.interface.ts
+++ b/frontend/src/app/interfaces/electrs.interface.ts
@@ -19,6 +19,7 @@ export interface Transaction {
ancestors?: Ancestor[];
bestDescendant?: BestDescendant | null;
cpfpChecked?: boolean;
+ acceleration?: number;
deleteAfter?: number;
_unblinded?: any;
_deduced?: boolean;
diff --git a/frontend/src/app/interfaces/node-api.interface.ts b/frontend/src/app/interfaces/node-api.interface.ts
index 7e7acfcf3..fe6233866 100644
--- a/frontend/src/app/interfaces/node-api.interface.ts
+++ b/frontend/src/app/interfaces/node-api.interface.ts
@@ -27,6 +27,7 @@ export interface CpfpInfo {
effectiveFeePerVsize?: number;
sigops?: number;
adjustedVsize?: number;
+ acceleration?: number;
}
export interface RbfInfo {
diff --git a/frontend/src/app/interfaces/websocket.interface.ts b/frontend/src/app/interfaces/websocket.interface.ts
index fb3c6d0c2..f8686042b 100644
--- a/frontend/src/app/interfaces/websocket.interface.ts
+++ b/frontend/src/app/interfaces/websocket.interface.ts
@@ -70,7 +70,7 @@ export interface MempoolBlockWithTransactions extends MempoolBlock {
export interface MempoolBlockDelta {
added: TransactionStripped[],
removed: string[],
- changed?: { txid: string, rate: number | undefined }[];
+ changed?: { txid: string, rate: number | undefined, acc: number | undefined }[];
}
export interface MempoolInfo {
@@ -88,6 +88,7 @@ export interface TransactionStripped {
fee: number;
vsize: number;
value: number;
+ acc?: number; // acceleration delta
rate?: number; // effective fee rate
status?: 'found' | 'missing' | 'sigop' | 'fresh' | 'freshcpfp' | 'added' | 'censored' | 'selected' | 'rbf' | 'accelerated';
context?: 'projected' | 'actual';
From c246db1cf9d116a3796d9a5e41c245e6880f9460 Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Tue, 30 May 2023 19:35:39 -0400
Subject: [PATCH 05/73] Refactor acceleration tracking
---
backend/src/api/mempool-blocks.ts | 20 ++++---
backend/src/api/mempool.ts | 72 +++++++++++++++---------
backend/src/api/services/acceleration.ts | 20 +++++++
backend/src/api/websocket-handler.ts | 6 +-
4 files changed, 79 insertions(+), 39 deletions(-)
create mode 100644 backend/src/api/services/acceleration.ts
diff --git a/backend/src/api/mempool-blocks.ts b/backend/src/api/mempool-blocks.ts
index 81f2092a0..bc0def7a8 100644
--- a/backend/src/api/mempool-blocks.ts
+++ b/backend/src/api/mempool-blocks.ts
@@ -5,6 +5,7 @@ import { Common, OnlineFeeStatsCalculator } from './common';
import config from '../config';
import { Worker } from 'worker_threads';
import path from 'path';
+import mempool from './mempool';
const MAX_UINT32 = Math.pow(2, 32) - 1;
@@ -212,9 +213,11 @@ class MempoolBlocks {
// reset mempool short ids
this.resetUids();
for (const tx of Object.values(newMempool)) {
- this.setUid(tx);
+ this.setUid(tx, true);
}
+ const accelerations = mempool.getAccelerations();
+
// prepare a stripped down version of the mempool with only the minimum necessary data
// to reduce the overhead of passing this data to the worker thread
const strippedMempool: Map = new Map();
@@ -222,7 +225,7 @@ class MempoolBlocks {
if (entry.uid !== null && entry.uid !== undefined) {
const stripped = {
uid: entry.uid,
- fee: entry.fee + (entry.acceleration || 0),
+ fee: entry.fee + (accelerations[entry.txid] || 0),
weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
@@ -273,7 +276,7 @@ class MempoolBlocks {
return this.mempoolBlocks;
}
- public async $updateBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, added: MempoolTransactionExtended[], removed: MempoolTransactionExtended[], saveResults: boolean = false): Promise {
+ public async $updateBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, added: MempoolTransactionExtended[], removed: MempoolTransactionExtended[], accelerationDelta: string[] = [], saveResults: boolean = false): Promise {
if (!this.txSelectionWorker) {
// need to reset the worker
await this.$makeBlockTemplates(newMempool, saveResults);
@@ -282,17 +285,20 @@ class MempoolBlocks {
const start = Date.now();
- for (const tx of Object.values(added)) {
+ const accelerations = mempool.getAccelerations();
+ const addedAndChanged: MempoolTransactionExtended[] = accelerationDelta.map(txid => newMempool[txid]).filter(tx => tx != null).concat(added);
+
+ for (const tx of addedAndChanged) {
this.setUid(tx, true);
}
-
const removedUids = removed.map(tx => this.getUid(tx)).filter(uid => uid != null) as number[];
+
// prepare a stripped down version of the mempool with only the minimum necessary data
// to reduce the overhead of passing this data to the worker thread
- const addedStripped: CompactThreadTransaction[] = added.filter(entry => (entry.uid !== null && entry.uid !== undefined)).map(entry => {
+ const addedStripped: CompactThreadTransaction[] = addedAndChanged.filter(entry => entry.uid != null).map(entry => {
return {
uid: entry.uid || 0,
- fee: entry.fee + (entry.acceleration || 0),
+ fee: entry.fee + (accelerations[entry.txid] || 0),
weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts
index 8e350c4fe..7bde83df9 100644
--- a/backend/src/api/mempool.ts
+++ b/backend/src/api/mempool.ts
@@ -1,5 +1,5 @@
import config from '../config';
-import bitcoinApi, { bitcoinCoreApi } from './bitcoin/bitcoin-api-factory';
+import bitcoinApi from './bitcoin/bitcoin-api-factory';
import { MempoolTransactionExtended, TransactionExtended, VbytesPerSecond } from '../mempool.interfaces';
import logger from '../logger';
import { Common } from './common';
@@ -9,7 +9,7 @@ import loadingIndicators from './loading-indicators';
import bitcoinClient from './bitcoin/bitcoin-client';
import bitcoinSecondClient from './bitcoin/bitcoin-second-client';
import rbfCache from './rbf-cache';
-import { IEsploraApi } from './bitcoin/esplora-api.interface';
+import accelerationApi from './services/acceleration';
class Mempool {
private inSync: boolean = false;
@@ -19,9 +19,9 @@ class Mempool {
private mempoolInfo: IBitcoinApi.MempoolInfo = { loaded: false, size: 0, bytes: 0, usage: 0, total_fee: 0,
maxmempool: 300000000, mempoolminfee: 0.00001000, minrelaytxfee: 0.00001000 };
private mempoolChangedCallback: ((newMempool: {[txId: string]: MempoolTransactionExtended; }, newTransactions: MempoolTransactionExtended[],
- deletedTransactions: MempoolTransactionExtended[]) => void) | undefined;
+ deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => void) | undefined;
private $asyncMempoolChangedCallback: ((newMempool: {[txId: string]: MempoolTransactionExtended; }, mempoolSize: number, newTransactions: MempoolTransactionExtended[],
- deletedTransactions: MempoolTransactionExtended[]) => Promise) | undefined;
+ deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => Promise) | undefined;
private accelerations: { [txId: string]: number } = {};
@@ -68,12 +68,12 @@ class Mempool {
}
public setMempoolChangedCallback(fn: (newMempool: { [txId: string]: MempoolTransactionExtended; },
- newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[]) => void): void {
+ newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => void): void {
this.mempoolChangedCallback = fn;
}
public setAsyncMempoolChangedCallback(fn: (newMempool: { [txId: string]: MempoolTransactionExtended; }, mempoolSize: number,
- newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[]) => Promise): void {
+ newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => Promise): void {
this.$asyncMempoolChangedCallback = fn;
}
@@ -98,10 +98,10 @@ class Mempool {
count++;
}
if (this.mempoolChangedCallback) {
- this.mempoolChangedCallback(this.mempoolCache, [], []);
+ this.mempoolChangedCallback(this.mempoolCache, [], [], []);
}
if (this.$asyncMempoolChangedCallback) {
- await this.$asyncMempoolChangedCallback(this.mempoolCache, count, [], []);
+ await this.$asyncMempoolChangedCallback(this.mempoolCache, count, [], [], []);
}
this.addToSpendMap(Object.values(this.mempoolCache));
}
@@ -303,25 +303,19 @@ class Mempool {
const newTransactionsStripped = newTransactions.map((tx) => Common.stripTransaction(tx));
this.latestTransactions = newTransactionsStripped.concat(this.latestTransactions).slice(0, 6);
- const newAccelerations: { txid: string, delta: number }[] = [];
- newTransactions.forEach(tx => {
- if (tx.txid.startsWith('00')) {
- const delta = Math.floor(Math.random() * 100000) + 100000;
- newAccelerations.push({ txid: tx.txid, delta });
- tx.acceleration = delta;
- }
- });
- this.addAccelerations(newAccelerations);
- this.removeAccelerations(deletedTransactions.map(tx => tx.txid));
+ const accelerationDelta = await this.$updateAccelerations();
+ if (accelerationDelta.length) {
+ hasChange = true;
+ }
this.mempoolCacheDelta = Math.abs(transactions.length - newMempoolSize);
if (this.mempoolChangedCallback && (hasChange || deletedTransactions.length)) {
- this.mempoolChangedCallback(this.mempoolCache, newTransactions, deletedTransactions);
+ this.mempoolChangedCallback(this.mempoolCache, newTransactions, deletedTransactions, accelerationDelta);
}
if (this.$asyncMempoolChangedCallback && (hasChange || deletedTransactions.length)) {
this.updateTimerProgress(timer, 'running async mempool callback');
- await this.$asyncMempoolChangedCallback(this.mempoolCache, newMempoolSize, newTransactions, deletedTransactions);
+ await this.$asyncMempoolChangedCallback(this.mempoolCache, newMempoolSize, newTransactions, deletedTransactions, accelerationDelta);
this.updateTimerProgress(timer, 'completed async mempool callback');
}
@@ -342,15 +336,37 @@ class Mempool {
return this.accelerations;
}
- public addAccelerations(newAccelerations: { txid: string, delta: number }[]): void {
- for (const acceleration of newAccelerations) {
- this.accelerations[acceleration.txid] = acceleration.delta;
- }
- }
+ public async $updateAccelerations(): Promise {
+ try {
+ const newAccelerations = await accelerationApi.fetchAccelerations$();
- public removeAccelerations(txids: string[]): void {
- for (const txid of txids) {
- delete this.accelerations[txid];
+ const changed: string[] = [];
+
+ const newAccelerationMap: { [txid: string]: number } = {};
+ for (const acceleration of newAccelerations) {
+ newAccelerationMap[acceleration.txid] = acceleration.feeDelta;
+ if (this.accelerations[acceleration.txid] == null) {
+ // new acceleration
+ changed.push(acceleration.txid);
+ } else if (this.accelerations[acceleration.txid] !== acceleration.feeDelta) {
+ // feeDelta changed
+ changed.push(acceleration.txid);
+ }
+ }
+
+ for (const oldTxid of Object.keys(this.accelerations)) {
+ if (!newAccelerationMap[oldTxid]) {
+ // removed
+ changed.push(oldTxid);
+ }
+ }
+
+ this.accelerations = newAccelerationMap;
+
+ return changed;
+ } catch (e: any) {
+ logger.debug(`Failed to update accelerations: ` + (e instanceof Error ? e.message : e));
+ return [];
}
}
diff --git a/backend/src/api/services/acceleration.ts b/backend/src/api/services/acceleration.ts
new file mode 100644
index 000000000..efbf32f5d
--- /dev/null
+++ b/backend/src/api/services/acceleration.ts
@@ -0,0 +1,20 @@
+import { query } from '../../utils/axios-query';
+import config from '../../config';
+
+export interface Acceleration {
+ txid: string,
+ feeDelta: number,
+}
+
+class AccelerationApi {
+ public async fetchAccelerations$(): Promise {
+ if (config.MEMPOOL_SERVICES.ACCELERATIONS) {
+ const response = await query(`${config.MEMPOOL_SERVICES.API}/accelerations`);
+ return (response as Acceleration[]) || [];
+ } else {
+ return [];
+ }
+ }
+}
+
+export default new AccelerationApi();
\ No newline at end of file
diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts
index a33a0f0fa..3a90b29f4 100644
--- a/backend/src/api/websocket-handler.ts
+++ b/backend/src/api/websocket-handler.ts
@@ -381,7 +381,7 @@ class WebsocketHandler {
}
async $handleMempoolChange(newMempool: { [txid: string]: MempoolTransactionExtended }, mempoolSize: number,
- newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[]): Promise {
+ newTransactions: MempoolTransactionExtended[], deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]): Promise {
if (!this.wss) {
throw new Error('WebSocket.Server is not set');
}
@@ -392,7 +392,7 @@ class WebsocketHandler {
if (config.MEMPOOL.RUST_GBT) {
await mempoolBlocks.$rustUpdateBlockTemplates(newMempool, mempoolSize, newTransactions, deletedTransactions);
} else {
- await mempoolBlocks.$updateBlockTemplates(newMempool, newTransactions, deletedTransactions, true);
+ await mempoolBlocks.$updateBlockTemplates(newMempool, newTransactions, deletedTransactions, accelerationDelta, true);
}
} else {
mempoolBlocks.updateMempoolBlocks(newMempool, true);
@@ -738,8 +738,6 @@ class WebsocketHandler {
const fees = feeApi.getRecommendedFee();
const mempoolInfo = memPool.getMempoolInfo();
- memPool.removeAccelerations(txIds);
-
// update init data
this.updateSocketDataFields({
'mempoolInfo': mempoolInfo,
From 20b3ceab1e318e088c8e2d9e266d367143c64bbc Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Tue, 30 May 2023 19:51:11 -0400
Subject: [PATCH 06/73] Implement accelerations API & config setting
---
backend/mempool-config.sample.json | 4 ++++
.../src/__fixtures__/mempool-config.template.json | 4 ++++
backend/src/__tests__/config.test.ts | 7 +++++++
backend/src/api/mempool.ts | 4 ++++
backend/src/config.ts | 12 +++++++++++-
docker/backend/mempool-config.json | 4 ++++
docker/backend/start.sh | 9 +++++++++
7 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/backend/mempool-config.sample.json b/backend/mempool-config.sample.json
index e3df7d2fe..8f8b82475 100644
--- a/backend/mempool-config.sample.json
+++ b/backend/mempool-config.sample.json
@@ -136,5 +136,9 @@
"trusted",
"servers"
]
+ },
+ "MEMPOOL_SERVICES": {
+ "API": "https://mempool.space/api",
+ "ACCELERATIONS": false
}
}
diff --git a/backend/src/__fixtures__/mempool-config.template.json b/backend/src/__fixtures__/mempool-config.template.json
index 4213f0ffb..d6754f966 100644
--- a/backend/src/__fixtures__/mempool-config.template.json
+++ b/backend/src/__fixtures__/mempool-config.template.json
@@ -127,5 +127,9 @@
"AUDIT": false,
"AUDIT_START_HEIGHT": 774000,
"SERVERS": []
+ },
+ "MEMPOOl_SERVICES": {
+ "API": "__MEMPOOL_SERVICES_API__",
+ "ACCELERATIONS": "__MEMPOOL_SERVICES_ACCELERATIONS__"
}
}
diff --git a/backend/src/__tests__/config.test.ts b/backend/src/__tests__/config.test.ts
index dc1beaa46..2c83d1af5 100644
--- a/backend/src/__tests__/config.test.ts
+++ b/backend/src/__tests__/config.test.ts
@@ -127,6 +127,11 @@ describe('Mempool Backend Config', () => {
AUDIT_START_HEIGHT: 774000,
SERVERS: []
});
+
+ expect(config.MEMPOOL_SERVICES).toStrictEqual({
+ API: "",
+ ACCELERATIONS: false,
+ });
});
});
@@ -160,6 +165,8 @@ describe('Mempool Backend Config', () => {
expect(config.PRICE_DATA_SERVER).toStrictEqual(fixture.PRICE_DATA_SERVER);
expect(config.EXTERNAL_DATA_SERVER).toStrictEqual(fixture.EXTERNAL_DATA_SERVER);
+
+ expect(config.MEMPOOL_SERVICES).toStrictEqual(fixture.MEMPOOL_SERVICES);
});
});
diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts
index 7bde83df9..b114c89fc 100644
--- a/backend/src/api/mempool.ts
+++ b/backend/src/api/mempool.ts
@@ -337,6 +337,10 @@ class Mempool {
}
public async $updateAccelerations(): Promise {
+ if (!config.MEMPOOL_SERVICES.ACCELERATIONS) {
+ return [];
+ }
+
try {
const newAccelerations = await accelerationApi.fetchAccelerations$();
diff --git a/backend/src/config.ts b/backend/src/config.ts
index 09d279537..ceb569e06 100644
--- a/backend/src/config.ts
+++ b/backend/src/config.ts
@@ -137,7 +137,11 @@ interface IConfig {
AUDIT: boolean;
AUDIT_START_HEIGHT: number;
SERVERS: string[];
- }
+ },
+ MEMPOOL_SERVICES: {
+ API: string;
+ ACCELERATIONS: boolean;
+ },
}
const defaults: IConfig = {
@@ -275,6 +279,10 @@ const defaults: IConfig = {
'AUDIT': false,
'AUDIT_START_HEIGHT': 774000,
'SERVERS': [],
+ },
+ 'MEMPOOL_SERVICES': {
+ 'API': '',
+ 'ACCELERATIONS': false,
}
};
@@ -296,6 +304,7 @@ class Config implements IConfig {
EXTERNAL_DATA_SERVER: IConfig['EXTERNAL_DATA_SERVER'];
MAXMIND: IConfig['MAXMIND'];
REPLICATION: IConfig['REPLICATION'];
+ MEMPOOL_SERVICES: IConfig['MEMPOOL_SERVICES'];
constructor() {
const configs = this.merge(configFromFile, defaults);
@@ -316,6 +325,7 @@ class Config implements IConfig {
this.EXTERNAL_DATA_SERVER = configs.EXTERNAL_DATA_SERVER;
this.MAXMIND = configs.MAXMIND;
this.REPLICATION = configs.REPLICATION;
+ this.MEMPOOL_SERVICES = configs.MEMPOOL_SERVICES;
}
merge = (...objects: object[]): IConfig => {
diff --git a/docker/backend/mempool-config.json b/docker/backend/mempool-config.json
index 2ff76d5dd..71fe3bd65 100644
--- a/docker/backend/mempool-config.json
+++ b/docker/backend/mempool-config.json
@@ -133,5 +133,9 @@
"AUDIT": __REPLICATION_AUDIT__,
"AUDIT_START_HEIGHT": __REPLICATION_AUDIT_START_HEIGHT__,
"SERVERS": __REPLICATION_SERVERS__
+ },
+ "MEMPOOL_SERVICES": {
+ "API": "__MEMPOOL_SERVICES_API__",
+ "ACCELERATIONS": __MEMPOOL_SERVICES_ACCELERATIONS__
}
}
diff --git a/docker/backend/start.sh b/docker/backend/start.sh
index c34d804b4..66f873605 100755
--- a/docker/backend/start.sh
+++ b/docker/backend/start.sh
@@ -136,6 +136,10 @@ __REPLICATION_AUDIT__=${REPLICATION_AUDIT:=true}
__REPLICATION_AUDIT_START_HEIGHT__=${REPLICATION_AUDIT_START_HEIGHT:=774000}
__REPLICATION_SERVERS__=${REPLICATION_SERVERS:=[]}
+# MEMPOOL_SERVICES
+__MEMPOOL_SERVICES_API__==${MEMPOOL_SERVICES_API:=""}
+__MEMPOOL_SERVICES_ACCELERATIONS__==${MEMPOOL_SERVICES_ACCELERATIONS:=false}
+
mkdir -p "${__MEMPOOL_CACHE_DIR__}"
@@ -262,4 +266,9 @@ sed -i "s!__REPLICATION_AUDIT__!${__REPLICATION_AUDIT__}!g" mempool-config.json
sed -i "s!__REPLICATION_AUDIT_START_HEIGHT__!${__REPLICATION_AUDIT_START_HEIGHT__}!g" mempool-config.json
sed -i "s!__REPLICATION_SERVERS__!${__REPLICATION_SERVERS__}!g" mempool-config.json
+# MEMPOOL_SERVICES
+sed -i "s!__MEMPOOL_SERVICES_API__!${__MEMPOOL_SERVICES_API__}!g" mempool-config.json
+sed -i "s!__MEMPOOL_SERVICES_ACCELERATIONS__!${__MEMPOOL_SERVICES_ACCELERATIONS__}!g" mempool-config.json
+
+
node /backend/package/index.js
From 083bfdba06875fd8d254b16c6db9a6070b6b2d0d Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Sat, 3 Jun 2023 16:54:12 -0400
Subject: [PATCH 07/73] Refactor accelerated audits
---
backend/src/api/audit.ts | 4 ++--
backend/src/api/mempool-blocks.ts | 28 +++++++++++++-----------
backend/src/api/mempool.ts | 2 +-
backend/src/api/services/acceleration.ts | 20 ++++++++++++++++-
backend/src/api/websocket-handler.ts | 17 ++++++++++----
5 files changed, 50 insertions(+), 21 deletions(-)
diff --git a/backend/src/api/audit.ts b/backend/src/api/audit.ts
index 9710d0362..e78b2796f 100644
--- a/backend/src/api/audit.ts
+++ b/backend/src/api/audit.ts
@@ -6,7 +6,7 @@ import rbfCache from './rbf-cache';
const PROPAGATION_MARGIN = 180; // in seconds, time since a transaction is first seen after which it is assumed to have propagated to all miners
class Audit {
- auditBlock(transactions: MempoolTransactionExtended[], projectedBlocks: MempoolBlockWithTransactions[], mempool: { [txId: string]: MempoolTransactionExtended })
+ auditBlock(transactions: MempoolTransactionExtended[], projectedBlocks: MempoolBlockWithTransactions[], mempool: { [txId: string]: MempoolTransactionExtended }, useAccelerations: boolean = false)
: { censored: string[], added: string[], fresh: string[], sigop: string[], fullrbf: string[], accelerated: string[], score: number, similarity: number } {
if (!projectedBlocks?.[0]?.transactionIds || !mempool) {
return { censored: [], added: [], fresh: [], sigop: [], fullrbf: [], accelerated: [], score: 0, similarity: 1 };
@@ -29,7 +29,7 @@ class Audit {
const now = Math.round((Date.now() / 1000));
for (const tx of transactions) {
inBlock[tx.txid] = tx;
- if (tx.acceleration) {
+ if (mempool[tx.txid] && mempool[tx.txid].acceleration) {
accelerated.push(tx.txid);
}
}
diff --git a/backend/src/api/mempool-blocks.ts b/backend/src/api/mempool-blocks.ts
index bc0def7a8..0ce0ea522 100644
--- a/backend/src/api/mempool-blocks.ts
+++ b/backend/src/api/mempool-blocks.ts
@@ -207,7 +207,7 @@ class MempoolBlocks {
return mempoolBlockDeltas;
}
- public async $makeBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, saveResults: boolean = false): Promise {
+ public async $makeBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, saveResults: boolean = false, useAccelerations: boolean = false): Promise {
const start = Date.now();
// reset mempool short ids
@@ -216,7 +216,7 @@ class MempoolBlocks {
this.setUid(tx, true);
}
- const accelerations = mempool.getAccelerations();
+ const accelerations = useAccelerations ? mempool.getAccelerations() : {};
// prepare a stripped down version of the mempool with only the minimum necessary data
// to reduce the overhead of passing this data to the worker thread
@@ -225,7 +225,7 @@ class MempoolBlocks {
if (entry.uid !== null && entry.uid !== undefined) {
const stripped = {
uid: entry.uid,
- fee: entry.fee + (accelerations[entry.txid] || 0),
+ fee: entry.fee + (useAccelerations ? (accelerations[entry.txid] || 0) : 0),
weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
@@ -265,7 +265,7 @@ class MempoolBlocks {
// clean up thread error listener
this.txSelectionWorker?.removeListener('error', threadErrorListener);
- const processed = this.processBlockTemplates(newMempool, blocks, null, Object.entries(rates), Object.values(clusters), saveResults);
+ const processed = this.processBlockTemplates(newMempool, blocks, null, Object.entries(rates), Object.values(clusters), accelerations, saveResults);
logger.debug(`makeBlockTemplates completed in ${(Date.now() - start)/1000} seconds`);
@@ -276,17 +276,17 @@ class MempoolBlocks {
return this.mempoolBlocks;
}
- public async $updateBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, added: MempoolTransactionExtended[], removed: MempoolTransactionExtended[], accelerationDelta: string[] = [], saveResults: boolean = false): Promise {
+ public async $updateBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, added: MempoolTransactionExtended[], removed: MempoolTransactionExtended[], accelerationDelta: string[] = [], saveResults: boolean = false, useAccelerations: boolean = false): Promise {
if (!this.txSelectionWorker) {
// need to reset the worker
- await this.$makeBlockTemplates(newMempool, saveResults);
+ await this.$makeBlockTemplates(newMempool, saveResults, useAccelerations);
return;
}
const start = Date.now();
- const accelerations = mempool.getAccelerations();
- const addedAndChanged: MempoolTransactionExtended[] = accelerationDelta.map(txid => newMempool[txid]).filter(tx => tx != null).concat(added);
+ const accelerations = useAccelerations ? mempool.getAccelerations() : {};
+ const addedAndChanged: MempoolTransactionExtended[] = useAccelerations ? accelerationDelta.map(txid => newMempool[txid]).filter(tx => tx != null).concat(added) : added;
for (const tx of addedAndChanged) {
this.setUid(tx, true);
@@ -298,7 +298,7 @@ class MempoolBlocks {
const addedStripped: CompactThreadTransaction[] = addedAndChanged.filter(entry => entry.uid != null).map(entry => {
return {
uid: entry.uid || 0,
- fee: entry.fee + (accelerations[entry.txid] || 0),
+ fee: entry.fee + (useAccelerations ? (accelerations[entry.txid] || 0) : 0),
weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
@@ -325,7 +325,7 @@ class MempoolBlocks {
// clean up thread error listener
this.txSelectionWorker?.removeListener('error', threadErrorListener);
- this.processBlockTemplates(newMempool, blocks, null, Object.entries(rates), Object.values(clusters), saveResults);
+ this.processBlockTemplates(newMempool, blocks, null, Object.entries(rates), Object.values(clusters), accelerations, saveResults);
logger.debug(`updateBlockTemplates completed in ${(Date.now() - start) / 1000} seconds`);
} catch (e) {
logger.err('updateBlockTemplates failed. ' + (e instanceof Error ? e.message : e));
@@ -362,7 +362,7 @@ class MempoolBlocks {
if (saveResults) {
this.rustInitialized = true;
}
- const processed = this.processBlockTemplates(newMempool, blocks, blockWeights, rates, clusters, saveResults);
+ const processed = this.processBlockTemplates(newMempool, blocks, blockWeights, rates, clusters, {}, saveResults);
logger.debug(`RUST makeBlockTemplates completed in ${(Date.now() - start)/1000} seconds`);
return processed;
} catch (e) {
@@ -414,7 +414,7 @@ class MempoolBlocks {
if (mempoolSize !== resultMempoolSize) {
throw new Error('GBT returned wrong number of transactions, cache is probably out of sync');
} else {
- this.processBlockTemplates(newMempool, blocks, blockWeights, rates, clusters, true);
+ this.processBlockTemplates(newMempool, blocks, blockWeights, rates, clusters, {}, true);
}
this.removeUids(removedUids);
logger.debug(`RUST updateBlockTemplates completed in ${(Date.now() - start)/1000} seconds`);
@@ -424,7 +424,7 @@ class MempoolBlocks {
}
}
- private processBlockTemplates(mempool: { [txid: string]: MempoolTransactionExtended }, blocks: string[][], blockWeights: number[] | null, rates: [string, number][], clusters: string[][], saveResults): MempoolBlockWithTransactions[] {
+ private processBlockTemplates(mempool: { [txid: string]: MempoolTransactionExtended }, blocks: string[][], blockWeights: number[] | null, rates: [string, number][], clusters: string[][], accelerations, saveResults): MempoolBlockWithTransactions[] {
for (const [txid, rate] of rates) {
if (txid in mempool) {
mempool[txid].effectiveFeePerVsize = rate;
@@ -503,6 +503,8 @@ class MempoolBlocks {
mempoolTx.cpfpChecked = true;
}
+ mempoolTx.acceleration = accelerations[txid];
+
// online calculation of stack-of-blocks fee stats
if (hasBlockStack && blockIndex === lastBlockIndex && feeStatsCalculator) {
feeStatsCalculator.processNext(mempoolTx);
diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts
index b114c89fc..4efe17731 100644
--- a/backend/src/api/mempool.ts
+++ b/backend/src/api/mempool.ts
@@ -342,7 +342,7 @@ class Mempool {
}
try {
- const newAccelerations = await accelerationApi.fetchAccelerations$();
+ const newAccelerations = await accelerationApi.$fetchAccelerations();
const changed: string[] = [];
diff --git a/backend/src/api/services/acceleration.ts b/backend/src/api/services/acceleration.ts
index efbf32f5d..8c849cdd8 100644
--- a/backend/src/api/services/acceleration.ts
+++ b/backend/src/api/services/acceleration.ts
@@ -1,5 +1,6 @@
import { query } from '../../utils/axios-query';
import config from '../../config';
+import { BlockExtended, PoolTag } from '../../mempool.interfaces';
export interface Acceleration {
txid: string,
@@ -7,7 +8,7 @@ export interface Acceleration {
}
class AccelerationApi {
- public async fetchAccelerations$(): Promise {
+ public async $fetchAccelerations(): Promise {
if (config.MEMPOOL_SERVICES.ACCELERATIONS) {
const response = await query(`${config.MEMPOOL_SERVICES.API}/accelerations`);
return (response as Acceleration[]) || [];
@@ -15,6 +16,23 @@ class AccelerationApi {
return [];
}
}
+
+ public async $fetchPools(): Promise {
+ if (config.MEMPOOL_SERVICES.ACCELERATIONS) {
+ const response = await query(`${config.MEMPOOL_SERVICES.API}/partners`);
+ return (response as PoolTag[]) || [];
+ } else {
+ return [];
+ }
+ }
+
+ public async $isAcceleratedBlock(block: BlockExtended): Promise {
+ const pools = await this.$fetchPools();
+ if (block?.extras?.pool?.id == null) {
+ return false;
+ }
+ return pools.reduce((match, tag) => match || tag.uniqueId === block.extras.pool.id, false);
+ }
}
export default new AccelerationApi();
\ No newline at end of file
diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts
index 3a90b29f4..51fccbcbb 100644
--- a/backend/src/api/websocket-handler.ts
+++ b/backend/src/api/websocket-handler.ts
@@ -21,7 +21,7 @@ import Audit from './audit';
import { deepClone } from '../utils/clone';
import priceUpdater from '../tasks/price-updater';
import { ApiPrice } from '../repositories/PricesRepository';
-import mempool from './mempool';
+import accelerationApi from './services/acceleration';
// valid 'want' subscriptions
const wantable = [
@@ -392,7 +392,7 @@ class WebsocketHandler {
if (config.MEMPOOL.RUST_GBT) {
await mempoolBlocks.$rustUpdateBlockTemplates(newMempool, mempoolSize, newTransactions, deletedTransactions);
} else {
- await mempoolBlocks.$updateBlockTemplates(newMempool, newTransactions, deletedTransactions, accelerationDelta, true);
+ await mempoolBlocks.$updateBlockTemplates(newMempool, newTransactions, deletedTransactions, accelerationDelta, true, config.MEMPOOL_SERVICES.ACCELERATIONS);
}
} else {
mempoolBlocks.updateMempoolBlocks(newMempool, true);
@@ -648,6 +648,7 @@ class WebsocketHandler {
if (config.MEMPOOL.AUDIT && memPool.isInSync()) {
let projectedBlocks;
let auditMempool = _memPool;
+ const isAccelerated = config.MEMPOOL_SERVICES.ACCELERATIONS && await accelerationApi.$isAcceleratedBlock(block);
// template calculation functions have mempool side effects, so calculate audits using
// a cloned copy of the mempool if we're running a different algorithm for mempool updates
const separateAudit = config.MEMPOOL.ADVANCED_GBT_AUDIT !== config.MEMPOOL.ADVANCED_GBT_MEMPOOL;
@@ -657,13 +658,17 @@ class WebsocketHandler {
if (config.MEMPOOL.RUST_GBT) {
projectedBlocks = await mempoolBlocks.$oneOffRustBlockTemplates(auditMempool);
} else {
- projectedBlocks = await mempoolBlocks.$makeBlockTemplates(auditMempool, false);
+ projectedBlocks = await mempoolBlocks.$makeBlockTemplates(auditMempool, false, isAccelerated);
}
} else {
projectedBlocks = mempoolBlocks.updateMempoolBlocks(auditMempool, false);
}
} else {
- projectedBlocks = mempoolBlocks.getMempoolBlocksWithTransactions();
+ if ((config.MEMPOOL_SERVICES.ACCELERATIONS && !isAccelerated)) {
+ projectedBlocks = await mempoolBlocks.$makeBlockTemplates(auditMempool, false, isAccelerated);
+ } else {
+ projectedBlocks = mempoolBlocks.getMempoolBlocksWithTransactions();
+ }
}
if (Common.indexingEnabled()) {
@@ -723,11 +728,15 @@ class WebsocketHandler {
}
if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) {
+<<<<<<< HEAD
if (config.MEMPOOL.RUST_GBT) {
await mempoolBlocks.$rustUpdateBlockTemplates(_memPool, Object.keys(_memPool).length, [], transactions);
} else {
await mempoolBlocks.$makeBlockTemplates(_memPool, true);
}
+=======
+ await mempoolBlocks.$makeBlockTemplates(_memPool, true, config.MEMPOOL_SERVICES.ACCELERATIONS);
+>>>>>>> 77b0a8ecc (Refactor accelerated audits)
} else {
mempoolBlocks.updateMempoolBlocks(_memPool, true);
}
From ba54bc9d1593076a9ce380216580731df22518bb Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Tue, 13 Jun 2023 13:35:25 -0400
Subject: [PATCH 08/73] support for acceleration mempool blocks animation
---
backend/src/api/websocket-handler.ts | 24 ++++++++++-----
.../mempool-blocks.component.html | 2 +-
.../mempool-blocks.component.scss | 30 +++++++++++++++++++
.../mempool-blocks.component.ts | 1 +
.../transaction/transaction.component.html | 4 +--
.../src/app/interfaces/node-api.interface.ts | 1 +
6 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts
index 51fccbcbb..7716ed7b7 100644
--- a/backend/src/api/websocket-handler.ts
+++ b/backend/src/api/websocket-handler.ts
@@ -173,9 +173,15 @@ class WebsocketHandler {
}
const tx = memPool.getMempool()[trackTxid];
if (tx && tx.position) {
+ const position: { block: number, vsize: number, accelerated?: number } = {
+ ...tx.position
+ };
+ if (tx.acceleration) {
+ position.accelerated = tx.acceleration;
+ }
response['txPosition'] = JSON.stringify({
txid: trackTxid,
- position: tx.position,
+ position
});
}
} else {
@@ -600,7 +606,10 @@ class WebsocketHandler {
if (mempoolTx && mempoolTx.position) {
response['txPosition'] = JSON.stringify({
txid: trackTxid,
- position: mempoolTx.position,
+ position: {
+ ...mempoolTx.position,
+ accelerated: mempoolTx.acceleration || undefined,
+ }
});
}
}
@@ -728,15 +737,11 @@ class WebsocketHandler {
}
if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) {
-<<<<<<< HEAD
if (config.MEMPOOL.RUST_GBT) {
await mempoolBlocks.$rustUpdateBlockTemplates(_memPool, Object.keys(_memPool).length, [], transactions);
} else {
- await mempoolBlocks.$makeBlockTemplates(_memPool, true);
+ await mempoolBlocks.$makeBlockTemplates(_memPool, true, config.MEMPOOL_SERVICES.ACCELERATIONS);
}
-=======
- await mempoolBlocks.$makeBlockTemplates(_memPool, true, config.MEMPOOL_SERVICES.ACCELERATIONS);
->>>>>>> 77b0a8ecc (Refactor accelerated audits)
} else {
mempoolBlocks.updateMempoolBlocks(_memPool, true);
}
@@ -799,7 +804,10 @@ class WebsocketHandler {
if (mempoolTx && mempoolTx.position) {
response['txPosition'] = JSON.stringify({
txid: trackTxid,
- position: mempoolTx.position,
+ position: {
+ ...mempoolTx.position,
+ accelerated: mempoolTx.acceleration || undefined,
+ }
});
}
}
diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html
index 9c5c338c0..59d35c91e 100644
--- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html
+++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.html
@@ -49,7 +49,7 @@
-
+
diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss
index 40f43a015..606699d93 100644
--- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss
+++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.scss
@@ -169,4 +169,34 @@
transform: translate(calc(-0.2 * var(--block-size)), calc(1.1 * var(--block-size)));
border-radius: 2px;
z-index: -1;
+}
+
+.blink{
+ width:400px;
+ height:400px;
+ border-bottom: 35px solid #FFF;
+ animation: blink 0.2s infinite;
+}
+@keyframes blink{
+ 0% {
+ border-bottom: 35px solid green;
+ }
+ 50% {
+ border-bottom: 35px solid yellow;
+ }
+ 100% {
+ border-bottom: 35px solid orange;
+ }
+}
+
+@-webkit-keyframes blink{
+ 0% {
+ border-bottom: 35px solid green;
+ }
+ 50% {
+ border-bottom: 35px solid yellow;
+ }
+ 100% {
+ border-bottom: 35px solid orange;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts
index 71075b261..33db897a5 100644
--- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts
+++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts
@@ -26,6 +26,7 @@ import { animate, style, transition, trigger } from '@angular/animations';
export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
@Input() minimal: boolean = false;
@Input() blockWidth: number = 125;
+ @Input() containerWidth: number = null;
@Input() count: number = null;
@Input() spotlight: number = 0;
@Input() getHref?: (index) => string = (index) => `/mempool-block/${index}`;
diff --git a/frontend/src/app/components/transaction/transaction.component.html b/frontend/src/app/components/transaction/transaction.component.html
index 81a6106db..7422c6894 100644
--- a/frontend/src/app/components/transaction/transaction.component.html
+++ b/frontend/src/app/components/transaction/transaction.component.html
@@ -488,8 +488,8 @@
|
- Accelerated fee rate |
- Effective fee rate |
+ Accelerated fee rate |
+ Effective fee rate |
diff --git a/frontend/src/app/interfaces/node-api.interface.ts b/frontend/src/app/interfaces/node-api.interface.ts
index fe6233866..a0a3da5e6 100644
--- a/frontend/src/app/interfaces/node-api.interface.ts
+++ b/frontend/src/app/interfaces/node-api.interface.ts
@@ -188,6 +188,7 @@ export interface RbfTransaction extends TransactionStripped {
export interface MempoolPosition {
block: number,
vsize: number,
+ accelerated?: boolean
}
export interface RewardStats {
From 6494f890fe587655e5ce3c6ef56633402f3823d4 Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Tue, 13 Jun 2023 17:03:36 -0400
Subject: [PATCH 09/73] include per-tx pools in /accelerations endpoint
---
backend/src/api/mempool-blocks.ts | 8 +++---
backend/src/api/mempool.ts | 36 +++++++++++++++++++-----
backend/src/api/services/acceleration.ts | 20 ++++---------
backend/src/api/websocket-handler.ts | 5 ++--
4 files changed, 42 insertions(+), 27 deletions(-)
diff --git a/backend/src/api/mempool-blocks.ts b/backend/src/api/mempool-blocks.ts
index 0ce0ea522..606c98c83 100644
--- a/backend/src/api/mempool-blocks.ts
+++ b/backend/src/api/mempool-blocks.ts
@@ -1,6 +1,6 @@
import { GbtGenerator, GbtResult, ThreadTransaction as RustThreadTransaction } from '../../rust-gbt';
import logger from '../logger';
-import { MempoolBlock, MempoolTransactionExtended, TransactionStripped, MempoolBlockWithTransactions, MempoolBlockDelta, Ancestor, CompactThreadTransaction, EffectiveFeeStats } from '../mempool.interfaces';
+import { MempoolBlock, MempoolTransactionExtended, TransactionStripped, MempoolBlockWithTransactions, MempoolBlockDelta, Ancestor, CompactThreadTransaction, EffectiveFeeStats, PoolTag } from '../mempool.interfaces';
import { Common, OnlineFeeStatsCalculator } from './common';
import config from '../config';
import { Worker } from 'worker_threads';
@@ -207,7 +207,7 @@ class MempoolBlocks {
return mempoolBlockDeltas;
}
- public async $makeBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, saveResults: boolean = false, useAccelerations: boolean = false): Promise {
+ public async $makeBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, saveResults: boolean = false, useAccelerations: boolean = false, accelerationPool?: number): Promise {
const start = Date.now();
// reset mempool short ids
@@ -225,7 +225,7 @@ class MempoolBlocks {
if (entry.uid !== null && entry.uid !== undefined) {
const stripped = {
uid: entry.uid,
- fee: entry.fee + (useAccelerations ? (accelerations[entry.txid] || 0) : 0),
+ fee: entry.fee + (useAccelerations && (!accelerationPool || accelerations[entry.txid]?.pools?.includes(accelerationPool)) ? (accelerations[entry.txid]?.feeDelta || 0) : 0),
weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
@@ -298,7 +298,7 @@ class MempoolBlocks {
const addedStripped: CompactThreadTransaction[] = addedAndChanged.filter(entry => entry.uid != null).map(entry => {
return {
uid: entry.uid || 0,
- fee: entry.fee + (useAccelerations ? (accelerations[entry.txid] || 0) : 0),
+ fee: entry.fee + (useAccelerations ? (accelerations[entry.txid]?.feeDelta || 0) : 0),
weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts
index 4efe17731..107aa41cb 100644
--- a/backend/src/api/mempool.ts
+++ b/backend/src/api/mempool.ts
@@ -23,7 +23,7 @@ class Mempool {
private $asyncMempoolChangedCallback: ((newMempool: {[txId: string]: MempoolTransactionExtended; }, mempoolSize: number, newTransactions: MempoolTransactionExtended[],
deletedTransactions: MempoolTransactionExtended[], accelerationDelta: string[]) => Promise) | undefined;
- private accelerations: { [txId: string]: number } = {};
+ private accelerations: { [txId: string]: Acceleration } = {};
private txPerSecondArray: number[] = [];
private txPerSecond: number = 0;
@@ -332,7 +332,7 @@ class Mempool {
this.clearTimer(timer);
}
- public getAccelerations(): { [txid: string]: number } {
+ public getAccelerations(): { [txid: string]: Acceleration } {
return this.accelerations;
}
@@ -346,15 +346,37 @@ class Mempool {
const changed: string[] = [];
- const newAccelerationMap: { [txid: string]: number } = {};
+ const newAccelerationMap: { [txid: string]: Acceleration } = {};
for (const acceleration of newAccelerations) {
- newAccelerationMap[acceleration.txid] = acceleration.feeDelta;
+ newAccelerationMap[acceleration.txid] = acceleration;
if (this.accelerations[acceleration.txid] == null) {
// new acceleration
changed.push(acceleration.txid);
- } else if (this.accelerations[acceleration.txid] !== acceleration.feeDelta) {
- // feeDelta changed
- changed.push(acceleration.txid);
+ } else {
+ if (this.accelerations[acceleration.txid].feeDelta !== acceleration.feeDelta) {
+ // feeDelta changed
+ changed.push(acceleration.txid);
+ } else if (this.accelerations[acceleration.txid].pools?.length) {
+ let poolsChanged = false;
+ const pools = new Set();
+ this.accelerations[acceleration.txid].pools.forEach(pool => {
+ pools.add(pool);
+ });
+ acceleration.pools.forEach(pool => {
+ if (!pools.has(pool)) {
+ poolsChanged = true;
+ } else {
+ pools.delete(pool);
+ }
+ });
+ if (pools.size > 0) {
+ poolsChanged = true;
+ }
+ if (poolsChanged) {
+ // pools changed
+ changed.push(acceleration.txid);
+ }
+ }
}
}
diff --git a/backend/src/api/services/acceleration.ts b/backend/src/api/services/acceleration.ts
index 8c849cdd8..1c2fff7c6 100644
--- a/backend/src/api/services/acceleration.ts
+++ b/backend/src/api/services/acceleration.ts
@@ -5,6 +5,7 @@ import { BlockExtended, PoolTag } from '../../mempool.interfaces';
export interface Acceleration {
txid: string,
feeDelta: number,
+ pools: number[],
}
class AccelerationApi {
@@ -17,21 +18,12 @@ class AccelerationApi {
}
}
- public async $fetchPools(): Promise {
- if (config.MEMPOOL_SERVICES.ACCELERATIONS) {
- const response = await query(`${config.MEMPOOL_SERVICES.API}/partners`);
- return (response as PoolTag[]) || [];
- } else {
- return [];
+ public isAcceleratedBlock(block: BlockExtended, accelerations: Acceleration[]): boolean {
+ let anyAccelerated = false;
+ for (let i = 0; i < accelerations.length && !anyAccelerated; i++) {
+ anyAccelerated = anyAccelerated || accelerations[i].pools?.includes(block.extras.pool.id);
}
- }
-
- public async $isAcceleratedBlock(block: BlockExtended): Promise {
- const pools = await this.$fetchPools();
- if (block?.extras?.pool?.id == null) {
- return false;
- }
- return pools.reduce((match, tag) => match || tag.uniqueId === block.extras.pool.id, false);
+ return anyAccelerated;
}
}
diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts
index 7716ed7b7..ced6642d8 100644
--- a/backend/src/api/websocket-handler.ts
+++ b/backend/src/api/websocket-handler.ts
@@ -22,6 +22,7 @@ import { deepClone } from '../utils/clone';
import priceUpdater from '../tasks/price-updater';
import { ApiPrice } from '../repositories/PricesRepository';
import accelerationApi from './services/acceleration';
+import mempool from './mempool';
// valid 'want' subscriptions
const wantable = [
@@ -657,7 +658,7 @@ class WebsocketHandler {
if (config.MEMPOOL.AUDIT && memPool.isInSync()) {
let projectedBlocks;
let auditMempool = _memPool;
- const isAccelerated = config.MEMPOOL_SERVICES.ACCELERATIONS && await accelerationApi.$isAcceleratedBlock(block);
+ const isAccelerated = config.MEMPOOL_SERVICES.ACCELERATIONS && accelerationApi.isAcceleratedBlock(block, Object.values(mempool.getAccelerations()));
// template calculation functions have mempool side effects, so calculate audits using
// a cloned copy of the mempool if we're running a different algorithm for mempool updates
const separateAudit = config.MEMPOOL.ADVANCED_GBT_AUDIT !== config.MEMPOOL.ADVANCED_GBT_MEMPOOL;
@@ -667,7 +668,7 @@ class WebsocketHandler {
if (config.MEMPOOL.RUST_GBT) {
projectedBlocks = await mempoolBlocks.$oneOffRustBlockTemplates(auditMempool);
} else {
- projectedBlocks = await mempoolBlocks.$makeBlockTemplates(auditMempool, false, isAccelerated);
+ projectedBlocks = await mempoolBlocks.$makeBlockTemplates(auditMempool, false, isAccelerated, block.extras.pool.id);
}
} else {
projectedBlocks = mempoolBlocks.updateMempoolBlocks(auditMempool, false);
From ffc2b6c53cecbd9f5c1b2e40732469ce05bf27f3 Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Tue, 18 Jul 2023 15:05:44 +0900
Subject: [PATCH 10/73] Add acceleration support to rust gbt
---
backend/rust-gbt/index.d.ts | 8 ++-
backend/rust-gbt/src/audit_transaction.rs | 27 +++++----
backend/rust-gbt/src/gbt.rs | 13 ++++-
backend/rust-gbt/src/lib.rs | 10 +++-
backend/src/api/mempool-blocks.ts | 56 ++++++++++++++-----
backend/src/api/mempool.ts | 2 +-
backend/src/api/websocket-handler.ts | 8 +--
backend/src/mempool.interfaces.ts | 4 +-
backend/src/replication/AuditReplication.ts | 1 +
.../block-overview-graph.component.ts | 2 +-
.../block-overview-graph/block-scene.ts | 2 +-
.../block-overview-graph/tx-view.ts | 2 +-
.../fee-distribution-graph.component.ts | 2 +-
.../src/app/interfaces/websocket.interface.ts | 4 +-
14 files changed, 96 insertions(+), 45 deletions(-)
diff --git a/backend/rust-gbt/index.d.ts b/backend/rust-gbt/index.d.ts
index 33ae32bdf..2bd8a620a 100644
--- a/backend/rust-gbt/index.d.ts
+++ b/backend/rust-gbt/index.d.ts
@@ -12,6 +12,10 @@ export interface ThreadTransaction {
effectiveFeePerVsize: number
inputs: Array
}
+export interface ThreadAcceleration {
+ uid: number
+ delta: number
+}
export class GbtGenerator {
constructor()
/**
@@ -19,13 +23,13 @@ export class GbtGenerator {
*
* Rejects if the thread panics or if the Mutex is poisoned.
*/
- make(mempool: Array, maxUid: number): Promise
+ make(mempool: Array, accelerations: Array, maxUid: number): Promise
/**
* # Errors
*
* Rejects if the thread panics or if the Mutex is poisoned.
*/
- update(newTxs: Array, removeTxs: Array, maxUid: number): Promise
+ update(newTxs: Array, removeTxs: Array, accelerations: Array, maxUid: number): Promise
}
/**
* The result from calling the gbt function.
diff --git a/backend/rust-gbt/src/audit_transaction.rs b/backend/rust-gbt/src/audit_transaction.rs
index 3e25a18a0..9b7472c30 100644
--- a/backend/rust-gbt/src/audit_transaction.rs
+++ b/backend/rust-gbt/src/audit_transaction.rs
@@ -1,6 +1,6 @@
use crate::{
u32_hasher_types::{u32hashset_new, U32HasherState},
- ThreadTransaction,
+ ThreadTransaction, thread_acceleration::ThreadAcceleration,
};
use std::{
cmp::Ordering,
@@ -88,37 +88,42 @@ impl Ord for AuditTransaction {
}
#[inline]
-fn calc_fee_rate(fee: f64, vsize: f64) -> f64 {
- fee / (if vsize == 0.0 { 1.0 } else { vsize })
+fn calc_fee_rate(fee: u64, vsize: f64) -> f64 {
+ (fee as f64) / (if vsize == 0.0 { 1.0 } else { vsize })
}
impl AuditTransaction {
- pub fn from_thread_transaction(tx: &ThreadTransaction) -> Self {
+ pub fn from_thread_transaction(tx: &ThreadTransaction, maybe_acceleration: Option |