diff --git a/docs/errors.md b/docs/errors.md index 6a35dc32a..edc10ec80 100644 --- a/docs/errors.md +++ b/docs/errors.md @@ -873,3 +873,17 @@ Failed to query BlockHashFromNumber from graph node **Solution** Graph-node could not find the block hash given network and block number, check if graph-node has access to a network client that has synced to the required block. + +## IE071 + +**Summary** + +Epoch subgraph required for subgraphs indexing networks in which rpc is unprovided to the indexer agent + +**Description** + +This is a sub-error of `IE069`. It is reported when the indexer agent doesn't have access to an epoch subgraph endpoint to identify the epoch start block for chains other than the settlement network as indicated by start-up option `--ethereum-network`. + +**Solution** + +Please provide a `epoch-subgraph-endpoint` and make sure graph node has consistent network configurations (`mainnet`, `goerli`, `gnosis`) and is on or after version 0.28.0. \ No newline at end of file diff --git a/packages/indexer-common/src/allocations/types.ts b/packages/indexer-common/src/allocations/types.ts index 4cf6ae236..b48376631 100644 --- a/packages/indexer-common/src/allocations/types.ts +++ b/packages/indexer-common/src/allocations/types.ts @@ -1,6 +1,3 @@ -import { IndexingStatusResolver } from '@graphprotocol/indexer-common' -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ - import { Address, SubgraphDeploymentID, toAddress } from '@graphprotocol/common-ts' import { BigNumber } from 'ethers' @@ -197,18 +194,3 @@ export const alias = (identifier: string): string => { throw new Error(`Failed to match chain ids to a network alias`) } } -/* eslint-disable @typescript-eslint/no-explicit-any */ -export const buildEpochBlock = async ( - status: IndexingStatusResolver, - block: any, -): Promise => { - return { - network: block.network.id, - epochNumber: +block.epochNumber, - startBlockNumber: +block.blockNumber, - startBlockHash: await status.blockHashFromNumber( - alias(block.network.id), - +block.blockNumber, - ), - } -} diff --git a/packages/indexer-common/src/errors.ts b/packages/indexer-common/src/errors.ts index ce2ac65c6..21093525e 100644 --- a/packages/indexer-common/src/errors.ts +++ b/packages/indexer-common/src/errors.ts @@ -81,6 +81,7 @@ export enum IndexerErrorCode { IE068 = 'IE068', IE069 = 'IE069', IE070 = 'IE070', + IE071 = 'IE071', } export const INDEXER_ERROR_MESSAGES: Record = { @@ -154,7 +155,8 @@ export const INDEXER_ERROR_MESSAGES: Record = { IE067: 'Failed to query POI for current epoch start block', IE068: 'User-provided POI did not match reference POI from graph-node', IE069: 'Failed to query Epoch Block Oracle Subgraph', - IE070: 'Failed to query BlockHashFromNumber from graph-node', + IE070: 'Failed to query latest valid epoch and block hash', + IE071: 'Add Epoch subgraph support for non-protocol chains', } export type IndexerErrorCause = unknown diff --git a/packages/indexer-common/src/indexer-management/monitor.ts b/packages/indexer-common/src/indexer-management/monitor.ts index 8529ff798..fef9a564a 100644 --- a/packages/indexer-common/src/indexer-management/monitor.ts +++ b/packages/indexer-common/src/indexer-management/monitor.ts @@ -17,7 +17,6 @@ import { NetworkEpochBlock, EpochSubgraph, BlockPointer, - buildEpochBlock, alias, } from '@graphprotocol/indexer-common' import { @@ -576,9 +575,12 @@ export class NetworkMonitor { if (network == this.networkAlias) { return await this.epochManagerCurrentStartBlock(network) } + this.logger.error(`Epoch start block not available for the network`, { + networkName: alias(network), + }) throw indexerError( - IndexerErrorCode.IE069, - `Epoch subgraph not available for indexed chains`, + IndexerErrorCode.IE071, + `Epoch start block not available for network: ${alias(network)}`, ) } try { @@ -613,29 +615,37 @@ export class NetworkMonitor { } if (!result.data.network || !result.data.network.latestValidBlockNumber) { - throw indexerError( - IndexerErrorCode.IE069, - `Failed to query latest valid epoch number for ${network}`, - ) + throw new Error(`Failed to query EBO for ${network}'s latest valid epoch number`) } - const epochBlock = await buildEpochBlock( - this.indexingStatusResolver, + // Check for validity with epoch manager currentEpoch, and fetch block hash + const validBlock = result.data.network.latestValidBlockNumber.epochNumber == - (await this.currentEpoch()) + (await this.currentEpoch()) ? result.data.network.latestValidBlockNumber - : result.data.network.latestValidBlockNumber.previousBlockNumber, + : result.data.network.latestValidBlockNumber.previousBlockNumber + const startBlockHash = await this.indexingStatusResolver.blockHashFromNumber( + alias(network), + validBlock.startBlockNumber, ) - return epochBlock + return { + network, + epochNumber: +validBlock.epochNumber, + startBlockNumber: +validBlock.blockNumber, + startBlockHash, + } } catch (err) { - this.logger.error( - `Failed to query latest global epoch number from epoch block oracle`, - { + if (err instanceof indexerError) { + throw err + } else { + this.logger.error(`Failed to query latest epoch number`, { err, - }, - ) - throw err + msg: err.message, + networkName: alias(network), + }) + throw indexerError(IndexerErrorCode.IE069, err) + } } } @@ -645,32 +655,34 @@ export class NetworkMonitor { allocation.subgraphDeployment.id, ]) if (indexingStatuses.length != 1 || indexingStatuses[0].chains.length != 1) { - throw `Failed to match allocation with an indexing status or chain` + this.logger.error( + `Failed to query indexing status for ${allocation.subgraphDeployment.id.ipfsHash}`, + ) + throw indexerError( + IndexerErrorCode.IE020, + `Failed to query indexing status for ${allocation.subgraphDeployment.id.ipfsHash}`, + ) } const networkID = indexingStatuses[0].chains[0].network const epoch = await this.latestValidEpoch(CAIPIds[networkID]) - const epochStartBlock = { - number: epoch.startBlockNumber, - hash: epoch.startBlockHash, - } this.logger.trace(`Fetched block pointer to use in resolving POI`, { deployment: allocation.subgraphDeployment.id.ipfsHash, networkID, - epochStartBlock, + number: epoch.startBlockNumber, + hash: epoch.startBlockHash, }) - return epochStartBlock + return { + number: epoch.startBlockNumber, + hash: epoch.startBlockHash, + } } catch (error) { - const err = indexerError(IndexerErrorCode.IE070, error.message) - this.logger.error( - `Failed to fetch block for resolving allocation POI ${allocation.subgraphDeployment.id}`, - { - err: error.message, - allocationID: allocation.id, - deployment: allocation.subgraphDeployment.id, - }, - ) - throw err + this.logger.error(`Failed to fetch block for resolving allocation POI`, { + err: error.cause ?? error.message, + allocationID: allocation.id, + deployment: allocation.subgraphDeployment.id.ipfsHash, + }) + throw error } } @@ -679,7 +691,6 @@ export class NetworkMonitor { poi: string | undefined, force: boolean, ): Promise { - const epochStartBlock = await this.fetchPOIBlockPointer(allocation) // poi = undefined, force=true -- submit even if poi is 0x0 // poi = defined, force=true -- no generatedPOI needed, just submit the POI supplied (with some sanitation?) // poi = undefined, force=false -- submit with generated POI if one available @@ -694,13 +705,14 @@ export class NetworkMonitor { return ( (await this.indexingStatusResolver.proofOfIndexing( allocation.subgraphDeployment.id, - epochStartBlock, + await this.fetchPOIBlockPointer(allocation), allocation.indexer, )) || utils.hexlify(Array(32).fill(0)) ) } break case false: { + const epochStartBlock = await this.fetchPOIBlockPointer(allocation) // Obtain the start block of the current epoch const generatedPOI = await this.indexingStatusResolver.proofOfIndexing( allocation.subgraphDeployment.id, diff --git a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts index 2728308e2..b29b39bfc 100644 --- a/packages/indexer-common/src/indexer-management/resolvers/allocations.ts +++ b/packages/indexer-common/src/indexer-management/resolvers/allocations.ts @@ -294,8 +294,6 @@ async function resolvePOI( poi: string | undefined, force: boolean, ): Promise { - // Obtain epoch start block based on subgraph deployment network's - const currentEpochStartBlock = await networkMonitor.fetchPOIBlockPointer(allocation) // poi = undefined, force=true -- submit even if poi is 0x0 // poi = defined, force=true -- no generatedPOI needed, just submit the POI supplied (with some sanitation?) // poi = undefined, force=false -- submit with generated POI if one available @@ -310,13 +308,14 @@ async function resolvePOI( return ( (await indexingStatusResolver.proofOfIndexing( allocation.subgraphDeployment.id, - currentEpochStartBlock, + await networkMonitor.fetchPOIBlockPointer(allocation), allocation.indexer, )) || utils.hexlify(Array(32).fill(0)) ) } break case false: { + const currentEpochStartBlock = await networkMonitor.fetchPOIBlockPointer(allocation) const generatedPOI = await indexingStatusResolver.proofOfIndexing( allocation.subgraphDeployment.id, currentEpochStartBlock, diff --git a/packages/indexer-common/src/indexing-status.ts b/packages/indexer-common/src/indexing-status.ts index deca7a918..8c6fd9242 100644 --- a/packages/indexer-common/src/indexing-status.ts +++ b/packages/indexer-common/src/indexing-status.ts @@ -213,7 +213,7 @@ export class IndexingStatusResolver { .toPromise() if (!result.data || !result.data.blockHashFromNumber || result.error) { - throw indexerError(IndexerErrorCode.IE070) + throw new Error(`Failed to query graph node for blockHashFromNumber`) } this.logger.trace('Resolved block hash', {