@@ -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