From 308f4b2d07ec7913cb06c82dad11573208037e2d Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Tue, 25 Mar 2025 18:53:37 +0400 Subject: [PATCH 1/4] graph: Validate if the graft chain contains any incompatible spec version for composed subgraphs --- graph/src/data_source/subgraph.rs | 69 +++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/graph/src/data_source/subgraph.rs b/graph/src/data_source/subgraph.rs index 9e120a4c82c..b005ac9523a 100644 --- a/graph/src/data_source/subgraph.rs +++ b/graph/src/data_source/subgraph.rs @@ -270,6 +270,55 @@ impl UnresolvedDataSource { .map(Arc::new) } + /// Recursively verifies that all grafts in the chain meet the minimum spec version requirement + async fn verify_graft_chain( + manifest: Arc>, + resolver: &Arc, + logger: &Logger, + graft_chain: &mut Vec, + ) -> Result<(), Error> { + // Add current manifest to graft chain + graft_chain.push(manifest.id.to_string()); + + // Check if current manifest meets spec version requirement + if manifest.spec_version < SPEC_VERSION_1_3_0 { + return Err(anyhow!( + "Subgraph manifest spec version {} is not supported, minimum supported version is {}. Graft chain: {}", + manifest.spec_version, + SPEC_VERSION_1_3_0, + graft_chain.join(" -> ") + )); + } + + // If there's a graft, recursively verify it + if let Some(graft) = &manifest.graft { + let graft_raw = resolver + .cat(logger, &graft.base.to_ipfs_link()) + .await + .context("Failed to resolve graft base manifest")?; + + let graft_raw: serde_yaml::Mapping = serde_yaml::from_slice(&graft_raw) + .context("Failed to parse graft base manifest as YAML")?; + + let graft_manifest = + UnresolvedSubgraphManifest::::parse(graft.base.clone(), graft_raw) + .context("Failed to parse graft base manifest")? + .resolve(resolver, logger, LATEST_VERSION.clone()) + .await + .context("Failed to resolve graft base manifest")?; + + Box::pin(Self::verify_graft_chain( + Arc::new(graft_manifest), + resolver, + logger, + graft_chain, + )) + .await?; + } + + Ok(()) + } + #[allow(dead_code)] pub(super) async fn resolve( self, @@ -286,6 +335,18 @@ impl UnresolvedDataSource { let kind = self.kind.clone(); let source_manifest = self.resolve_source_manifest::(resolver, logger).await?; let source_spec_version = &source_manifest.spec_version; + if source_spec_version < &SPEC_VERSION_1_3_0 { + return Err(anyhow!( + "Source subgraph manifest spec version {} is not supported, minimum supported version is {}", + source_spec_version, + SPEC_VERSION_1_3_0 + )); + } + + // Verify the entire graft chain meets spec version requirements + let mut graft_chain = Vec::new(); + Self::verify_graft_chain(source_manifest.clone(), resolver, logger, &mut graft_chain) + .await?; if source_manifest .data_sources @@ -295,14 +356,6 @@ impl UnresolvedDataSource { return Err(anyhow!("Nested subgraph data sources are not supported.")); } - if source_spec_version < &SPEC_VERSION_1_3_0 { - return Err(anyhow!( - "Source subgraph manifest spec version {} is not supported, minimum supported version is {}", - source_spec_version, - SPEC_VERSION_1_3_0 - )); - } - let pruning_enabled = match source_manifest.indexer_hints.as_ref() { None => false, Some(hints) => hints.prune.is_some(), From 3be77cc41abfb6c12834d4806d61b0346256db4d Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 26 Mar 2025 15:47:56 +0400 Subject: [PATCH 2/4] graph: allow subgraphs with prune set to never to be sourcable --- graph/src/data_source/subgraph.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graph/src/data_source/subgraph.rs b/graph/src/data_source/subgraph.rs index b005ac9523a..dac28d7a881 100644 --- a/graph/src/data_source/subgraph.rs +++ b/graph/src/data_source/subgraph.rs @@ -358,7 +358,10 @@ impl UnresolvedDataSource { let pruning_enabled = match source_manifest.indexer_hints.as_ref() { None => false, - Some(hints) => hints.prune.is_some(), + Some(hints) => match hints.prune.as_ref() { + None => false, + Some(prune) => !matches!(prune, crate::data::subgraph::Prune::Never), + }, }; if pruning_enabled { From 95f2a988c5238df8fbef8b611596687fad008189 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Wed, 26 Mar 2025 18:44:59 +0400 Subject: [PATCH 3/4] graph: remove the pruning check completely for source subgraphs --- graph/src/data_source/subgraph.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/graph/src/data_source/subgraph.rs b/graph/src/data_source/subgraph.rs index dac28d7a881..33c20c3c52d 100644 --- a/graph/src/data_source/subgraph.rs +++ b/graph/src/data_source/subgraph.rs @@ -356,20 +356,6 @@ impl UnresolvedDataSource { return Err(anyhow!("Nested subgraph data sources are not supported.")); } - let pruning_enabled = match source_manifest.indexer_hints.as_ref() { - None => false, - Some(hints) => match hints.prune.as_ref() { - None => false, - Some(prune) => !matches!(prune, crate::data::subgraph::Prune::Never), - }, - }; - - if pruning_enabled { - return Err(anyhow!( - "Pruning is enabled for source subgraph, which is not supported" - )); - } - let mapping_entities: Vec = self .mapping .handlers From 0f9d42b9fdae84484e6d242c15db82d93a98d818 Mon Sep 17 00:00:00 2001 From: incrypto32 Date: Mon, 31 Mar 2025 12:20:01 +0400 Subject: [PATCH 4/4] Address review comments --- graph/src/data_source/subgraph.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/graph/src/data_source/subgraph.rs b/graph/src/data_source/subgraph.rs index 33c20c3c52d..2dd3a35c571 100644 --- a/graph/src/data_source/subgraph.rs +++ b/graph/src/data_source/subgraph.rs @@ -270,8 +270,8 @@ impl UnresolvedDataSource { .map(Arc::new) } - /// Recursively verifies that all grafts in the chain meet the minimum spec version requirement - async fn verify_graft_chain( + /// Recursively verifies that all grafts in the chain meet the minimum spec version requirement for a subgraph source + async fn verify_graft_chain_sourcable( manifest: Arc>, resolver: &Arc, logger: &Logger, @@ -283,7 +283,7 @@ impl UnresolvedDataSource { // Check if current manifest meets spec version requirement if manifest.spec_version < SPEC_VERSION_1_3_0 { return Err(anyhow!( - "Subgraph manifest spec version {} is not supported, minimum supported version is {}. Graft chain: {}", + "Subgraph with a spec version {} is not supported for a subgraph source, minimum supported version is {}. Graft chain: {}", manifest.spec_version, SPEC_VERSION_1_3_0, graft_chain.join(" -> ") @@ -307,7 +307,7 @@ impl UnresolvedDataSource { .await .context("Failed to resolve graft base manifest")?; - Box::pin(Self::verify_graft_chain( + Box::pin(Self::verify_graft_chain_sourcable( Arc::new(graft_manifest), resolver, logger, @@ -345,8 +345,13 @@ impl UnresolvedDataSource { // Verify the entire graft chain meets spec version requirements let mut graft_chain = Vec::new(); - Self::verify_graft_chain(source_manifest.clone(), resolver, logger, &mut graft_chain) - .await?; + Self::verify_graft_chain_sourcable( + source_manifest.clone(), + resolver, + logger, + &mut graft_chain, + ) + .await?; if source_manifest .data_sources