6868#[ path = "class_test.rs" ]
6969mod class_test;
7070
71+ use std:: collections:: HashMap ;
72+
7173use apollo_proc_macros:: latency_histogram;
7274use starknet_api:: block:: BlockNumber ;
7375use starknet_api:: core:: ClassHash ;
7476use starknet_api:: deprecated_contract_class:: ContractClass as DeprecatedContractClass ;
75- use starknet_api:: state:: SierraContractClass ;
77+ use starknet_api:: state:: { ContractClassComponentHashes , SierraContractClass } ;
7678
7779use crate :: db:: table_types:: Table ;
7880use crate :: db:: RW ;
7981use crate :: mmap_file:: LocationInFile ;
80- use crate :: state:: { DeclaredClassesTable , DeprecatedDeclaredClassesTable , FileOffsetTable } ;
82+ use crate :: state:: {
83+ DeclaredClassesTable ,
84+ DeprecatedDeclaredClassesTable ,
85+ FileOffsetTable ,
86+ StateStorageReader ,
87+ } ;
8188use crate :: {
8289 DbTransaction ,
8390 FileHandlers ,
@@ -87,6 +94,8 @@ use crate::{
8794 StorageError ,
8895 StorageResult ,
8996 StorageTransaction ,
97+ StorageTxn ,
98+ TransactionKind ,
9099} ;
91100
92101/// Interface for reading data related to classes or deprecated classes.
@@ -205,6 +214,45 @@ impl<T: StorageTransaction> ClassStorageReader for T {
205214 }
206215}
207216
217+ /// Builds the map from each Cairo 1 class hash declared in `block_number` to its contract class
218+ /// component hashes, matching the `declared_class_hash_to_component_hashes` field of the OS block
219+ /// input. This excludes classes whose compiled class hash was merely migrated in `block_number`.
220+ pub fn get_declared_class_hash_to_component_hashes < Mode : TransactionKind > (
221+ txn : & StorageTxn < ' _ , Mode > ,
222+ block_number : BlockNumber ,
223+ ) -> StorageResult < HashMap < ClassHash , ContractClassComponentHashes > > {
224+ let state_diff = txn. get_state_diff ( block_number) ?. ok_or ( StorageError :: MissingObject {
225+ object_name : "state diff" . to_string ( ) ,
226+ height : block_number,
227+ } ) ?;
228+ let state_reader = txn. get_state_reader ( ) ?;
229+
230+ let mut declared_sierra_classes = Vec :: new ( ) ;
231+ // Read all Sierra classes declared in this block from storage.
232+ for class_hash in state_diff. class_hash_to_compiled_class_hash . keys ( ) {
233+ // `class_hash_to_compiled_class_hash` merges fresh declarations with migrated classes,
234+ // while `declared_classes_block` records each class's original declaration block.
235+ // Only classes first declared in this block contribute component hashes.
236+ if state_reader. get_class_definition_block_number ( class_hash) ? != Some ( block_number) {
237+ // A migrated class that was declared in an earlier block.
238+ continue ;
239+ }
240+ let sierra_class = txn. get_class ( class_hash) ?. ok_or ( StorageError :: DBInconsistency {
241+ msg : format ! (
242+ "Class {class_hash} is declared in block {} but its Sierra class is missing from \
243+ storage.",
244+ block_number. 0
245+ ) ,
246+ } ) ?;
247+ declared_sierra_classes. push ( ( * class_hash, sierra_class) ) ;
248+ }
249+
250+ Ok ( declared_sierra_classes
251+ . into_iter ( )
252+ . map ( |( class_hash, sierra_class) | ( class_hash, sierra_class. get_component_hashes ( ) ) )
253+ . collect ( ) )
254+ }
255+
208256impl < T : StorageTransaction < Mode = RW > > ClassStorageWriter for T {
209257 #[ latency_histogram( "storage_append_classes_latency_seconds" , false ) ]
210258 fn append_classes (
0 commit comments