Skip to content

Commit 127d15c

Browse files
authored
Validate if the source subgraph graft chain contains any incompatible spec version (#5911)
* graph: Validate if the graft chain contains any incompatible spec version for composed subgraphs * graph: allow subgraphs with prune set to never to be sourcable * graph: remove the pruning check completely for source subgraphs * Address review comments
1 parent 5ff1974 commit 127d15c

1 file changed

Lines changed: 64 additions & 17 deletions

File tree

graph/src/data_source/subgraph.rs

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,55 @@ impl UnresolvedDataSource {
270270
.map(Arc::new)
271271
}
272272

273+
/// Recursively verifies that all grafts in the chain meet the minimum spec version requirement for a subgraph source
274+
async fn verify_graft_chain_sourcable<C: Blockchain>(
275+
manifest: Arc<SubgraphManifest<C>>,
276+
resolver: &Arc<dyn LinkResolver>,
277+
logger: &Logger,
278+
graft_chain: &mut Vec<String>,
279+
) -> Result<(), Error> {
280+
// Add current manifest to graft chain
281+
graft_chain.push(manifest.id.to_string());
282+
283+
// Check if current manifest meets spec version requirement
284+
if manifest.spec_version < SPEC_VERSION_1_3_0 {
285+
return Err(anyhow!(
286+
"Subgraph with a spec version {} is not supported for a subgraph source, minimum supported version is {}. Graft chain: {}",
287+
manifest.spec_version,
288+
SPEC_VERSION_1_3_0,
289+
graft_chain.join(" -> ")
290+
));
291+
}
292+
293+
// If there's a graft, recursively verify it
294+
if let Some(graft) = &manifest.graft {
295+
let graft_raw = resolver
296+
.cat(logger, &graft.base.to_ipfs_link())
297+
.await
298+
.context("Failed to resolve graft base manifest")?;
299+
300+
let graft_raw: serde_yaml::Mapping = serde_yaml::from_slice(&graft_raw)
301+
.context("Failed to parse graft base manifest as YAML")?;
302+
303+
let graft_manifest =
304+
UnresolvedSubgraphManifest::<C>::parse(graft.base.clone(), graft_raw)
305+
.context("Failed to parse graft base manifest")?
306+
.resolve(resolver, logger, LATEST_VERSION.clone())
307+
.await
308+
.context("Failed to resolve graft base manifest")?;
309+
310+
Box::pin(Self::verify_graft_chain_sourcable(
311+
Arc::new(graft_manifest),
312+
resolver,
313+
logger,
314+
graft_chain,
315+
))
316+
.await?;
317+
}
318+
319+
Ok(())
320+
}
321+
273322
#[allow(dead_code)]
274323
pub(super) async fn resolve<C: Blockchain>(
275324
self,
@@ -286,15 +335,6 @@ impl UnresolvedDataSource {
286335
let kind = self.kind.clone();
287336
let source_manifest = self.resolve_source_manifest::<C>(resolver, logger).await?;
288337
let source_spec_version = &source_manifest.spec_version;
289-
290-
if source_manifest
291-
.data_sources
292-
.iter()
293-
.any(|ds| matches!(ds, crate::data_source::DataSource::Subgraph(_)))
294-
{
295-
return Err(anyhow!("Nested subgraph data sources are not supported."));
296-
}
297-
298338
if source_spec_version < &SPEC_VERSION_1_3_0 {
299339
return Err(anyhow!(
300340
"Source subgraph manifest spec version {} is not supported, minimum supported version is {}",
@@ -303,15 +343,22 @@ impl UnresolvedDataSource {
303343
));
304344
}
305345

306-
let pruning_enabled = match source_manifest.indexer_hints.as_ref() {
307-
None => false,
308-
Some(hints) => hints.prune.is_some(),
309-
};
346+
// Verify the entire graft chain meets spec version requirements
347+
let mut graft_chain = Vec::new();
348+
Self::verify_graft_chain_sourcable(
349+
source_manifest.clone(),
350+
resolver,
351+
logger,
352+
&mut graft_chain,
353+
)
354+
.await?;
310355

311-
if pruning_enabled {
312-
return Err(anyhow!(
313-
"Pruning is enabled for source subgraph, which is not supported"
314-
));
356+
if source_manifest
357+
.data_sources
358+
.iter()
359+
.any(|ds| matches!(ds, crate::data_source::DataSource::Subgraph(_)))
360+
{
361+
return Err(anyhow!("Nested subgraph data sources are not supported."));
315362
}
316363

317364
let mapping_entities: Vec<String> = self

0 commit comments

Comments
 (0)