Fix pruning of canonical block if null block is encountered (#499)

This commit is contained in:
Nabarun Gogoi 2023-12-28 15:07:12 +05:30 committed by GitHub
parent a6deed9c27
commit 33e4455f92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 25 additions and 19 deletions

View File

@ -324,8 +324,8 @@ export class Database implements DatabaseInterface {
await this._baseDatabase.deleteEntitiesByConditions(queryRunner, entity, findConditions); await this._baseDatabase.deleteEntitiesByConditions(queryRunner, entity, findConditions);
} }
async getAncestorAtDepth (blockHash: string, depth: number): Promise<string> { async getAncestorAtHeight (blockHash: string, height: number): Promise<string> {
return this._baseDatabase.getAncestorAtDepth(blockHash, depth); return this._baseDatabase.getAncestorAtHeight(blockHash, height);
} }
_getPropertyColumnMapForEntity (entityName: string): Map<string, string> { _getPropertyColumnMapForEntity (entityName: string): Map<string, string> {

View File

@ -744,8 +744,8 @@ export class Indexer implements IndexerInterface {
return this._baseIndexer.updateBlockProgress(block, lastProcessedEventIndex); return this._baseIndexer.updateBlockProgress(block, lastProcessedEventIndex);
} }
async getAncestorAtDepth (blockHash: string, depth: number): Promise<string> { async getAncestorAtHeight (blockHash: string, height: number): Promise<string> {
return this._baseIndexer.getAncestorAtDepth(blockHash, depth); return this._baseIndexer.getAncestorAtHeight(blockHash, height);
} }
async resetWatcherToBlock (blockNumber: number): Promise<void> { async resetWatcherToBlock (blockNumber: number): Promise<void> {

View File

@ -107,9 +107,9 @@ export class Indexer implements IndexerInterface {
return []; return [];
} }
async getAncestorAtDepth (blockHash: string, depth: number): Promise<string> { async getAncestorAtHeight (blockHash: string, height: number): Promise<string> {
assert(blockHash); assert(blockHash);
assert(depth); assert(height);
return ''; return '';
} }

View File

@ -457,15 +457,14 @@ export class Database {
await repo.delete(findConditions); await repo.delete(findConditions);
} }
async getAncestorAtDepth (blockHash: string, depth: number): Promise<string> { async getAncestorAtHeight (blockHash: string, height: number): Promise<string> {
const heirerchicalQuery = ` const heirerchicalQuery = `
WITH RECURSIVE cte_query AS WITH RECURSIVE cte_query AS
( (
SELECT SELECT
block_hash, block_hash,
block_number, block_number,
parent_hash, parent_hash
0 as depth
FROM FROM
block_progress block_progress
WHERE WHERE
@ -474,14 +473,13 @@ export class Database {
SELECT SELECT
b.block_hash, b.block_hash,
b.block_number, b.block_number,
b.parent_hash, b.parent_hash
c.depth + 1
FROM FROM
block_progress b block_progress b
INNER JOIN INNER JOIN
cte_query c ON c.parent_hash = b.block_hash cte_query c ON c.parent_hash = b.block_hash
WHERE WHERE
c.depth < $2 b.block_number >= $2
) )
SELECT SELECT
block_hash, block_number block_hash, block_number
@ -492,7 +490,7 @@ export class Database {
`; `;
// Get ancestor block hash using heirarchical query. // Get ancestor block hash using heirarchical query.
const [{ block_hash: ancestorBlockHash }] = await this._conn.query(heirerchicalQuery, [blockHash, depth]); const [{ block_hash: ancestorBlockHash }] = await this._conn.query(heirerchicalQuery, [blockHash, height]);
return ancestorBlockHash; return ancestorBlockHash;
} }

View File

@ -713,8 +713,8 @@ export class Indexer {
} }
} }
async getAncestorAtDepth (blockHash: string, depth: number): Promise<string> { async getAncestorAtHeight (blockHash: string, height: number): Promise<string> {
return this._db.getAncestorAtDepth(blockHash, depth); return this._db.getAncestorAtHeight(blockHash, height);
} }
async saveEventEntity (dbEvent: EventInterface): Promise<EventInterface> { async saveEventEntity (dbEvent: EventInterface): Promise<EventInterface> {

View File

@ -445,10 +445,18 @@ export class JobRunner {
// We have more than one node at this height, so prune all nodes not reachable from indexed block at max reorg depth from prune height. // We have more than one node at this height, so prune all nodes not reachable from indexed block at max reorg depth from prune height.
// This will lead to orphaned nodes, which will get pruned at the next height. // This will lead to orphaned nodes, which will get pruned at the next height.
if (blocksAtHeight.length > 1) { if (blocksAtHeight.length > 1) {
const [indexedBlock] = await this._indexer.getBlocksAtHeight(pruneBlockHeight + MAX_REORG_DEPTH, false); let indexedBlock: BlockProgressInterface | undefined;
let indexedBlockHeight = pruneBlockHeight + MAX_REORG_DEPTH;
// Loop to find latest indexed block incase null block is encountered
while (!indexedBlock) {
[indexedBlock] = await this._indexer.getBlocksAtHeight(indexedBlockHeight, false);
--indexedBlockHeight;
assert(indexedBlockHeight > pruneBlockHeight, `No blocks found above pruneBlockHeight ${pruneBlockHeight}`);
}
// Get ancestor blockHash from indexed block at prune height. // Get ancestor blockHash from indexed block at prune height.
const ancestorBlockHash = await this._indexer.getAncestorAtDepth(indexedBlock.blockHash, MAX_REORG_DEPTH); const ancestorBlockHash = await this._indexer.getAncestorAtHeight(indexedBlock.blockHash, pruneBlockHeight);
newCanonicalBlockHash = ancestorBlockHash; newCanonicalBlockHash = ancestorBlockHash;
const blocksToBePruned = blocksAtHeight.filter(block => ancestorBlockHash !== block.blockHash); const blocksToBePruned = blocksAtHeight.filter(block => ancestorBlockHash !== block.blockHash);

View File

@ -173,7 +173,7 @@ export interface IndexerInterface {
getLatestCanonicalBlock (): Promise<BlockProgressInterface | undefined> getLatestCanonicalBlock (): Promise<BlockProgressInterface | undefined>
getLatestStateIndexedBlock (): Promise<BlockProgressInterface> getLatestStateIndexedBlock (): Promise<BlockProgressInterface>
getBlockEvents (blockHash: string, where: Where, queryOptions: QueryOptions): Promise<Array<EventInterface>> getBlockEvents (blockHash: string, where: Where, queryOptions: QueryOptions): Promise<Array<EventInterface>>
getAncestorAtDepth (blockHash: string, depth: number): Promise<string> getAncestorAtHeight (blockHash: string, height: number): Promise<string>
saveBlockAndFetchEvents (block: DeepPartial<BlockProgressInterface>): Promise<[ saveBlockAndFetchEvents (block: DeepPartial<BlockProgressInterface>): Promise<[
BlockProgressInterface, BlockProgressInterface,
DeepPartial<EventInterface>[], DeepPartial<EventInterface>[],
@ -249,7 +249,7 @@ export interface DatabaseInterface {
getBlockEvents (blockHash: string, where?: Where, queryOptions?: QueryOptions): Promise<EventInterface[]>; getBlockEvents (blockHash: string, where?: Where, queryOptions?: QueryOptions): Promise<EventInterface[]>;
getEvent (id: string): Promise<EventInterface | undefined> getEvent (id: string): Promise<EventInterface | undefined>
getSyncStatus (queryRunner: QueryRunner): Promise<SyncStatusInterface | undefined> getSyncStatus (queryRunner: QueryRunner): Promise<SyncStatusInterface | undefined>
getAncestorAtDepth (blockHash: string, depth: number): Promise<string> getAncestorAtHeight (blockHash: string, height: number): Promise<string>
getProcessedBlockCountForRange (fromBlockNumber: number, toBlockNumber: number): Promise<{ expected: number, actual: number }>; getProcessedBlockCountForRange (fromBlockNumber: number, toBlockNumber: number): Promise<{ expected: number, actual: number }>;
getEventsInRange (fromBlockNumber: number, toBlockNumber: number): Promise<Array<EventInterface>>; getEventsInRange (fromBlockNumber: number, toBlockNumber: number): Promise<Array<EventInterface>>;
markBlocksAsPruned (queryRunner: QueryRunner, blocks: BlockProgressInterface[]): Promise<void>; markBlocksAsPruned (queryRunner: QueryRunner, blocks: BlockProgressInterface[]): Promise<void>;