List orphaned blocks in the new blocks-bulk API
This commit is contained in:
parent
458f24c9f2
commit
281899f551
@ -25,6 +25,7 @@ import mining from './mining/mining';
|
|||||||
import DifficultyAdjustmentsRepository from '../repositories/DifficultyAdjustmentsRepository';
|
import DifficultyAdjustmentsRepository from '../repositories/DifficultyAdjustmentsRepository';
|
||||||
import PricesRepository from '../repositories/PricesRepository';
|
import PricesRepository from '../repositories/PricesRepository';
|
||||||
import priceUpdater from '../tasks/price-updater';
|
import priceUpdater from '../tasks/price-updater';
|
||||||
|
import chainTips from './chain-tips';
|
||||||
|
|
||||||
class Blocks {
|
class Blocks {
|
||||||
private blocks: BlockExtended[] = [];
|
private blocks: BlockExtended[] = [];
|
||||||
@ -171,6 +172,7 @@ class Blocks {
|
|||||||
blk.extras.coinbaseRaw = blk.extras.coinbaseTx.vin[0].scriptsig;
|
blk.extras.coinbaseRaw = blk.extras.coinbaseTx.vin[0].scriptsig;
|
||||||
blk.extras.usd = priceUpdater.latestPrices.USD;
|
blk.extras.usd = priceUpdater.latestPrices.USD;
|
||||||
blk.extras.medianTimestamp = block.medianTime;
|
blk.extras.medianTimestamp = block.medianTime;
|
||||||
|
blk.extras.orphans = chainTips.getOrphanedBlocksAtHeight(blk.height);
|
||||||
|
|
||||||
if (block.height === 0) {
|
if (block.height === 0) {
|
||||||
blk.extras.medianFee = 0; // 50th percentiles
|
blk.extras.medianFee = 0; // 50th percentiles
|
||||||
@ -204,7 +206,6 @@ class Blocks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
blk.extras.blockTime = 0; // TODO
|
blk.extras.blockTime = 0; // TODO
|
||||||
blk.extras.orphaned = false; // TODO
|
|
||||||
|
|
||||||
blk.extras.feePercentiles = await BlocksSummariesRepository.$getFeePercentilesByBlockId(block.id);
|
blk.extras.feePercentiles = await BlocksSummariesRepository.$getFeePercentilesByBlockId(block.id);
|
||||||
if (blk.extras.feePercentiles !== null) {
|
if (blk.extras.feePercentiles !== null) {
|
||||||
@ -545,6 +546,7 @@ class Blocks {
|
|||||||
} else {
|
} else {
|
||||||
this.currentBlockHeight++;
|
this.currentBlockHeight++;
|
||||||
logger.debug(`New block found (#${this.currentBlockHeight})!`);
|
logger.debug(`New block found (#${this.currentBlockHeight})!`);
|
||||||
|
await chainTips.updateOrphanedBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockHash = await bitcoinApi.$getBlockHash(this.currentBlockHeight);
|
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);
|
blocks.push(block);
|
||||||
fromHeight++;
|
fromHeight++;
|
||||||
}
|
}
|
||||||
|
53
backend/src/api/chain-tips.ts
Normal file
53
backend/src/api/chain-tips.ts
Normal 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();
|
@ -37,6 +37,7 @@ import fundingTxFetcher from './tasks/lightning/sync-tasks/funding-tx-fetcher';
|
|||||||
import forensicsService from './tasks/lightning/forensics.service';
|
import forensicsService from './tasks/lightning/forensics.service';
|
||||||
import priceUpdater from './tasks/price-updater';
|
import priceUpdater from './tasks/price-updater';
|
||||||
import mining from './api/mining/mining';
|
import mining from './api/mining/mining';
|
||||||
|
import chainTips from './api/chain-tips';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
@ -134,6 +135,7 @@ class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
priceUpdater.$run();
|
priceUpdater.$run();
|
||||||
|
await chainTips.updateOrphanedBlocks();
|
||||||
|
|
||||||
this.setUpHttpApiRoutes();
|
this.setUpHttpApiRoutes();
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { IEsploraApi } from './api/bitcoin/esplora-api.interface';
|
import { IEsploraApi } from './api/bitcoin/esplora-api.interface';
|
||||||
|
import { OrphanedBlock } from './api/chain-tips';
|
||||||
import { HeapNode } from "./utils/pairing-heap";
|
import { HeapNode } from "./utils/pairing-heap";
|
||||||
|
|
||||||
export interface PoolTag {
|
export interface PoolTag {
|
||||||
@ -163,7 +164,7 @@ export interface BlockExtension {
|
|||||||
usd?: number | null;
|
usd?: number | null;
|
||||||
medianTimestamp?: number;
|
medianTimestamp?: number;
|
||||||
blockTime?: number;
|
blockTime?: number;
|
||||||
orphaned?: boolean;
|
orphans?: OrphanedBlock[] | null;
|
||||||
coinbaseAddress?: string | null;
|
coinbaseAddress?: string | null;
|
||||||
coinbaseSignature?: string | null;
|
coinbaseSignature?: string | null;
|
||||||
virtualSize?: number;
|
virtualSize?: number;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user