@@ -42,6 +42,8 @@ use crate::test_utils::cairo_runner::{
4242 ValueArg ,
4343} ;
4444
45+ const COMPRESSION_MODULE_PATH : & str = "starkware.starknet.core.os.data_availability.compression" ;
46+
4547/// Runs the OS compression function and returns the compressed data, plus the execution resources
4648/// used to compress the data.
4749fn cairo_compress ( data : & [ Felt ] ) -> ( Vec < Felt > , ExecutionResources ) {
@@ -54,7 +56,7 @@ fn cairo_compress(data: &[Felt]) -> (Vec<Felt>, ExecutionResources) {
5456 let ( mut runner, program, entrypoint) = initialize_cairo_runner (
5557 & runner_config,
5658 OS_PROGRAM_BYTES ,
57- "starkware.starknet.core.os.data_availability.compression. compress",
59+ & format ! ( "{COMPRESSION_MODULE_PATH}. compress") ,
5860 std:: slice:: from_ref ( & range_check_arg) ,
5961 HashMap :: new ( ) ,
6062 )
@@ -115,6 +117,74 @@ fn cairo_compress(data: &[Felt]) -> (Vec<Felt>, ExecutionResources) {
115117 ( compressed_data. into_iter ( ) . map ( |f| * f) . collect ( ) , runner. get_execution_resources ( ) . unwrap ( ) )
116118}
117119
120+ /// Runs the OS decompression function and returns the decompressed data.
121+ fn cairo_decompress ( compressed : & [ Felt ] ) -> Vec < Felt > {
122+ let range_check_arg = ImplicitArg :: Builtin ( BuiltinName :: range_check) ;
123+ let runner_config = EntryPointRunnerConfig {
124+ layout : LayoutName :: starknet,
125+ add_main_prefix_to_entrypoint : false ,
126+ ..Default :: default ( )
127+ } ;
128+ let ( mut runner, program, entrypoint) = initialize_cairo_runner (
129+ & runner_config,
130+ OS_PROGRAM_BYTES ,
131+ & format ! ( "{COMPRESSION_MODULE_PATH}.decompress" ) ,
132+ std:: slice:: from_ref ( & range_check_arg) ,
133+ HashMap :: new ( ) ,
134+ )
135+ . unwrap ( ) ;
136+
137+ // Function accepts destination pointer explicitly, and the compressed data pointer is passed
138+ // as an implicit argument (along with the range check pointer). A pointer to the end of the
139+ // decompressed data is returned as an explicit argument.
140+ let compressed_ptr = runner
141+ . vm
142+ . gen_arg ( & compressed. iter ( ) . map ( |x| MaybeRelocatable :: Int ( * x) ) . collect :: < Vec < _ > > ( ) )
143+ . unwrap ( )
144+ . get_relocatable ( )
145+ . unwrap ( ) ;
146+ let decompressed_dst = runner. vm . add_memory_segment ( ) ;
147+ let explicit_args = vec ! [ EndpointArg :: Value ( ValueArg :: Single ( decompressed_dst. into( ) ) ) ] ;
148+ let implicit_args = vec ! [
149+ range_check_arg,
150+ ImplicitArg :: NonBuiltin ( EndpointArg :: Value ( ValueArg :: Single ( compressed_ptr. into( ) ) ) ) ,
151+ ] ;
152+ // Dummy value, just to indicate to the runner that a return value is expected.
153+ let expected_explicit_return_values = vec ! [ EndpointArg :: from( Felt :: ZERO ) ] ;
154+
155+ // Run the entrypoint.
156+ // The compressed data is stored in the segment starting at `compressed_dst`, the returned
157+ // implicit value is the end of the compressed data.
158+ let state_reader = None ;
159+ let ( _implicit_return_values, explicit_return_values, _hint_processor) =
160+ run_cairo_0_entrypoint (
161+ entrypoint,
162+ & explicit_args,
163+ & implicit_args,
164+ state_reader,
165+ & mut runner,
166+ & program,
167+ & runner_config,
168+ & expected_explicit_return_values,
169+ )
170+ . unwrap ( ) ;
171+
172+ // The explicit return value should be the decompressed end pointer.
173+ assert_eq ! ( explicit_return_values. len( ) , 1 ) ;
174+ let EndpointArg :: Value ( ValueArg :: Single ( MaybeRelocatable :: RelocatableValue ( decompressed_end) ) ) =
175+ explicit_return_values[ 0 ]
176+ else {
177+ panic ! ( "Expected a single felt return value, got {:?}" , explicit_return_values[ 0 ] ) ;
178+ } ;
179+
180+ // Read the compressed data from the segment and return.
181+ let decompressed_data = runner
182+ . vm
183+ . get_integer_range ( decompressed_dst, ( decompressed_end - decompressed_dst) . unwrap ( ) )
184+ . unwrap ( ) ;
185+ decompressed_data. into_iter ( ) . map ( |f| * f) . collect ( )
186+ }
187+
118188#[ rstest]
119189#[ case:: zero( [ false ; 10 ] , Felt :: ZERO ) ]
120190#[ case:: thousand(
@@ -391,6 +461,6 @@ fn test_cairo_compress(#[case] data: Vec<Felt>, #[case] expected_n_steps_per_elm
391461 . assert_debug_eq ( & ( execution_resources. n_steps / data. len ( ) ) ) ;
392462 }
393463
464+ assert_eq ! ( data, cairo_decompress( & compressed) ) ;
394465 assert_eq ! ( data, decompress( & mut compressed. into_iter( ) ) ) ;
395- // TODO(Dori): Check cairo decompression.
396466}
0 commit comments