mirror of
https://github.com/mempool/mempool.git
synced 2025-03-15 12:20:28 +01:00
Fetch block txs from mempool/electrs in bulk
This commit is contained in:
parent
81d1c0a4d5
commit
0ebfd6f017
5 changed files with 42 additions and 35 deletions
|
@ -8,6 +8,7 @@ export interface AbstractBitcoinApi {
|
||||||
$getBlockHeightTip(): Promise<number>;
|
$getBlockHeightTip(): Promise<number>;
|
||||||
$getBlockHashTip(): Promise<string>;
|
$getBlockHashTip(): Promise<string>;
|
||||||
$getTxIdsForBlock(hash: string): Promise<string[]>;
|
$getTxIdsForBlock(hash: string): Promise<string[]>;
|
||||||
|
$getTxsForBlock(hash: string): Promise<IEsploraApi.Transaction[]>;
|
||||||
$getBlockHash(height: number): Promise<string>;
|
$getBlockHash(height: number): Promise<string>;
|
||||||
$getBlockHeader(hash: string): Promise<string>;
|
$getBlockHeader(hash: string): Promise<string>;
|
||||||
$getBlock(hash: string): Promise<IEsploraApi.Block>;
|
$getBlock(hash: string): Promise<IEsploraApi.Block>;
|
||||||
|
|
|
@ -81,6 +81,10 @@ class BitcoinApi implements AbstractBitcoinApi {
|
||||||
.then((rpcBlock: IBitcoinApi.Block) => rpcBlock.tx);
|
.then((rpcBlock: IBitcoinApi.Block) => rpcBlock.tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$getTxsForBlock(hash: string): Promise<IEsploraApi.Transaction[]> {
|
||||||
|
throw new Error('Method getTxsForBlock not supported by the Bitcoin RPC API.');
|
||||||
|
}
|
||||||
|
|
||||||
$getRawBlock(hash: string): Promise<Buffer> {
|
$getRawBlock(hash: string): Promise<Buffer> {
|
||||||
return this.bitcoindClient.getBlock(hash, 0)
|
return this.bitcoindClient.getBlock(hash, 0)
|
||||||
.then((raw: string) => Buffer.from(raw, "hex"));
|
.then((raw: string) => Buffer.from(raw, "hex"));
|
||||||
|
|
|
@ -89,6 +89,10 @@ class ElectrsApi implements AbstractBitcoinApi {
|
||||||
return this.$queryWrapper<string[]>(config.ESPLORA.REST_API_URL + '/block/' + hash + '/txids');
|
return this.$queryWrapper<string[]>(config.ESPLORA.REST_API_URL + '/block/' + hash + '/txids');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$getTxsForBlock(hash: string): Promise<IEsploraApi.Transaction[]> {
|
||||||
|
return this.$queryWrapper<IEsploraApi.Transaction[]>(config.ESPLORA.REST_API_URL + '/block/' + hash + '/txs');
|
||||||
|
}
|
||||||
|
|
||||||
$getBlockHash(height: number): Promise<string> {
|
$getBlockHash(height: number): Promise<string> {
|
||||||
return this.$queryWrapper<string>(config.ESPLORA.REST_API_URL + '/block-height/' + height);
|
return this.$queryWrapper<string>(config.ESPLORA.REST_API_URL + '/block-height/' + height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,22 +80,30 @@ class Blocks {
|
||||||
quiet: boolean = false,
|
quiet: boolean = false,
|
||||||
addMempoolData: boolean = false,
|
addMempoolData: boolean = false,
|
||||||
): Promise<TransactionExtended[]> {
|
): Promise<TransactionExtended[]> {
|
||||||
const transactions: TransactionExtended[] = [];
|
let transactions: TransactionExtended[] = [];
|
||||||
if (!txIds) {
|
|
||||||
txIds = await bitcoinApi.$getTxIdsForBlock(blockHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mempool = memPool.getMempool();
|
const mempool = memPool.getMempool();
|
||||||
let transactionsFound = 0;
|
let transactionsFound = 0;
|
||||||
let transactionsFetched = 0;
|
let transactionsFetched = 0;
|
||||||
|
|
||||||
|
if (config.MEMPOOL.BACKEND === 'esplora') {
|
||||||
|
const rawTransactions = await bitcoinApi.$getTxsForBlock(blockHash);
|
||||||
|
transactions = rawTransactions.map(tx => transactionUtils.extendTransaction(tx));
|
||||||
|
|
||||||
|
if (!quiet) {
|
||||||
|
logger.debug(`${transactions.length} fetched through backend service.`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!txIds) {
|
||||||
|
txIds = await bitcoinApi.$getTxIdsForBlock(blockHash);
|
||||||
|
}
|
||||||
for (let i = 0; i < txIds.length; i++) {
|
for (let i = 0; i < txIds.length; i++) {
|
||||||
if (mempool[txIds[i]]) {
|
if (mempool[txIds[i]]) {
|
||||||
// We update blocks before the mempool (index.ts), therefore we can
|
// We update blocks before the mempool (index.ts), therefore we can
|
||||||
// optimize here by directly fetching txs in the "outdated" mempool
|
// optimize here by directly fetching txs in the "outdated" mempool
|
||||||
transactions.push(mempool[txIds[i]]);
|
transactions.push(mempool[txIds[i]]);
|
||||||
transactionsFound++;
|
transactionsFound++;
|
||||||
} else if (config.MEMPOOL.BACKEND === 'esplora' || !memPool.hasPriority() || i === 0) {
|
} else if (!memPool.hasPriority() || i === 0) {
|
||||||
// Otherwise we fetch the tx data through backend services (esplora, electrum, core rpc...)
|
// Otherwise we fetch the tx data through backend services (esplora, electrum, core rpc...)
|
||||||
if (!quiet && (i % (Math.round((txIds.length) / 10)) === 0 || i + 1 === txIds.length)) { // Avoid log spam
|
if (!quiet && (i % (Math.round((txIds.length) / 10)) === 0 || i + 1 === txIds.length)) { // Avoid log spam
|
||||||
logger.debug(`Indexing tx ${i + 1} of ${txIds.length} in block #${blockHeight}`);
|
logger.debug(`Indexing tx ${i + 1} of ${txIds.length} in block #${blockHeight}`);
|
||||||
|
@ -104,16 +112,6 @@ class Blocks {
|
||||||
const tx = await transactionUtils.$getTransactionExtended(txIds[i], false, false, false, addMempoolData);
|
const tx = await transactionUtils.$getTransactionExtended(txIds[i], false, false, false, addMempoolData);
|
||||||
transactions.push(tx);
|
transactions.push(tx);
|
||||||
transactionsFetched++;
|
transactionsFetched++;
|
||||||
} catch (e) {
|
|
||||||
try {
|
|
||||||
if (config.MEMPOOL.BACKEND === 'esplora') {
|
|
||||||
// Try again with core
|
|
||||||
const tx = await transactionUtils.$getTransactionExtended(txIds[i], false, false, true, addMempoolData);
|
|
||||||
transactions.push(tx);
|
|
||||||
transactionsFetched++;
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
const msg = `Cannot fetch coinbase tx ${txIds[i]}. Reason: ` + (e instanceof Error ? e.message : e);
|
const msg = `Cannot fetch coinbase tx ${txIds[i]}. Reason: ` + (e instanceof Error ? e.message : e);
|
||||||
|
@ -124,7 +122,6 @@ class Blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (onlyCoinbase === true) {
|
if (onlyCoinbase === true) {
|
||||||
break; // Fetch the first transaction and exit
|
break; // Fetch the first transaction and exit
|
||||||
|
@ -134,6 +131,7 @@ class Blocks {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
logger.debug(`${transactionsFound} of ${txIds.length} found in mempool. ${transactionsFetched} fetched through backend service.`);
|
logger.debug(`${transactionsFound} of ${txIds.length} found in mempool. ${transactionsFetched} fetched through backend service.`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return transactions;
|
return transactions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ class TransactionUtils {
|
||||||
return (await this.$getTransactionExtended(txId, addPrevouts, lazyPrevouts, forceCore, true)) as MempoolTransactionExtended;
|
return (await this.$getTransactionExtended(txId, addPrevouts, lazyPrevouts, forceCore, true)) as MempoolTransactionExtended;
|
||||||
}
|
}
|
||||||
|
|
||||||
private extendTransaction(transaction: IEsploraApi.Transaction): TransactionExtended {
|
public extendTransaction(transaction: IEsploraApi.Transaction): TransactionExtended {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (transaction.vsize) {
|
if (transaction.vsize) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
Loading…
Add table
Reference in a new issue