Merge pull request #3442 from mempool/nymkappa/reorg-keep-templates
When a re-org happens, keep the block templates for audit
This commit is contained in:
		
						commit
						2ef340712f
					
				@ -590,11 +590,10 @@ class Blocks {
 | 
			
		||||
        if (!fastForwarded) {
 | 
			
		||||
          const lastBlock = await blocksRepository.$getBlockByHeight(blockExtended.height - 1);
 | 
			
		||||
          if (lastBlock !== null && blockExtended.previousblockhash !== lastBlock.id) {
 | 
			
		||||
            logger.warn(`Chain divergence detected at block ${lastBlock.height}, re-indexing most recent data`);
 | 
			
		||||
            logger.warn(`Chain divergence detected at block ${lastBlock.height}, re-indexing most recent data`, logger.tags.mining);
 | 
			
		||||
            // We assume there won't be a reorg with more than 10 block depth
 | 
			
		||||
            await BlocksRepository.$deleteBlocksFrom(lastBlock.height - 10);
 | 
			
		||||
            await HashratesRepository.$deleteLastEntries();
 | 
			
		||||
            await BlocksSummariesRepository.$deleteBlocksFrom(lastBlock.height - 10);
 | 
			
		||||
            await cpfpRepository.$deleteClustersFrom(lastBlock.height - 10);
 | 
			
		||||
            for (let i = 10; i >= 0; --i) {
 | 
			
		||||
              const newBlock = await this.$indexBlock(lastBlock.height - i);
 | 
			
		||||
@ -605,7 +604,7 @@ class Blocks {
 | 
			
		||||
            }
 | 
			
		||||
            await mining.$indexDifficultyAdjustments();
 | 
			
		||||
            await DifficultyAdjustmentsRepository.$deleteLastAdjustment();
 | 
			
		||||
            logger.info(`Re-indexed 10 blocks and summaries. Also re-indexed the last difficulty adjustments. Will re-index latest hashrates in a few seconds.`);
 | 
			
		||||
            logger.info(`Re-indexed 10 blocks and summaries. Also re-indexed the last difficulty adjustments. Will re-index latest hashrates in a few seconds.`, logger.tags.mining);
 | 
			
		||||
            indexer.reindex();
 | 
			
		||||
          }
 | 
			
		||||
          await blocksRepository.$saveBlockInDatabase(blockExtended);
 | 
			
		||||
@ -737,7 +736,7 @@ class Blocks {
 | 
			
		||||
 | 
			
		||||
    // Index the response if needed
 | 
			
		||||
    if (Common.blocksSummariesIndexingEnabled() === true) {
 | 
			
		||||
      await BlocksSummariesRepository.$saveSummary({height: block.height, mined: summary});
 | 
			
		||||
      await BlocksSummariesRepository.$saveTransactions(block.height, block.hash, summary.transactions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return summary.transactions;
 | 
			
		||||
@ -853,7 +852,7 @@ class Blocks {
 | 
			
		||||
        if (cleanBlock.fee_amt_percentiles === null) {
 | 
			
		||||
          const block = await bitcoinClient.getBlock(cleanBlock.hash, 2);
 | 
			
		||||
          const summary = this.summarizeBlock(block);
 | 
			
		||||
          await BlocksSummariesRepository.$saveSummary({ height: block.height, mined: summary });
 | 
			
		||||
          await BlocksSummariesRepository.$saveTransactions(cleanBlock.height, cleanBlock.hash, summary.transactions);
 | 
			
		||||
          cleanBlock.fee_amt_percentiles = await BlocksSummariesRepository.$getFeePercentilesByBlockId(cleanBlock.hash);
 | 
			
		||||
        }
 | 
			
		||||
        if (cleanBlock.fee_amt_percentiles !== null) {
 | 
			
		||||
 | 
			
		||||
@ -466,30 +466,6 @@ class BlocksRepository {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get one block by hash
 | 
			
		||||
   */
 | 
			
		||||
  public async $getBlockByHash(hash: string): Promise<object | null> {
 | 
			
		||||
    try {
 | 
			
		||||
      const query = `
 | 
			
		||||
        SELECT ${BLOCK_DB_FIELDS}
 | 
			
		||||
        FROM blocks
 | 
			
		||||
        JOIN pools ON blocks.pool_id = pools.id
 | 
			
		||||
        WHERE hash = ?;
 | 
			
		||||
      `;
 | 
			
		||||
      const [rows]: any[] = await DB.query(query, [hash]);
 | 
			
		||||
 | 
			
		||||
      if (rows.length <= 0) {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
      return await this.formatDbBlockIntoExtendedBlock(rows[0]);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err(`Cannot get indexed block ${hash}. Reason: ` + (e instanceof Error ? e.message : e));
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return blocks difficulty
 | 
			
		||||
   */
 | 
			
		||||
@ -599,7 +575,6 @@ class BlocksRepository {
 | 
			
		||||
        if (blocks[idx].previous_block_hash !== blocks[idx - 1].hash) {
 | 
			
		||||
          logger.warn(`Chain divergence detected at block ${blocks[idx - 1].height}`);
 | 
			
		||||
          await this.$deleteBlocksFrom(blocks[idx - 1].height);
 | 
			
		||||
          await BlocksSummariesRepository.$deleteBlocksFrom(blocks[idx - 1].height);
 | 
			
		||||
          await HashratesRepository.$deleteHashratesFromTimestamp(blocks[idx - 1].timestamp - 604800);
 | 
			
		||||
          await DifficultyAdjustmentsRepository.$deleteAdjustementsFromHeight(blocks[idx - 1].height);
 | 
			
		||||
          return false;
 | 
			
		||||
@ -619,7 +594,7 @@ class BlocksRepository {
 | 
			
		||||
   * Delete blocks from the database from blockHeight
 | 
			
		||||
   */
 | 
			
		||||
  public async $deleteBlocksFrom(blockHeight: number) {
 | 
			
		||||
    logger.info(`Delete newer blocks from height ${blockHeight} from the database`);
 | 
			
		||||
    logger.info(`Delete newer blocks from height ${blockHeight} from the database`, logger.tags.mining);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      await DB.query(`DELETE FROM blocks where height >= ${blockHeight}`);
 | 
			
		||||
@ -997,6 +972,7 @@ class BlocksRepository {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If we're missing block summary related field, check if we can populate them on the fly now
 | 
			
		||||
    // This is for example triggered upon re-org
 | 
			
		||||
    if (Common.blocksSummariesIndexingEnabled() &&
 | 
			
		||||
      (extras.medianFeeAmt === null || extras.feePercentiles === null))
 | 
			
		||||
    {
 | 
			
		||||
@ -1004,7 +980,7 @@ class BlocksRepository {
 | 
			
		||||
      if (extras.feePercentiles === null) {
 | 
			
		||||
        const block = await bitcoinClient.getBlock(dbBlk.id, 2);
 | 
			
		||||
        const summary = blocks.summarizeBlock(block);
 | 
			
		||||
        await BlocksSummariesRepository.$saveSummary({ height: block.height, mined: summary });
 | 
			
		||||
        await BlocksSummariesRepository.$saveTransactions(dbBlk.height, dbBlk.hash, summary.transactions);
 | 
			
		||||
        extras.feePercentiles = await BlocksSummariesRepository.$getFeePercentilesByBlockId(dbBlk.id);
 | 
			
		||||
      }
 | 
			
		||||
      if (extras.feePercentiles !== null) {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import DB from '../database';
 | 
			
		||||
import logger from '../logger';
 | 
			
		||||
import { BlockSummary } from '../mempool.interfaces';
 | 
			
		||||
import { BlockSummary, TransactionStripped } from '../mempool.interfaces';
 | 
			
		||||
 | 
			
		||||
class BlocksSummariesRepository {
 | 
			
		||||
  public async $getByBlockId(id: string): Promise<BlockSummary | undefined> {
 | 
			
		||||
@ -17,7 +17,7 @@ class BlocksSummariesRepository {
 | 
			
		||||
    return undefined;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $saveSummary(params: { height: number, mined?: BlockSummary}) {
 | 
			
		||||
  public async $saveSummary(params: { height: number, mined?: BlockSummary}): Promise<void> {
 | 
			
		||||
    const blockId = params.mined?.id;
 | 
			
		||||
    try {
 | 
			
		||||
      const transactions = JSON.stringify(params.mined?.transactions || []);
 | 
			
		||||
@ -37,6 +37,20 @@ class BlocksSummariesRepository {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $saveTransactions(blockHeight: number, blockId: string, transactions: TransactionStripped[]): Promise<void> {
 | 
			
		||||
    try {
 | 
			
		||||
      const transactionsStr = JSON.stringify(transactions);
 | 
			
		||||
      await DB.query(`
 | 
			
		||||
        INSERT INTO blocks_summaries
 | 
			
		||||
        SET height = ?, transactions = ?, id = ?
 | 
			
		||||
        ON DUPLICATE KEY UPDATE transactions = ?`,
 | 
			
		||||
        [blockHeight, transactionsStr, blockId, transactionsStr]);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      logger.debug(`Cannot save block summary transactions for ${blockId}. Reason: ${e instanceof Error ? e.message : e}`);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $saveTemplate(params: { height: number, template: BlockSummary}) {
 | 
			
		||||
    const blockId = params.template?.id;
 | 
			
		||||
    try {
 | 
			
		||||
@ -68,19 +82,6 @@ class BlocksSummariesRepository {
 | 
			
		||||
    return [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Delete blocks from the database from blockHeight
 | 
			
		||||
   */
 | 
			
		||||
  public async $deleteBlocksFrom(blockHeight: number) {
 | 
			
		||||
    logger.info(`Delete newer blocks summary from height ${blockHeight} from the database`);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      await DB.query(`DELETE FROM blocks_summaries where height >= ${blockHeight}`);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot delete indexed blocks summaries. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the fee percentiles if the block has already been indexed, [] otherwise
 | 
			
		||||
   * 
 | 
			
		||||
 | 
			
		||||
@ -220,7 +220,7 @@ class HashratesRepository {
 | 
			
		||||
   * Delete hashrates from the database from timestamp
 | 
			
		||||
   */
 | 
			
		||||
  public async $deleteHashratesFromTimestamp(timestamp: number) {
 | 
			
		||||
    logger.info(`Delete newer hashrates from timestamp ${new Date(timestamp * 1000).toUTCString()} from the database`);
 | 
			
		||||
    logger.info(`Delete newer hashrates from timestamp ${new Date(timestamp * 1000).toUTCString()} from the database`, logger.tags.mining);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      await DB.query(`DELETE FROM hashrates WHERE hashrate_timestamp >= FROM_UNIXTIME(?)`, [timestamp]);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user