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