1
1
use crate :: trace:: types:: { ContractName , Selector } ;
2
2
use cairo_lang_sierra:: program:: ProgramArtifact ;
3
+ use cairo_lang_sierra_to_casm:: compiler:: CairoProgramDebugInfo ;
4
+ use cairo_lang_starknet_classes:: casm_contract_class:: CasmContractClass ;
3
5
use cairo_lang_starknet_classes:: contract_class:: ContractClass ;
4
6
use cheatnet:: forking:: data:: ForkData ;
5
7
use cheatnet:: runtime_extensions:: forge_runtime_extension:: contracts_data:: ContractsData ;
@@ -8,6 +10,7 @@ use rayon::iter::ParallelIterator;
8
10
use starknet:: core:: types:: contract:: { AbiEntry , SierraClass } ;
9
11
use starknet_api:: core:: { ClassHash , EntryPointSelector } ;
10
12
use std:: collections:: HashMap ;
13
+ use std:: hash:: Hash ;
11
14
12
15
/// Data structure containing information about contracts,
13
16
/// including their ABI, names, selectors and programs that will be used to create a [`Trace`](crate::Trace).
@@ -16,6 +19,8 @@ pub struct ContractsDataStore {
16
19
contract_names : HashMap < ClassHash , ContractName > ,
17
20
selectors : HashMap < EntryPointSelector , Selector > ,
18
21
programs : HashMap < ClassHash , ProgramArtifact > ,
22
+ // FIXME(https://github.com/software-mansion/universal-sierra-compiler/issues/98): Use CASM debug info from USC once it provides it.
23
+ casm_debug_infos : HashMap < ClassHash , CairoProgramDebugInfo > ,
19
24
}
20
25
21
26
impl ContractsDataStore {
@@ -46,7 +51,7 @@ impl ContractsDataStore {
46
51
. chain ( fork_data. abi . clone ( ) )
47
52
. collect ( ) ;
48
53
49
- let programs = contracts_data
54
+ let program_data = contracts_data
50
55
. contracts
51
56
. par_iter ( )
52
57
. map ( |( _, contract_data) | {
@@ -65,15 +70,27 @@ impl ContractsDataStore {
65
70
debug_info,
66
71
} ;
67
72
68
- ( contract_data. class_hash , program_artifact)
73
+ let casm_debug_info = compile ( ContractClass {
74
+ // Debug info is unused in the compilation. This saves us a costly clone.
75
+ sierra_program_debug_info : None ,
76
+ ..contract_class
77
+ } ) ;
78
+
79
+ (
80
+ contract_data. class_hash ,
81
+ ( program_artifact, casm_debug_info) ,
82
+ )
69
83
} )
70
- . collect ( ) ;
84
+ . collect :: < Vec < _ > > ( ) ;
85
+
86
+ let ( programs, casm_debug_infos) = split_maps ( program_data) ;
71
87
72
88
Self {
73
89
abi,
74
90
contract_names,
75
91
selectors,
76
92
programs,
93
+ casm_debug_infos,
77
94
}
78
95
}
79
96
@@ -99,4 +116,36 @@ impl ContractsDataStore {
99
116
pub fn get_program_artifact ( & self , class_hash : & ClassHash ) -> Option < & ProgramArtifact > {
100
117
self . programs . get ( class_hash)
101
118
}
119
+
120
+ /// Gets the [`CairoProgramDebugInfo`] for a given contract [`ClassHash`].
121
+ #[ must_use]
122
+ pub fn get_casm_debug_info ( & self , class_hash : & ClassHash ) -> Option < & CairoProgramDebugInfo > {
123
+ self . casm_debug_infos . get ( class_hash)
124
+ }
125
+ }
126
+
127
+ /// Compile the given [`ContractClass`] to `casm` and return [`CairoProgramDebugInfo`]
128
+ fn compile ( contract_class : ContractClass ) -> CairoProgramDebugInfo {
129
+ let ( _, casm_debug_info) =
130
+ CasmContractClass :: from_contract_class_with_debug_info ( contract_class, false , usize:: MAX )
131
+ . expect ( "compilation should succeed" ) ;
132
+ casm_debug_info
133
+ }
134
+
135
+ /// Splits an iterator of `(K, (V1, V2))` into two `HashMaps`:
136
+ /// `HashMap<K, V1>` and `HashMap<K, V2>`
137
+ fn split_maps < K , V1 , V2 , I > ( iter : I ) -> ( HashMap < K , V1 > , HashMap < K , V2 > )
138
+ where
139
+ K : Copy + Eq + Hash ,
140
+ I : IntoIterator < Item = ( K , ( V1 , V2 ) ) > ,
141
+ {
142
+ let mut map1 = HashMap :: new ( ) ;
143
+ let mut map2 = HashMap :: new ( ) ;
144
+
145
+ for ( key, ( v1, v2) ) in iter {
146
+ map1. insert ( key, v1) ;
147
+ map2. insert ( key, v2) ;
148
+ }
149
+
150
+ ( map1, map2)
102
151
}
0 commit comments