diff --git a/backend/crates/common/src/graphql_api/types.rs b/backend/crates/common/src/graphql_api/types.rs index b715746..48ca2aa 100644 --- a/backend/crates/common/src/graphql_api/types.rs +++ b/backend/crates/common/src/graphql_api/types.rs @@ -18,18 +18,40 @@ pub use filters::*; mod divergence_investigation { use super::*; + /// Once Graphix launches a PoI divergence investigation, its status value + /// can be one of these. #[derive(Debug, Copy, Clone, Enum, PartialEq, Eq, Serialize, Deserialize)] pub enum DivergenceInvestigationStatus { + /// The investigation has been requested, but not yet launched and it's + /// scheduled to be launched soon. Pending, + /// The investigation has been launched, some requests have possibly + /// been sent already, but the investigation is not concluded. Some + /// information may be available already, but partial. InProgress, + /// The investigation has been concluded and the end results are + /// available. Complete, } + /// A divergence investigation report contains all information that pertains to a divergence + /// investigation, including the results of its bisection run(s). #[derive(Debug, Serialize, SimpleObject, Deserialize)] pub struct DivergenceInvestigationReport { + /// The UUID of the divergence investigation request that this report + /// pertains to. This UUID is also used to identify the report, as well + /// as the request. pub uuid: UuidString, + /// The latest known status of the divergence investigation. pub status: DivergenceInvestigationStatus, + /// A list of bisection runs that were performed as part of this + /// divergence investigation. If the investigation is still in progress, + /// this list may be incomplete. pub bisection_runs: Vec, + /// If the divergence investigation failed altogether, this field + /// contains the error message. Please note that specific bisection runs + /// may also fail, in which case the error message will be in the + /// `error` field of the corresponding `BisectionRunReport`. pub error: Option, } @@ -39,36 +61,79 @@ mod divergence_investigation { pub upper_bound: PartialBlock, } + /// When Graphix investigates a divergence between two indexers, it runs a + /// bisection algorithm and collects useful information about each block + /// from the indexer's `graph-node` instance through its public GraphQL API. + /// This metadata is then available in divergence investigation reports. #[derive(Debug, SimpleObject, Serialize, Deserialize)] pub struct GraphNodeBlockMetadata { + /// The block number and hash that this metadata pertains to. pub block: PartialBlock, + /// The contents of `graph-node`'s block cache for this block, if + /// requested and available. pub block_cache_contents: Option, + /// The contents of `graph-node`'s eth call cache for this block, if + /// requested and available. pub eth_call_cache_contents: Option, + /// A list of entitity changes produced by `graph-node` for this block + /// and subgraph deployment, + /// if requested and available. pub entity_changes: Option, } + /// A bisection run report contains information about a specific bisection + /// run that is part of a larger divergence investigation. #[derive(Debug, Clone, SimpleObject, Serialize, Deserialize)] pub struct BisectionRunReport { + /// The UUID of the bisection run that this report pertains to. This UUID + /// is different from the UUID of the parent divergence investigation + /// request. pub uuid: UuidString, + /// The first PoI that was used to start the bisection run. pub poi1: HexBytesWith0xPrefix, + /// The second PoI that was used to start the bisection run. pub poi2: HexBytesWith0xPrefix, + /// The lower and upper block bounds inside which the bisection run + /// occurred. pub divergence_block_bounds: DivergenceBlockBounds, + /// For each specific bisection, a list of bisection reports is + /// available which includes the block number and hash, as well as the + /// metadata that was collected from `graph-node` for that block. pub bisects: Vec, + /// If the bisection run failed before reaching a conclusion at a single + /// block, this field contains the error message. pub error: Option, } + /// Metadata that was collected during a bisection run. #[derive(Debug, Clone, SimpleObject, Serialize, Deserialize)] pub struct BisectionReport { + /// The block number and hash that this metadata pertains to. pub block: PartialBlock, + /// The metadata that was collected from the first indexer's + /// `graph-node` instance. pub indexer1_response: String, + /// The metadata that was collected from the second indexer's + /// `graph-node` instance. pub indexer2_response: String, } + /// The type of a new divergence investigation request that the API user + /// can submit. #[derive(InputObject, Deserialize, Debug, Clone, FromSqlRow, Serialize)] pub struct DivergenceInvestigationRequest { + /// A list of PoI hashes that should be investigated for divergence. + /// If this list contains more than two PoIs, a new bisection run will be performed + /// for each unordered pair of PoIs. pub pois: Vec, + /// Indicates whether to collect `graph-node`'s block cache contents + /// during bisection runs to include in the report. pub query_block_caches: Option, + /// Indicates whether to collect `graph-node`'s eth call cache contents + /// during bisection runs to include in the report. pub query_eth_call_caches: Option, + /// Indicates whether to collect `graph-node`'s entity changes during + /// bisection runs to include in the report. pub query_entity_changes: Option, } @@ -96,52 +161,82 @@ mod divergence_investigation { mod filters { use super::*; + /// A filter for subgraph deployments. #[derive(Default, InputObject)] pub struct SgDeploymentsQuery { + /// What network the subgraph indexes. pub network: Option, + /// The human-readable name of the queried subgraph deployment(s). pub name: Option, + /// The IPFS hash of the subgraph deployment(s). pub ipfs_cid: Option, + /// Upper limit on the number of shown results. pub limit: Option, } + /// A filter for PoIs (proofs of indexing). #[derive(Default, InputObject)] pub struct PoisQuery { + /// Restricts the query to PoIs for subgraph deployments that index the + /// given chain name. pub network: Option, + /// Restricts the query to PoIs for these given subgraph deployments (by + /// hex-encoded IPFS CID with '0x' prefix). pub deployments: Vec, + /// Restricts the query to PoIs that were collected in the given block + /// range. pub block_range: Option, + /// Upper limit on the number of shown results. pub limit: Option, } + /// A filter for indexers. #[derive(Default, InputObject)] pub struct IndexersQuery { + /// The address of the indexer, encoded as a hex string with a '0x' + /// prefix. pub address: Option, + /// Upper limit on the number of shown results. pub limit: Option, } } +/// A block range, specified by optional start and end block numbers. #[derive(InputObject)] pub struct BlockRangeInput { + /// The start block number (inclusive). pub start: Option, + /// The end block number (inclusive). pub end: Option, } +/// A network where subgraph deployments are indexed. #[derive(SimpleObject, Debug)] pub struct Network { + /// Human-readable name of the network, following The Graph naming + /// conventions. pub name: String, + /// CAIP-2 chain ID of the network, if it exists. pub caip2: Option, } +/// A block pointer for a specific network. #[derive(SimpleObject, Debug)] pub struct Block { + /// The network that this block belongs to. pub network: Network, + /// The block number (or height). pub number: u64, + /// The block hash, expressed as a hex string with a '0x' prefix. pub hash: HexBytesWith0xPrefix, } /// A block number that may or may not also have an associated hash. #[derive(Debug, Clone, Serialize, SimpleObject, Deserialize)] pub struct PartialBlock { + /// The block number (or height). pub number: i64, + /// The block hash, if known. Expressed as a hex string with a '0x' prefix. pub hash: Option, } @@ -150,18 +245,28 @@ pub struct Deployment { pub id: String, } +/// A PoI (proof of indexing) that was queried and collected by Graphix. #[derive(SimpleObject, Debug)] pub struct ProofOfIndexing { + /// The block height and hash for which this PoI is valid. pub block: Block, + /// The PoI's hash. pub hash: String, + /// The subgraph deployment that this PoI is for. pub deployment: Deployment, + /// The amount of allocated tokens by the indexer for this PoI, if known. pub allocated_tokens: Option, + /// The indexer that produced this PoI. pub indexer: Indexer, } +/// An indexer that is known to Graphix. #[derive(SimpleObject, Debug)] pub struct Indexer { + /// The indexer's ID, which is equal to its hex-encoded address with a '0x' + /// prefix. pub id: HexBytesWith0xPrefix, + /// The number of tokens allocated to the indexer, if known. pub allocated_tokens: Option, } diff --git a/backend/crates/common/src/store/models/mod.rs b/backend/crates/common/src/store/models/mod.rs index 0542706..cc78482 100644 --- a/backend/crates/common/src/store/models/mod.rs +++ b/backend/crates/common/src/store/models/mod.rs @@ -106,10 +106,14 @@ pub struct NewIndexer { pub name: Option, } +/// A subgraph deployment that is monitored by Graphix. #[derive(Debug, Queryable, Serialize, SimpleObject)] pub struct QueriedSgDeployment { + /// IPFS CID of the subgraph deployment. pub id: SgDeploymentCid, + /// Human-readable name of the subgraph deployment, if present. pub name: Option, + /// Network name of the subgraph deployment. pub network_name: String, } diff --git a/backend/crates/schema/graphql/.gitignore b/backend/crates/schema/graphql/.gitignore deleted file mode 100644 index a9fd035..0000000 --- a/backend/crates/schema/graphql/.gitignore +++ /dev/null @@ -1 +0,0 @@ -api_schema.graphql diff --git a/backend/crates/schema/graphql/api_schema.graphql b/backend/crates/schema/graphql/api_schema.graphql new file mode 100644 index 0000000..2e3d5ee --- /dev/null +++ b/backend/crates/schema/graphql/api_schema.graphql @@ -0,0 +1,404 @@ +# AUTOGENERATED. DO NOT MODIFY. ALL CHANGES WILL BE LOST. + +""" +Metadata that was collected during a bisection run. +""" +type BisectionReport { + """ + The block number and hash that this metadata pertains to. + """ + block: PartialBlock! + """ + The metadata that was collected from the first indexer's + `graph-node` instance. + """ + indexer1Response: String! + """ + The metadata that was collected from the second indexer's + `graph-node` instance. + """ + indexer2Response: String! +} + +""" +A bisection run report contains information about a specific bisection +run that is part of a larger divergence investigation. +""" +type BisectionRunReport { + """ + The UUID of the bisection run that this report pertains to. This UUID + is different from the UUID of the parent divergence investigation + request. + """ + uuid: String! + """ + The first PoI that was used to start the bisection run. + """ + poi1: String! + """ + The second PoI that was used to start the bisection run. + """ + poi2: String! + """ + The lower and upper block bounds inside which the bisection run + occurred. + """ + divergenceBlockBounds: DivergenceBlockBounds! + """ + For each specific bisection, a list of bisection reports is + available which includes the block number and hash, as well as the + metadata that was collected from `graph-node` for that block. + """ + bisects: [BisectionReport!]! + """ + If the bisection run failed before reaching a conclusion at a single + block, this field contains the error message. + """ + error: String +} + +""" +A block pointer for a specific network. +""" +type Block { + """ + The network that this block belongs to. + """ + network: Network! + """ + The block number (or height). + """ + number: Int! + """ + The block hash, expressed as a hex string with a '0x' prefix. + """ + hash: String! +} + +""" +A block range, specified by optional start and end block numbers. +""" +input BlockRangeInput { + """ + The start block number (inclusive). + """ + start: Int + """ + The end block number (inclusive). + """ + end: Int +} + + +type Deployment { + id: String! +} + +type DivergenceBlockBounds { + lowerBound: PartialBlock! + upperBound: PartialBlock! +} + +""" +A divergence investigation report contains all information that pertains to a divergence +investigation, including the results of its bisection run(s). +""" +type DivergenceInvestigationReport { + """ + The UUID of the divergence investigation request that this report + pertains to. This UUID is also used to identify the report, as well + as the request. + """ + uuid: String! + """ + The latest known status of the divergence investigation. + """ + status: DivergenceInvestigationStatus! + """ + A list of bisection runs that were performed as part of this + divergence investigation. If the investigation is still in progress, + this list may be incomplete. + """ + bisectionRuns: [BisectionRunReport!]! + """ + If the divergence investigation failed altogether, this field + contains the error message. Please note that specific bisection runs + may also fail, in which case the error message will be in the + `error` field of the corresponding `BisectionRunReport`. + """ + error: String +} + +""" +The type of a new divergence investigation request that the API user +can submit. +""" +input DivergenceInvestigationRequest { + """ + A list of PoI hashes that should be investigated for divergence. + If this list contains more than two PoIs, a new bisection run will be performed + for each unordered pair of PoIs. + """ + pois: [String!]! + """ + Indicates whether to collect `graph-node`'s block cache contents + during bisection runs to include in the report. + """ + queryBlockCaches: Boolean + """ + Indicates whether to collect `graph-node`'s eth call cache contents + during bisection runs to include in the report. + """ + queryEthCallCaches: Boolean + """ + Indicates whether to collect `graph-node`'s entity changes during + bisection runs to include in the report. + """ + queryEntityChanges: Boolean +} + +""" +Once Graphix launches a PoI divergence investigation, its status value +can be one of these. +""" +enum DivergenceInvestigationStatus { + """ + The investigation has been requested, but not yet launched and it's + scheduled to be launched soon. + """ + PENDING + """ + The investigation has been launched, some requests have possibly + been sent already, but the investigation is not concluded. Some + information may be available already, but partial. + """ + IN_PROGRESS + """ + The investigation has been concluded and the end results are + available. + """ + COMPLETE +} + + + +""" +An indexer that is known to Graphix. +""" +type Indexer { + """ + The indexer's ID, which is equal to its hex-encoded address with a '0x' + prefix. + """ + id: String! + """ + The number of tokens allocated to the indexer, if known. + """ + allocatedTokens: Int +} + +""" +A filter for indexers. +""" +input IndexersQuery { + """ + The address of the indexer, encoded as a hex string with a '0x' + prefix. + """ + address: String + """ + Upper limit on the number of shown results. + """ + limit: Int +} + + +type MutationRoot { + launchDivergenceInvestigation(req: DivergenceInvestigationRequest!): DivergenceInvestigationReport! + setDeploymentName(deploymentIpfsCid: String!, name: String!): Deployment! + deleteNetwork(network: String!): String! +} + +""" +A network where subgraph deployments are indexed. +""" +type Network { + """ + Human-readable name of the network, following The Graph naming + conventions. + """ + name: String! + """ + CAIP-2 chain ID of the network, if it exists. + """ + caip2: String +} + +""" +A block number that may or may not also have an associated hash. +""" +type PartialBlock { + """ + The block number (or height). + """ + number: Int! + """ + The block hash, if known. Expressed as a hex string with a '0x' prefix. + """ + hash: String +} + +""" +A specific indexer can use `PoiAgreementRatio` to check in how much agreement it is with other +indexers, given its own poi for each deployment. A consensus currently means a majority of +indexers agreeing on a particular POI. +""" +type PoiAgreementRatio { + poi: String! + deployment: Deployment! + block: PartialBlock! + """ + Total number of indexers that have live pois for the deployment. + """ + totalIndexers: Int! + """ + Number of indexers that agree on the POI with the specified indexer, + including the indexer itself. + """ + nAgreeingIndexers: Int! + """ + Number of indexers that disagree on the POI with the specified indexer. + """ + nDisagreeingIndexers: Int! + """ + Indicates if a consensus on the POI exists among indexers. + """ + hasConsensus: Boolean! + """ + Indicates if the specified indexer's POI is part of the consensus. + """ + inConsensus: Boolean! +} + +""" +A filter for PoIs (proofs of indexing). +""" +input PoisQuery { + """ + Restricts the query to PoIs for subgraph deployments that index the + given chain name. + """ + network: String + """ + Restricts the query to PoIs for these given subgraph deployments (by + hex-encoded IPFS CID with '0x' prefix). + """ + deployments: [String!]! + """ + Restricts the query to PoIs that were collected in the given block + range. + """ + blockRange: BlockRangeInput + """ + Upper limit on the number of shown results. + """ + limit: Int +} + +""" +A PoI (proof of indexing) that was queried and collected by Graphix. +""" +type ProofOfIndexing { + """ + The block height and hash for which this PoI is valid. + """ + block: Block! + """ + The PoI's hash. + """ + hash: String! + """ + The subgraph deployment that this PoI is for. + """ + deployment: Deployment! + """ + The amount of allocated tokens by the indexer for this PoI, if known. + """ + allocatedTokens: Int + """ + The indexer that produced this PoI. + """ + indexer: Indexer! +} + +""" +A subgraph deployment that is monitored by Graphix. +""" +type QueriedSgDeployment { + """ + IPFS CID of the subgraph deployment. + """ + id: String! + """ + Human-readable name of the subgraph deployment, if present. + """ + name: String + """ + Network name of the subgraph deployment. + """ + networkName: String! +} + +type QueryRoot { + """ + Fetches all tracked subgraph deploymens in this Graphix instance and + filters them according to some filtering rules. + """ + deployments(filter: SgDeploymentsQuery!): [QueriedSgDeployment!]! + """ + Fetches all tracked indexers in this Graphix instance and filters them + according to some filtering rules. + """ + indexers(filter: IndexersQuery!): [Indexer!]! + """ + Filters through all PoIs ever collected by this Graphix + instance, according to some filtering rules specified in `filter`. + """ + proofsOfIndexing(filter: PoisQuery!): [ProofOfIndexing!]! + """ + Same as [`QueryRoot::proofs_of_indexing`], but only returns PoIs that + are "live" i.e. they are the most recent PoI collected for their + subgraph deployment. + """ + liveProofsOfIndexing(filter: PoisQuery!): [ProofOfIndexing!]! + poiAgreementRatios(indexerName: String!): [PoiAgreementRatio!]! + divergenceInvestigationReport(uuid: String!): DivergenceInvestigationReport +} + +""" +A filter for subgraph deployments. +""" +input SgDeploymentsQuery { + """ + What network the subgraph indexes. + """ + network: String + """ + The human-readable name of the queried subgraph deployment(s). + """ + name: String + """ + The IPFS hash of the subgraph deployment(s). + """ + ipfsCid: String + """ + Upper limit on the number of shown results. + """ + limit: Int +} + + +schema { + query: QueryRoot + mutation: MutationRoot +}