Fetch block txs from mempool/electrs in bulk
This commit is contained in:
		
							parent
							
								
									81d1c0a4d5
								
							
						
					
					
						commit
						0ebfd6f017
					
				| @ -8,6 +8,7 @@ export interface AbstractBitcoinApi { | ||||
|   $getBlockHeightTip(): Promise<number>; | ||||
|   $getBlockHashTip(): Promise<string>; | ||||
|   $getTxIdsForBlock(hash: string): Promise<string[]>; | ||||
|   $getTxsForBlock(hash: string): Promise<IEsploraApi.Transaction[]>; | ||||
|   $getBlockHash(height: number): Promise<string>; | ||||
|   $getBlockHeader(hash: string): Promise<string>; | ||||
|   $getBlock(hash: string): Promise<IEsploraApi.Block>; | ||||
|  | ||||
| @ -81,6 +81,10 @@ class BitcoinApi implements AbstractBitcoinApi { | ||||
|       .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> { | ||||
|     return this.bitcoindClient.getBlock(hash, 0) | ||||
|       .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'); | ||||
|   } | ||||
| 
 | ||||
|   $getTxsForBlock(hash: string): Promise<IEsploraApi.Transaction[]> { | ||||
|     return this.$queryWrapper<IEsploraApi.Transaction[]>(config.ESPLORA.REST_API_URL + '/block/' + hash + '/txs'); | ||||
|   } | ||||
| 
 | ||||
|   $getBlockHash(height: number): Promise<string> { | ||||
|     return this.$queryWrapper<string>(config.ESPLORA.REST_API_URL + '/block-height/' + height); | ||||
|   } | ||||
|  | ||||
| @ -80,40 +80,38 @@ class Blocks { | ||||
|     quiet: boolean = false, | ||||
|     addMempoolData: boolean = false, | ||||
|   ): Promise<TransactionExtended[]> { | ||||
|     const transactions: TransactionExtended[] = []; | ||||
|     if (!txIds) { | ||||
|       txIds = await bitcoinApi.$getTxIdsForBlock(blockHash); | ||||
|     } | ||||
|     let transactions: TransactionExtended[] = []; | ||||
| 
 | ||||
|     const mempool = memPool.getMempool(); | ||||
|     let transactionsFound = 0; | ||||
|     let transactionsFetched = 0; | ||||
| 
 | ||||
|     for (let i = 0; i < txIds.length; i++) { | ||||
|       if (mempool[txIds[i]]) { | ||||
|         // We update blocks before the mempool (index.ts), therefore we can
 | ||||
|         // optimize here by directly fetching txs in the "outdated" mempool
 | ||||
|         transactions.push(mempool[txIds[i]]); | ||||
|         transactionsFound++; | ||||
|       } else if (config.MEMPOOL.BACKEND === 'esplora' || !memPool.hasPriority() || i === 0) { | ||||
|         // 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
 | ||||
|           logger.debug(`Indexing tx ${i + 1} of ${txIds.length} in block #${blockHeight}`); | ||||
|         } | ||||
|         try { | ||||
|           const tx = await transactionUtils.$getTransactionExtended(txIds[i], false, false, false, addMempoolData); | ||||
|           transactions.push(tx); | ||||
|           transactionsFetched++; | ||||
|         } catch (e) { | ||||
|     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++) { | ||||
|         if (mempool[txIds[i]]) { | ||||
|           // We update blocks before the mempool (index.ts), therefore we can
 | ||||
|           // optimize here by directly fetching txs in the "outdated" mempool
 | ||||
|           transactions.push(mempool[txIds[i]]); | ||||
|           transactionsFound++; | ||||
|         } else if (!memPool.hasPriority() || i === 0) { | ||||
|           // 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
 | ||||
|             logger.debug(`Indexing tx ${i + 1} of ${txIds.length} in block #${blockHeight}`); | ||||
|           } | ||||
|           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; | ||||
|             } | ||||
|             const tx = await transactionUtils.$getTransactionExtended(txIds[i], false, false, false, addMempoolData); | ||||
|             transactions.push(tx); | ||||
|             transactionsFetched++; | ||||
|           } catch (e) { | ||||
|             if (i === 0) { | ||||
|               const msg = `Cannot fetch coinbase tx ${txIds[i]}. Reason: ` + (e instanceof Error ? e.message : e);  | ||||
| @ -124,17 +122,17 @@ class Blocks { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         if (onlyCoinbase === true) { | ||||
|           break; // Fetch the first transaction and exit
 | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       if (onlyCoinbase === true) { | ||||
|         break; // Fetch the first transaction and exit
 | ||||
|       if (!quiet) { | ||||
|         logger.debug(`${transactionsFound} of ${txIds.length} found in mempool. ${transactionsFetched} fetched through backend service.`); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (!quiet) { | ||||
|       logger.debug(`${transactionsFound} of ${txIds.length} found in mempool. ${transactionsFetched} fetched through backend service.`); | ||||
|     } | ||||
| 
 | ||||
|     return transactions; | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -53,7 +53,7 @@ class TransactionUtils { | ||||
|     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
 | ||||
|     if (transaction.vsize) { | ||||
|       // @ts-ignore
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user