From 9f4107319fe002600cd49164b31d604341bddf9d Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Sat, 7 Jan 2023 11:17:30 +0100 Subject: [PATCH 1/2] Fetch coinbase tx with core when esplora fails to do so --- backend/src/api/blocks.ts | 23 +++++++++++++++++------ backend/src/api/transaction-utils.ts | 16 ++++++++++++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index 472ef48ef..8292fe241 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -101,12 +101,23 @@ class Blocks { transactions.push(tx); transactionsFetched++; } catch (e) { - if (i === 0) { - const msg = `Cannot fetch coinbase tx ${txIds[i]}. Reason: ` + (e instanceof Error ? e.message : e); - logger.err(msg); - throw new Error(msg); - } else { - logger.err(`Cannot fetch tx ${txIds[i]}. Reason: ` + (e instanceof Error ? e.message : e)); + try { + if (config.MEMPOOL.BACKEND === 'esplora') { + // Try again with core + const tx = await transactionUtils.$getTransactionExtended(txIds[i], false, false, true); + transactions.push(tx); + transactionsFetched++; + } else { + throw e; + } + } catch (e) { + if (i === 0) { + const msg = `Cannot fetch coinbase tx ${txIds[i]}. Reason: ` + (e instanceof Error ? e.message : e); + logger.err(msg); + throw new Error(msg); + } else { + logger.err(`Cannot fetch tx ${txIds[i]}. Reason: ` + (e instanceof Error ? e.message : e)); + } } } } diff --git a/backend/src/api/transaction-utils.ts b/backend/src/api/transaction-utils.ts index 5b92cea5f..5da168584 100644 --- a/backend/src/api/transaction-utils.ts +++ b/backend/src/api/transaction-utils.ts @@ -3,6 +3,7 @@ import { TransactionExtended, TransactionMinerInfo } from '../mempool.interfaces import { IEsploraApi } from './bitcoin/esplora-api.interface'; import config from '../config'; import { Common } from './common'; +import bitcoinClient from './bitcoin/bitcoin-client'; class TransactionUtils { constructor() { } @@ -21,8 +22,19 @@ class TransactionUtils { }; } - public async $getTransactionExtended(txId: string, addPrevouts = false, lazyPrevouts = false): Promise { - const transaction: IEsploraApi.Transaction = await bitcoinApi.$getRawTransaction(txId, false, addPrevouts, lazyPrevouts); + /** + * @param txId + * @param addPrevouts + * @param lazyPrevouts + * @param forceCore - See https://github.com/mempool/mempool/issues/2904 + */ + public async $getTransactionExtended(txId: string, addPrevouts = false, lazyPrevouts = false, forceCore = false): Promise { + let transaction: IEsploraApi.Transaction; + if (forceCore === true) { + transaction = await bitcoinClient.$getRawTransaction(txId, true); + } else { + transaction = await bitcoinApi.$getRawTransaction(txId, false, addPrevouts, lazyPrevouts); + } return this.extendTransaction(transaction); } From 71d1c3de04d64f07d5929bc042a084241002f73d Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Sun, 8 Jan 2023 11:24:23 +0100 Subject: [PATCH 2/2] Update `bitcoin-api-factory` so we can use core only if needed --- backend/src/api/audit.ts | 7 +------ backend/src/api/bitcoin/bitcoin-api-factory.ts | 2 ++ backend/src/api/transaction-utils.ts | 6 ++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/backend/src/api/audit.ts b/backend/src/api/audit.ts index 6aafc9ded..b6b36dbdc 100644 --- a/backend/src/api/audit.ts +++ b/backend/src/api/audit.ts @@ -1,10 +1,5 @@ import config from '../config'; -import bitcoinApi from './bitcoin/bitcoin-api-factory'; -import { Common } from './common'; -import { TransactionExtended, MempoolBlockWithTransactions, AuditScore } from '../mempool.interfaces'; -import blocksRepository from '../repositories/BlocksRepository'; -import blocksAuditsRepository from '../repositories/BlocksAuditsRepository'; -import blocks from '../api/blocks'; +import { TransactionExtended, MempoolBlockWithTransactions } from '../mempool.interfaces'; const PROPAGATION_MARGIN = 180; // in seconds, time since a transaction is first seen after which it is assumed to have propagated to all miners diff --git a/backend/src/api/bitcoin/bitcoin-api-factory.ts b/backend/src/api/bitcoin/bitcoin-api-factory.ts index f89d07b50..24916b97b 100644 --- a/backend/src/api/bitcoin/bitcoin-api-factory.ts +++ b/backend/src/api/bitcoin/bitcoin-api-factory.ts @@ -17,4 +17,6 @@ function bitcoinApiFactory(): AbstractBitcoinApi { } } +export const bitcoinCoreApi = new BitcoinApi(bitcoinClient); + export default bitcoinApiFactory(); diff --git a/backend/src/api/transaction-utils.ts b/backend/src/api/transaction-utils.ts index 5da168584..fb5aeea42 100644 --- a/backend/src/api/transaction-utils.ts +++ b/backend/src/api/transaction-utils.ts @@ -1,9 +1,7 @@ -import bitcoinApi from './bitcoin/bitcoin-api-factory'; import { TransactionExtended, TransactionMinerInfo } from '../mempool.interfaces'; import { IEsploraApi } from './bitcoin/esplora-api.interface'; -import config from '../config'; import { Common } from './common'; -import bitcoinClient from './bitcoin/bitcoin-client'; +import bitcoinApi, { bitcoinCoreApi } from './bitcoin/bitcoin-api-factory'; class TransactionUtils { constructor() { } @@ -31,7 +29,7 @@ class TransactionUtils { public async $getTransactionExtended(txId: string, addPrevouts = false, lazyPrevouts = false, forceCore = false): Promise { let transaction: IEsploraApi.Transaction; if (forceCore === true) { - transaction = await bitcoinClient.$getRawTransaction(txId, true); + transaction = await bitcoinCoreApi.$getRawTransaction(txId, true); } else { transaction = await bitcoinApi.$getRawTransaction(txId, false, addPrevouts, lazyPrevouts); }