List orphaned blocks in the new blocks-bulk API

This commit is contained in:
nymkappa 2023-02-18 14:10:07 +09:00
parent 458f24c9f2
commit 281899f551
No known key found for this signature in database
GPG Key ID: E155910B16E8BD04
4 changed files with 64 additions and 2 deletions

View File

@ -25,6 +25,7 @@ import mining from './mining/mining';
import DifficultyAdjustmentsRepository from '../repositories/DifficultyAdjustmentsRepository';
import PricesRepository from '../repositories/PricesRepository';
import priceUpdater from '../tasks/price-updater';
import chainTips from './chain-tips';
class Blocks {
private blocks: BlockExtended[] = [];
@ -171,6 +172,7 @@ class Blocks {
blk.extras.coinbaseRaw = blk.extras.coinbaseTx.vin[0].scriptsig;
blk.extras.usd = priceUpdater.latestPrices.USD;
blk.extras.medianTimestamp = block.medianTime;
blk.extras.orphans = chainTips.getOrphanedBlocksAtHeight(blk.height);
if (block.height === 0) {
blk.extras.medianFee = 0; // 50th percentiles
@ -204,7 +206,6 @@ class Blocks {
}
blk.extras.blockTime = 0; // TODO
blk.extras.orphaned = false; // TODO
blk.extras.feePercentiles = await BlocksSummariesRepository.$getFeePercentilesByBlockId(block.id);
if (blk.extras.feePercentiles !== null) {
@ -545,6 +546,7 @@ class Blocks {
} else {
this.currentBlockHeight++;
logger.debug(`New block found (#${this.currentBlockHeight})!`);
await chainTips.updateOrphanedBlocks();
}
const blockHash = await bitcoinApi.$getBlockHash(this.currentBlockHeight);
@ -812,6 +814,10 @@ class Blocks {
}
}
// Re-org can happen after indexing so we need to always get the
// latest state from core
block.orphans = chainTips.getOrphanedBlocksAtHeight(block.height);
blocks.push(block);
fromHeight++;
}

View File

@ -0,0 +1,53 @@
import logger from "../logger";
import bitcoinClient from "./bitcoin/bitcoin-client";
export interface ChainTip {
height: number;
hash: string;
branchlen: number;
status: 'invalid' | 'active' | 'valid-fork' | 'valid-headers' | 'headers-only';
};
export interface OrphanedBlock {
height: number;
hash: string;
status: 'valid-fork' | 'valid-headers' | 'headers-only';
}
class ChainTips {
private chainTips: ChainTip[] = [];
private orphanedBlocks: OrphanedBlock[] = [];
public async updateOrphanedBlocks(): Promise<void> {
this.chainTips = await bitcoinClient.getChainTips();
this.orphanedBlocks = [];
for (const chain of this.chainTips) {
if (chain.status === 'valid-fork' || chain.status === 'valid-headers' || chain.status === 'headers-only') {
let block = await bitcoinClient.getBlock(chain.hash);
while (block && block.confirmations === -1) {
this.orphanedBlocks.push({
height: block.height,
hash: block.hash,
status: chain.status
});
block = await bitcoinClient.getBlock(block.previousblockhash);
}
}
}
logger.debug(`Updated orphaned blocks cache. Found ${this.orphanedBlocks.length} orphaned blocks`);
}
public getOrphanedBlocksAtHeight(height: number): OrphanedBlock[] {
const orphans: OrphanedBlock[] = [];
for (const block of this.orphanedBlocks) {
if (block.height === height) {
orphans.push(block);
}
}
return orphans;
}
}
export default new ChainTips();

View File

@ -37,6 +37,7 @@ import fundingTxFetcher from './tasks/lightning/sync-tasks/funding-tx-fetcher';
import forensicsService from './tasks/lightning/forensics.service';
import priceUpdater from './tasks/price-updater';
import mining from './api/mining/mining';
import chainTips from './api/chain-tips';
import { AxiosError } from 'axios';
class Server {
@ -134,6 +135,7 @@ class Server {
}
priceUpdater.$run();
await chainTips.updateOrphanedBlocks();
this.setUpHttpApiRoutes();

View File

@ -1,4 +1,5 @@
import { IEsploraApi } from './api/bitcoin/esplora-api.interface';
import { OrphanedBlock } from './api/chain-tips';
import { HeapNode } from "./utils/pairing-heap";
export interface PoolTag {
@ -163,7 +164,7 @@ export interface BlockExtension {
usd?: number | null;
medianTimestamp?: number;
blockTime?: number;
orphaned?: boolean;
orphans?: OrphanedBlock[] | null;
coinbaseAddress?: string | null;
coinbaseSignature?: string | null;
virtualSize?: number;