Skip to content

Commit

Permalink
fix: tune finalized condition (#136)
Browse files Browse the repository at this point in the history
* fix: tune finalized condition

* fix: tune finalized condition
  • Loading branch information
vgorkavenko authored Mar 16, 2023
1 parent 340018a commit 48b1ce8
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { rejectDelay } from 'common/functions/rejectDelay';
import { retrier } from 'common/functions/retrier';
import { urljoin } from 'common/functions/urljoin';
import { PrometheusService, TrackCLRequest } from 'common/prometheus';
import { EpochProcessingState } from 'storage/clickhouse';

import { BlockCache, BlockCacheService } from './block-cache';
import { MaxDeepError, ResponseError, errCommon, errRequest } from './errors';
Expand Down Expand Up @@ -115,6 +116,35 @@ export class ConsensusProviderService {
);
}

public async getFinalizedBlockHeader(processingState: EpochProcessingState): Promise<BlockHeaderResponse | void> {
return await this.retryRequest<BlockHeaderResponse>(
async (apiURL: string) => this.apiGet(apiURL, this.endpoints.beaconHeaders('finalized')),
{
maxRetries: this.config.get('CL_API_GET_BLOCK_INFO_MAX_RETRIES'),
useFallbackOnResolved: (r) => {
if (Number(r.data.header.message.slot) > this.lastFinalizedSlot.slot) {
this.lastFinalizedSlot = { slot: Number(r.data.header.message.slot), fetchTime: Number(Date.now()) };
}
if (processingState.epoch <= Math.trunc(this.lastFinalizedSlot.slot / this.config.get('FETCH_INTERVAL_SLOTS'))) {
// if our last processed epoch is less than last finalized, we shouldn't use fallback
return false;
} else if (Number(Date.now()) - this.lastFinalizedSlot.fetchTime > 420 * 1000) {
// if 'finalized' slot doesn't change ~7m we must switch to fallback
this.logger.error("Finalized slot hasn't changed in ~7m");
return true;
}
// for other states don't use fallback on resolved
return false;
},
},
).catch((e) => {
if (404 != e.$httpCode) {
this.logger.error('Unexpected status code while fetching block header');
throw e;
}
});
}

public async getBlockHeader(blockId: BlockId): Promise<BlockHeaderResponse | void> {
const cached: BlockCache = this.cache.get(String(blockId));
if (cached && (cached.missed || cached.header)) {
Expand All @@ -124,18 +154,7 @@ export class ConsensusProviderService {

const blockHeader = await this.retryRequest<BlockHeaderResponse>(
async (apiURL: string) => this.apiGet(apiURL, this.endpoints.beaconHeaders(blockId)),
{
maxRetries: this.config.get('CL_API_GET_BLOCK_INFO_MAX_RETRIES'),
useFallbackOnResolved: (r) => {
if (blockId == 'finalized') {
if (Number(r.data.header.message.slot) > this.lastFinalizedSlot.slot) {
this.lastFinalizedSlot = { slot: Number(r.data.header.message.slot), fetchTime: Number(Date.now()) };
}
}
// for other states don't use fallback on resolved
return false;
},
},
{ maxRetries: this.config.get('CL_API_GET_BLOCK_INFO_MAX_RETRIES') },
).catch((e) => {
if (404 != e.$httpCode) {
this.logger.error('Unexpected status code while fetching block header');
Expand Down
8 changes: 5 additions & 3 deletions src/inspector/inspector.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,15 @@ export class InspectorService implements OnModuleInit {

protected async getEpochDataToProcess(): Promise<EpochProcessingState & { slot: Slot }> {
const chosen = await this.chooseEpochToProcess();
const latestFinalizedBeaconBlock = Number((<BlockHeaderResponse>await this.clClient.getBlockHeader('finalized')).header.message.slot);
const latestFinalizedBeaconBlock = Number(
(<BlockHeaderResponse>await this.clClient.getFinalizedBlockHeader(chosen)).header.message.slot,
);
let latestFinalizedEpoch = Math.trunc(latestFinalizedBeaconBlock / this.config.get('FETCH_INTERVAL_SLOTS'));
if (latestFinalizedEpoch * this.config.get('FETCH_INTERVAL_SLOTS') == latestFinalizedBeaconBlock) {
// if it's the first slot of epoch, it finalizes previous epoch
latestFinalizedEpoch -= 1;
}
const existedHeader = (await this.clClient.getBeaconBlockHeaderOrPreviousIfMissed(chosen.slot)).header.message;
if (Number(existedHeader.slot) > latestFinalizedBeaconBlock) {
if (chosen.slot > latestFinalizedBeaconBlock) {
// new finalized slot hasn't happened, from which parent we can get information about needed state
// just wait `CHAIN_SLOT_TIME_SECONDS` until finality happens
const sleepTime = this.config.get('CHAIN_SLOT_TIME_SECONDS');
Expand All @@ -91,6 +92,7 @@ export class InspectorService implements OnModuleInit {
});
}
// new finalized epoch has happened, from which parent we can get information about needed state
const existedHeader = (await this.clClient.getBeaconBlockHeaderOrPreviousIfMissed(chosen.slot)).header.message;
this.logger.log(`Latest finalized epoch [${latestFinalizedEpoch}]. Next epoch to process [${chosen.epoch}]`);
if (chosen.slot == Number(existedHeader.slot)) {
this.logger.log(
Expand Down

0 comments on commit 48b1ce8

Please sign in to comment.