fix: fetch chain tips from db, not all blocks

This commit is contained in:
rodribp 2026-06-14 22:48:21 -06:00
parent 8733ce74a0
commit a8b1798eda
No known key found for this signature in database
GPG key ID: CC349739DA92EE20
2 changed files with 29 additions and 27 deletions

View file

@ -24,6 +24,7 @@ export interface StaleTip extends ChainTip {
export interface OrphanedBlock {
height: number;
hash: string;
branchlen: number;
status: 'valid-fork' | 'valid-headers' | 'headers-only';
prevhash: string;
}
@ -70,6 +71,7 @@ class ChainTips {
orphan = {
height: block.height,
hash: block.id,
branchlen: chain.branchlen - 1,
status: chain.status,
prevhash: block.previousblockhash,
};
@ -173,7 +175,7 @@ class ChainTips {
this.staleTips[staleBlock.height] = {
height: staleBlock.height,
hash: staleBlock.id,
branchlen: tip.height - staleBlock.height,
branchlen: tip.branchlen,
status: tip.status,
stale: staleBlock,
canonical: canonicalBlock,
@ -213,7 +215,7 @@ class ChainTips {
return Object.values(this.staleTips).sort((a, b) => b.height - a.height);
}
/** @asyncSafe */
/** @asyncUnsafe */
public async $getStaleTipsPage(fromHeight: number | undefined, limit: number): Promise<StaleTip[]> {
const cacheTips = this.getStaleTips();
if (!Common.indexingEnabled()) {
@ -221,15 +223,7 @@ class ChainTips {
return page.slice(0, limit);
}
const staleBlocks = await BlocksRepository.$getStaleBlocks(fromHeight, limit);
// map the previous block hashes of each stale block so we can reconstruct branch lengths
const staleByPrevhash: { [prevhash: string]: BlockExtended } = {};
for (const block of staleBlocks) {
if (block.previousblockhash) {
staleByPrevhash[block.previousblockhash] = block;
}
}
const staleTips = await BlocksRepository.$getStaleTips(fromHeight, limit);
const cacheTipsMap = new Map<string, StaleTip>();
for (const cacheTip of cacheTips) {
@ -237,29 +231,31 @@ class ChainTips {
}
const tips: StaleTip[] = [];
for (const staleBlock of staleBlocks) {
for (const staleTip of staleTips) {
const cachedTip = cacheTipsMap.get(staleBlock.id);
const cachedTip = cacheTipsMap.get(staleTip.id);
if (cachedTip) {
tips.push(cachedTip);
continue;
}
const canonical = await BlocksRepository.$getBlockByHeight(staleBlock.height);
const canonical = await BlocksRepository.$getBlockByHeight(staleTip.height);
if (!canonical) {
continue;
}
// walk up the stale branch to find its tip, depth = branchTipHeight - staleHeight
let branchTip = staleBlock;
while (staleByPrevhash[branchTip.id]) {
branchTip = staleByPrevhash[branchTip.id];
let prevBlock = await BlocksRepository.$getBlockByHash(staleTip.previousblockhash);
let branchlen = 0;
while(prevBlock?.stale) {
prevBlock = await BlocksRepository.$getBlockByHash(prevBlock.previousblockhash);
branchlen++;
}
tips.push({
height: staleBlock.height,
hash: staleBlock.id,
branchlen: branchTip.height - staleBlock.height,
stale: staleBlock,
height: staleTip.height,
hash: staleTip.id,
branchlen,
stale: staleTip,
canonical,
});
}

View file

@ -604,7 +604,7 @@ class BlocksRepository {
* When fromHeight is defined, only stale blocks strictly below it are returned.
* @asyncSafe
*/
public async $getStaleBlocks(fromHeight: number | undefined, limit: number): Promise<BlockExtended[]> {
public async $getStaleTips(fromHeight: number | undefined, limit: number): Promise<BlockExtended[]> {
try {
const params: (number)[] = [];
let heightFilter = '';
@ -619,18 +619,23 @@ class BlocksRepository {
FROM blocks
JOIN pools ON blocks.pool_id = pools.id
WHERE blocks.stale = 1${heightFilter}
AND NOT EXISTS (
SELECT 1 FROM blocks AS child
WHERE child.previous_block_hash = blocks.hash
AND child.stale = 1
)
ORDER BY blocks.height DESC
LIMIT ?`,
params
);
const staleBlocks: BlockExtended[] = [];
const staleTips: BlockExtended[] = [];
for (const row of rows) {
staleBlocks.push(await this.formatDbBlockIntoExtendedBlock(row as DatabaseBlock));
staleTips.push(await this.formatDbBlockIntoExtendedBlock(row as DatabaseBlock));
}
return staleBlocks;
return staleTips;
} catch (e) {
logger.err(`Cannot get stale blocks. Reason: ` + (e instanceof Error ? e.message : e));
logger.err(`Cannot get stale tips. Reason: ` + (e instanceof Error ? e.message : e));
throw e;
}
}
@ -1292,6 +1297,7 @@ class BlocksRepository {
blk.previousblockhash = dbBlk.previousblockhash;
blk.mediantime = dbBlk.mediantime;
blk.indexVersion = dbBlk.index_version;
blk.stale = dbBlk.stale;
// BlockExtension
extras.totalFees = dbBlk.totalFees;
extras.medianFee = dbBlk.medianFee;