Merge pull request #3932 from mempool/mononaut/stale-blocks
Stale blocks
This commit is contained in:
		
						commit
						168cc9c1bf
					
				| @ -29,6 +29,7 @@ class BitcoinApi implements AbstractBitcoinApi { | ||||
|       weight: block.weight, | ||||
|       previousblockhash: block.previousblockhash, | ||||
|       mediantime: block.mediantime, | ||||
|       stale: block.confirmations === -1, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -89,6 +89,7 @@ export namespace IEsploraApi { | ||||
|     weight: number; | ||||
|     previousblockhash: string; | ||||
|     mediantime: number; | ||||
|     stale: boolean; | ||||
|   } | ||||
| 
 | ||||
|   export interface Address { | ||||
|  | ||||
| @ -656,10 +656,6 @@ class Blocks { | ||||
|       const blockSummary: BlockSummary = this.summarizeBlockTransactions(block.id, cpfpSummary.transactions); | ||||
|       this.updateTimerProgress(timer, `got block data for ${this.currentBlockHeight}`); | ||||
| 
 | ||||
|       // start async callbacks
 | ||||
|       this.updateTimerProgress(timer, `starting async callbacks for ${this.currentBlockHeight}`); | ||||
|       const callbackPromises = this.newAsyncBlockCallbacks.map((cb) => cb(blockExtended, txIds, transactions)); | ||||
| 
 | ||||
|       if (Common.indexingEnabled()) { | ||||
|         if (!fastForwarded) { | ||||
|           const lastBlock = await blocksRepository.$getBlockByHeight(blockExtended.height - 1); | ||||
| @ -671,9 +667,11 @@ class Blocks { | ||||
|             await BlocksRepository.$deleteBlocksFrom(lastBlock.height - 10); | ||||
|             await HashratesRepository.$deleteLastEntries(); | ||||
|             await cpfpRepository.$deleteClustersFrom(lastBlock.height - 10); | ||||
|             this.blocks = this.blocks.slice(0, -10); | ||||
|             this.updateTimerProgress(timer, `rolled back chain divergence from ${this.currentBlockHeight}`); | ||||
|             for (let i = 10; i >= 0; --i) { | ||||
|               const newBlock = await this.$indexBlock(lastBlock.height - i); | ||||
|               this.blocks.push(newBlock); | ||||
|               this.updateTimerProgress(timer, `reindexed block`); | ||||
|               let cpfpSummary; | ||||
|               if (config.MEMPOOL.CPFP_INDEXING) { | ||||
| @ -722,6 +720,10 @@ class Blocks { | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       // start async callbacks
 | ||||
|       this.updateTimerProgress(timer, `starting async callbacks for ${this.currentBlockHeight}`); | ||||
|       const callbackPromises = this.newAsyncBlockCallbacks.map((cb) => cb(blockExtended, txIds, transactions)); | ||||
| 
 | ||||
|       if (block.height % 2016 === 0) { | ||||
|         if (Common.indexingEnabled()) { | ||||
|           await DifficultyAdjustmentsRepository.$saveAdjustments({ | ||||
| @ -814,6 +816,16 @@ class Blocks { | ||||
|     return blockExtended; | ||||
|   } | ||||
| 
 | ||||
|   public async $indexStaleBlock(hash: string): Promise<BlockExtended> { | ||||
|     const block: IEsploraApi.Block = await bitcoinCoreApi.$getBlock(hash); | ||||
|     const transactions = await this.$getTransactionsExtended(hash, block.height, true); | ||||
|     const blockExtended = await this.$getBlockExtended(block, transactions); | ||||
| 
 | ||||
|     blockExtended.canonical = await bitcoinApi.$getBlockHash(block.height); | ||||
| 
 | ||||
|     return blockExtended; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Get one block by its hash | ||||
|    */ | ||||
| @ -831,8 +843,12 @@ class Blocks { | ||||
| 
 | ||||
|     // Bitcoin network, add our custom data on top
 | ||||
|     const block: IEsploraApi.Block = await bitcoinCoreApi.$getBlock(hash); | ||||
|     if (block.stale) { | ||||
|       return await this.$indexStaleBlock(hash); | ||||
|     } else { | ||||
|       return await this.$indexBlock(block.height); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public async $getStrippedBlockTransactions(hash: string, skipMemoryCache = false, | ||||
|     skipDBLookup = false, cpfpSummary?: CpfpSummary, blockHeight?: number): Promise<TransactionStripped[]> | ||||
|  | ||||
| @ -227,6 +227,7 @@ export interface BlockExtension { | ||||
|  */ | ||||
| export interface BlockExtended extends IEsploraApi.Block { | ||||
|   extras: BlockExtension; | ||||
|   canonical?: string; | ||||
| } | ||||
| 
 | ||||
| export interface BlockSummary { | ||||
|  | ||||
| @ -62,8 +62,7 @@ class BlocksAuditRepositories { | ||||
|   public async $getBlockAudit(hash: string): Promise<any> { | ||||
|     try { | ||||
|       const [rows]: any[] = await DB.query( | ||||
|         `SELECT blocks.height, blocks.hash as id, UNIX_TIMESTAMP(blocks.blockTimestamp) as timestamp, blocks.size,
 | ||||
|         blocks.weight, blocks.tx_count, | ||||
|         `SELECT blocks_audits.height, blocks_audits.hash as id, UNIX_TIMESTAMP(blocks_audits.time) as timestamp,
 | ||||
|         template, | ||||
|         missing_txs as missingTxs, | ||||
|         added_txs as addedTxs, | ||||
| @ -73,7 +72,6 @@ class BlocksAuditRepositories { | ||||
|         expected_fees as expectedFees, | ||||
|         expected_weight as expectedWeight | ||||
|         FROM blocks_audits | ||||
|         JOIN blocks ON blocks.hash = blocks_audits.hash | ||||
|         JOIN blocks_templates ON blocks_templates.id = blocks_audits.hash | ||||
|         WHERE blocks_audits.hash = "${hash}" | ||||
|       `);
 | ||||
|  | ||||
| @ -1,6 +1,10 @@ | ||||
| <div class="container-xl" (window:resize)="onResize($event)"> | ||||
| 
 | ||||
|   <div class="title-block" [class.time-ltr]="timeLtr" id="block"> | ||||
|     <div *ngIf="block?.stale" class="alert alert-mempool" role="alert"> | ||||
|       <span i18n="block.reorged|Block reorg" class="alert-text">This block does not belong to the main chain, it has been replaced by:</span> | ||||
|       <app-truncate [text]="block.canonical" [lastChars]="12" [link]="['/block/' | relativeUrl, block.canonical]" [maxWidth]="480"></app-truncate> | ||||
|     </div> | ||||
|     <h1> | ||||
|       <ng-container *ngIf="blockHeight == null || blockHeight > 0; else genesis" i18n="shared.block-title">Block</ng-container> | ||||
|       <ng-template #genesis i18n="@@2303359202781425764">Genesis</ng-template> | ||||
| @ -23,6 +27,8 @@ | ||||
| 
 | ||||
|     <div class="grow"></div> | ||||
| 
 | ||||
|     <button *ngIf="block?.stale" type="button" class="btn btn-sm btn-danger container-button" i18n="block.stale|Stale block state">Stale</button> | ||||
| 
 | ||||
|     <button [routerLink]="['/' | relativeUrl]" class="btn btn-sm">✕</button> | ||||
|   </div> | ||||
| 
 | ||||
|  | ||||
| @ -1,3 +1,26 @@ | ||||
| .title-block { | ||||
|   flex-wrap: wrap; | ||||
|   align-items: baseline; | ||||
|   @media (min-width: 650px) { | ||||
|     flex-direction: row; | ||||
|   } | ||||
|   h1 { | ||||
|     margin: 0rem; | ||||
|     margin-right: 15px; | ||||
|     line-height: 1; | ||||
|   } | ||||
| 
 | ||||
|   .alert-mempool { | ||||
|     flex-direction: row; | ||||
|     flex-wrap: wrap; | ||||
|   } | ||||
| 
 | ||||
|   .container-button { | ||||
|     align-self: center; | ||||
|     margin-right: 1em; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .qr-wrapper { | ||||
|   background-color: #FFF; | ||||
|   padding: 10px; | ||||
|  | ||||
| @ -120,6 +120,8 @@ export interface Block { | ||||
|   size: number; | ||||
|   weight: number; | ||||
|   previousblockhash: string; | ||||
|   stale?: boolean; | ||||
|   canonical?: string; | ||||
| } | ||||
| 
 | ||||
| export interface Address { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user