Skip to content

Commit 308f4b2

Browse files
committed
graph: Validate if the graft chain contains any incompatible spec version for composed subgraphs
1 parent f898def commit 308f4b2

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

graph/src/data_source/subgraph.rs

Lines changed: 61 additions & 8 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
274+
async fn verify_graft_chain<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 manifest spec version {} is not supported, 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(
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,6 +335,18 @@ 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;
338+
if source_spec_version < &SPEC_VERSION_1_3_0 {
339+
return Err(anyhow!(
340+
"Source subgraph manifest spec version {} is not supported, minimum supported version is {}",
341+
source_spec_version,
342+
SPEC_VERSION_1_3_0
343+
));
344+
}
345+
346+
// Verify the entire graft chain meets spec version requirements
347+
let mut graft_chain = Vec::new();
348+
Self::verify_graft_chain(source_manifest.clone(), resolver, logger, &mut graft_chain)
349+
.await?;
289350

290351
if source_manifest
291352
.data_sources
@@ -295,14 +356,6 @@ impl UnresolvedDataSource {
295356
return Err(anyhow!("Nested subgraph data sources are not supported."));
296357
}
297358

298-
if source_spec_version < &SPEC_VERSION_1_3_0 {
299-
return Err(anyhow!(
300-
"Source subgraph manifest spec version {} is not supported, minimum supported version is {}",
301-
source_spec_version,
302-
SPEC_VERSION_1_3_0
303-
));
304-
}
305-
306359
let pruning_enabled = match source_manifest.indexer_hints.as_ref() {
307360
None => false,
308361
Some(hints) => hints.prune.is_some(),

0 commit comments

Comments
 (0)