cairo_vm/vm/runners/builtin_runner/
keccak.rs

1use crate::air_private_input::{PrivateInput, PrivateInputKeccakState};
2use crate::math_utils::safe_div_usize;
3use crate::stdlib::{cell::RefCell, collections::HashMap, prelude::*};
4use crate::types::builtin_name::BuiltinName;
5use crate::types::instance_definitions::keccak_instance_def::{
6    CELLS_PER_KECCAK, INPUT_CELLS_PER_KECCAK,
7};
8use crate::types::relocatable::{MaybeRelocatable, Relocatable};
9use crate::vm::errors::memory_errors::MemoryError;
10use crate::vm::errors::runner_errors::RunnerError;
11use crate::vm::vm_memory::memory::Memory;
12use crate::vm::vm_memory::memory_segments::MemorySegmentManager;
13use crate::Felt252;
14use lazy_static::lazy_static;
15use num_bigint::BigUint;
16use num_integer::div_ceil;
17
18const KECCAK_FELT_BYTE_SIZE: usize = 25; // 200 / 8
19const BITS: u32 = 200;
20lazy_static! {
21    static ref KECCAK_INPUT_MAX: Felt252 = Felt252::TWO.pow(BITS);
22}
23
24#[derive(Debug, Clone)]
25pub struct KeccakBuiltinRunner {
26    ratio: Option<u32>,
27    pub base: usize,
28    pub(crate) stop_ptr: Option<usize>,
29    pub(crate) included: bool,
30    cache: RefCell<HashMap<Relocatable, Felt252>>,
31}
32
33impl KeccakBuiltinRunner {
34    pub(crate) fn new(ratio: Option<u32>, included: bool) -> Self {
35        KeccakBuiltinRunner {
36            base: 0,
37            ratio,
38            stop_ptr: None,
39            included,
40            cache: RefCell::new(HashMap::new()),
41        }
42    }
43
44    pub fn initialize_segments(&mut self, segments: &mut MemorySegmentManager) {
45        self.base = segments.add().segment_index as usize // segments.add() always returns a positive index
46    }
47
48    pub fn initial_stack(&self) -> Vec<MaybeRelocatable> {
49        if self.included {
50            vec![MaybeRelocatable::from((self.base as isize, 0))]
51        } else {
52            vec![]
53        }
54    }
55
56    pub fn base(&self) -> usize {
57        self.base
58    }
59
60    pub fn ratio(&self) -> Option<u32> {
61        self.ratio
62    }
63
64    pub fn deduce_memory_cell(
65        &self,
66        address: Relocatable,
67        memory: &Memory,
68    ) -> Result<Option<MaybeRelocatable>, RunnerError> {
69        let index = address.offset % CELLS_PER_KECCAK as usize;
70        if index < INPUT_CELLS_PER_KECCAK as usize {
71            return Ok(None);
72        }
73        if let Some(felt) = self.cache.borrow().get(&address) {
74            return Ok(Some(felt.into()));
75        }
76        let first_input_addr = (address - index)?;
77        let first_output_addr = (first_input_addr + INPUT_CELLS_PER_KECCAK as usize)?;
78
79        let mut input_felts = vec![];
80
81        for i in 0..INPUT_CELLS_PER_KECCAK as usize {
82            let m_index = (first_input_addr + i)?;
83            let val = match memory.get(&m_index) {
84                Some(value) => {
85                    let num = value
86                        .get_int_ref()
87                        .ok_or(RunnerError::BuiltinExpectedInteger(Box::new((
88                            BuiltinName::keccak,
89                            (first_input_addr + i)?,
90                        ))))?;
91                    if num >= &KECCAK_INPUT_MAX {
92                        return Err(RunnerError::IntegerBiggerThanPowerOfTwo(Box::new((
93                            (first_input_addr + i)?,
94                            BITS,
95                            *num,
96                        ))));
97                    }
98                    *num
99                }
100                _ => return Ok(None),
101            };
102            input_felts.push(val)
103        }
104        let input_message: Vec<u8> = input_felts
105            .iter()
106            .flat_map(|x| {
107                let mut bytes = x.to_bytes_le().to_vec();
108                bytes.resize(KECCAK_FELT_BYTE_SIZE, 0);
109                bytes
110            })
111            .collect();
112        let keccak_result = Self::keccak_f(&input_message)?;
113
114        let mut start_index = 0_usize;
115        for i in 0..INPUT_CELLS_PER_KECCAK {
116            let end_index = start_index + BITS as usize / 8;
117            self.cache.borrow_mut().insert((first_output_addr + i)?, {
118                let mut bytes = keccak_result[start_index..end_index].to_vec();
119                bytes.resize(32, 0);
120                Felt252::from_bytes_le_slice(&bytes)
121            });
122            start_index = end_index;
123        }
124        Ok(self.cache.borrow().get(&address).map(|x| x.into()))
125    }
126
127    pub fn get_used_cells(&self, segments: &MemorySegmentManager) -> Result<usize, MemoryError> {
128        segments
129            .get_segment_used_size(self.base())
130            .ok_or(MemoryError::MissingSegmentUsedSizes)
131    }
132
133    pub fn get_used_instances(
134        &self,
135        segments: &MemorySegmentManager,
136    ) -> Result<usize, MemoryError> {
137        let used_cells = self.get_used_cells(segments)?;
138        Ok(div_ceil(used_cells, CELLS_PER_KECCAK as usize))
139    }
140
141    pub fn get_used_diluted_check_units(&self, diluted_n_bits: u32) -> usize {
142        // The diluted cells are:
143        // state - 25 rounds times 1600 elements.
144        // parity - 24 rounds times 1600/5 elements times 3 auxiliaries.
145        // after_theta_rho_pi - 24 rounds times 1600 elements.
146        // theta_aux - 24 rounds times 1600 elements.
147        // chi_iota_aux - 24 rounds times 1600 elements times 2 auxiliaries.
148        // In total 25 * 1600 + 24 * 320 * 3 + 24 * 1600 + 24 * 1600 + 24 * 1600 * 2 = 216640.
149        // But we actually allocate 4 virtual columns, of dimensions 64 * 1024, in which we embed the
150        // real cells, and we don't free the unused ones.
151        // So the real number is 4 * 64 * 1024 = 262144.
152        safe_div_usize(262144_usize, diluted_n_bits as usize).unwrap_or(0)
153    }
154
155    fn keccak_f(input_message: &[u8]) -> Result<Vec<u8>, RunnerError> {
156        let bigint = BigUint::from_bytes_le(input_message);
157        let mut keccak_input = bigint.to_u64_digits();
158        keccak_input.resize(25, 0);
159        // This unwrap wont fail as keccak_input's size is always 25
160        let mut keccak_input: [u64; 25] = keccak_input.try_into().unwrap();
161        keccak::f1600(&mut keccak_input);
162        Ok(keccak_input.iter().flat_map(|x| x.to_le_bytes()).collect())
163    }
164
165    pub fn air_private_input(&self, memory: &Memory) -> Vec<PrivateInput> {
166        let mut private_inputs = vec![];
167        if let Some(segment) = memory.data.get(self.base) {
168            let segment_len = segment.len();
169            for (index, off) in (0..segment_len)
170                .step_by(CELLS_PER_KECCAK as usize)
171                .enumerate()
172            {
173                // Add the input cells of each keccak instance to the private inputs
174                if let (
175                    Ok(input_s0),
176                    Ok(input_s1),
177                    Ok(input_s2),
178                    Ok(input_s3),
179                    Ok(input_s4),
180                    Ok(input_s5),
181                    Ok(input_s6),
182                    Ok(input_s7),
183                ) = (
184                    memory.get_integer((self.base as isize, off).into()),
185                    memory.get_integer((self.base as isize, off + 1).into()),
186                    memory.get_integer((self.base as isize, off + 2).into()),
187                    memory.get_integer((self.base as isize, off + 3).into()),
188                    memory.get_integer((self.base as isize, off + 4).into()),
189                    memory.get_integer((self.base as isize, off + 5).into()),
190                    memory.get_integer((self.base as isize, off + 6).into()),
191                    memory.get_integer((self.base as isize, off + 7).into()),
192                ) {
193                    private_inputs.push(PrivateInput::KeccakState(PrivateInputKeccakState {
194                        index,
195                        input_s0: *input_s0,
196                        input_s1: *input_s1,
197                        input_s2: *input_s2,
198                        input_s3: *input_s3,
199                        input_s4: *input_s4,
200                        input_s5: *input_s5,
201                        input_s6: *input_s6,
202                        input_s7: *input_s7,
203                    }))
204                }
205            }
206        }
207        private_inputs
208    }
209}
210
211#[cfg(test)]
212mod tests {
213    use super::*;
214    use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor;
215    use crate::types::program::Program;
216    use crate::utils::test_utils::*;
217    use crate::{felt_hex, relocatable};
218
219    use crate::vm::{
220        errors::{memory_errors::MemoryError, runner_errors::RunnerError},
221        runners::builtin_runner::BuiltinRunner,
222    };
223
224    #[cfg(target_arch = "wasm32")]
225    use wasm_bindgen_test::*;
226
227    #[test]
228    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
229    fn get_used_instances() {
230        let builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(10), true).into();
231
232        let mut vm = vm!();
233        vm.segments.segment_used_sizes = Some(vec![1]);
234
235        assert_eq!(builtin.get_used_instances(&vm.segments), Ok(1));
236    }
237
238    #[test]
239    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
240    fn final_stack() {
241        let mut builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(10), true).into();
242
243        let mut vm = vm!();
244
245        vm.segments = segments![
246            ((0, 0), (0, 0)),
247            ((0, 1), (0, 1)),
248            ((2, 0), (0, 0)),
249            ((2, 1), (0, 0))
250        ];
251
252        vm.segments.segment_used_sizes = Some(vec![0]);
253
254        let pointer = Relocatable::from((2, 2));
255
256        assert_eq!(
257            builtin.final_stack(&vm.segments, pointer).unwrap(),
258            Relocatable::from((2, 1))
259        );
260    }
261
262    #[test]
263    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
264    fn final_stack_error_stop_pointer() {
265        let mut builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(10), true).into();
266
267        let mut vm = vm!();
268
269        vm.segments = segments![
270            ((0, 0), (0, 0)),
271            ((0, 1), (0, 1)),
272            ((2, 0), (0, 0)),
273            ((2, 1), (0, 0))
274        ];
275
276        vm.segments.segment_used_sizes = Some(vec![992]);
277
278        let pointer = Relocatable::from((2, 2));
279        assert_eq!(
280            builtin.final_stack(&vm.segments, pointer),
281            Err(RunnerError::InvalidStopPointer(Box::new((
282                BuiltinName::keccak,
283                relocatable!(0, 992),
284                relocatable!(0, 0)
285            ))))
286        );
287    }
288
289    #[test]
290    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
291    fn final_stack_error_when_not_included() {
292        let mut builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(10), false).into();
293
294        let mut vm = vm!();
295
296        vm.segments = segments![
297            ((0, 0), (0, 0)),
298            ((0, 1), (0, 1)),
299            ((2, 0), (0, 0)),
300            ((2, 1), (0, 0))
301        ];
302
303        vm.segments.segment_used_sizes = Some(vec![0]);
304
305        let pointer = Relocatable::from((2, 2));
306
307        assert_eq!(
308            builtin.final_stack(&vm.segments, pointer).unwrap(),
309            Relocatable::from((2, 2))
310        );
311    }
312
313    #[test]
314    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
315    fn final_stack_error_non_relocatable() {
316        let mut builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(10), true).into();
317
318        let mut vm = vm!();
319
320        vm.segments = segments![
321            ((0, 0), (0, 0)),
322            ((0, 1), (0, 1)),
323            ((2, 0), (0, 0)),
324            ((2, 1), 2)
325        ];
326
327        vm.segments.segment_used_sizes = Some(vec![0]);
328
329        let pointer = Relocatable::from((2, 2));
330
331        assert_eq!(
332            builtin.final_stack(&vm.segments, pointer),
333            Err(RunnerError::NoStopPointer(Box::new(BuiltinName::keccak)))
334        );
335    }
336
337    #[test]
338    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
339    fn get_used_cells_and_allocated_size_test() {
340        let builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(10), true).into();
341
342        let program = Program::from_bytes(
343            include_bytes!("../../../../../cairo_programs/keccak.json"),
344            Some("main"),
345        )
346        .unwrap();
347
348        let mut cairo_runner = cairo_runner!(program);
349        cairo_runner.vm.segments.segment_used_sizes = Some(vec![0]);
350
351        let mut hint_processor = BuiltinHintProcessor::new_empty();
352
353        let address = cairo_runner.initialize(false).unwrap();
354
355        cairo_runner
356            .run_until_pc(address, &mut hint_processor)
357            .unwrap();
358
359        assert_eq!(
360            builtin.get_used_cells_and_allocated_size(&cairo_runner.vm),
361            Ok((0, 1072))
362        );
363    }
364
365    #[test]
366    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
367    fn get_allocated_memory_units() {
368        let builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(10), true).into();
369
370        let mut vm = vm!();
371        vm.current_step = 160;
372
373        assert_eq!(builtin.get_allocated_memory_units(&vm), Ok(256));
374    }
375
376    #[test]
377    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
378    fn get_used_cells_missing_segment_used_sizes() {
379        let builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(2048), true).into();
380        let vm = vm!();
381
382        assert_eq!(
383            builtin.get_used_cells(&vm.segments),
384            Err(MemoryError::MissingSegmentUsedSizes)
385        );
386    }
387
388    #[test]
389    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
390    fn get_used_cells_empty() {
391        let builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(2048), true).into();
392        let mut vm = vm!();
393
394        vm.segments.segment_used_sizes = Some(vec![0]);
395        assert_eq!(builtin.get_used_cells(&vm.segments), Ok(0));
396    }
397
398    #[test]
399    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
400    fn get_used_cells() {
401        let builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(2048), true).into();
402        let mut vm = vm!();
403
404        vm.segments.segment_used_sizes = Some(vec![4]);
405        assert_eq!(builtin.get_used_cells(&vm.segments), Ok(4));
406    }
407
408    #[test]
409    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
410    fn initial_stackincluded_test() {
411        let keccak_builtin = KeccakBuiltinRunner::new(Some(2048), true);
412        assert_eq!(
413            keccak_builtin.initial_stack(),
414            vec![mayberelocatable!(0, 0)]
415        )
416    }
417
418    #[test]
419    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
420    fn initial_stack_notincluded_test() {
421        let keccak_builtin = KeccakBuiltinRunner::new(Some(2048), false);
422        assert_eq!(keccak_builtin.initial_stack(), Vec::new())
423    }
424
425    #[test]
426    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
427    fn deduce_memory_cell_memory_valid() {
428        let memory = memory![
429            ((0, 16), 43),
430            ((0, 17), 199),
431            ((0, 18), 0),
432            ((0, 19), 0),
433            ((0, 20), 0),
434            ((0, 21), 0),
435            ((0, 22), 0),
436            ((0, 23), 1),
437            ((0, 24), 0),
438            ((0, 25), 0),
439            ((0, 26), 43),
440            ((0, 27), 199),
441            ((0, 28), 0),
442            ((0, 29), 0),
443            ((0, 30), 0),
444            ((0, 31), 0),
445            ((0, 32), 0),
446            ((0, 33), 1),
447            ((0, 34), 0),
448            ((0, 35), 0)
449        ];
450        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
451
452        let result = builtin.deduce_memory_cell(Relocatable::from((0, 25)), &memory);
453        assert_eq!(
454            result,
455            Ok(Some(MaybeRelocatable::from(felt_hex!(
456                "0xa06bd018ba91b93146f53563cff2efba46fee2eabe9d89b4cb"
457            ))))
458        );
459    }
460
461    #[test]
462    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
463    fn deduce_memory_cell_non_reloc_address_err() {
464        let memory = memory![
465            ((0, 4), 32),
466            ((0, 5), 72),
467            ((0, 6), 0),
468            ((0, 7), 120),
469            ((0, 8), 52)
470        ];
471        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
472        let result = builtin.deduce_memory_cell(Relocatable::from((0, 1)), &memory);
473        assert_eq!(result, Ok(None));
474    }
475
476    #[test]
477    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
478    fn deduce_memory_cell_offset_lt_input_cell_length_none() {
479        let memory = memory![((0, 4), 32)];
480        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
481        let result = builtin.deduce_memory_cell(Relocatable::from((0, 2)), &memory);
482        assert_eq!(result, Ok(None));
483    }
484
485    #[test]
486    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
487    fn deduce_memory_cell_expected_integer() {
488        let memory = memory![((0, 0), (1, 2))];
489
490        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
491
492        let result = builtin.deduce_memory_cell(Relocatable::from((0, 9)), &memory);
493
494        assert_eq!(
495            result,
496            Err(RunnerError::BuiltinExpectedInteger(Box::new((
497                BuiltinName::keccak,
498                (0, 0).into()
499            ))))
500        );
501    }
502
503    #[test]
504    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
505    fn deduce_memory_cell_missing_input_cells() {
506        let memory = memory![((0, 1), (1, 2))];
507
508        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
509
510        let result = builtin.deduce_memory_cell(Relocatable::from((0, 1)), &memory);
511
512        assert_eq!(result, Ok(None));
513    }
514
515    #[test]
516    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
517    fn deduce_memory_cell_get_memory_err() {
518        let memory = memory![((0, 35), 0)];
519
520        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
521
522        let result = builtin.deduce_memory_cell(Relocatable::from((0, 15)), &memory);
523
524        assert_eq!(result, Ok(None));
525    }
526
527    #[test]
528    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
529    fn deduce_memory_cell_memory_int_larger_than_bits() {
530        let mut memory = memory![
531            ((0, 17), 199),
532            ((0, 18), 0),
533            ((0, 19), 0),
534            ((0, 20), 0),
535            ((0, 21), 0),
536            ((0, 22), 0),
537            ((0, 23), 1),
538            ((0, 24), 0),
539            ((0, 25), 0),
540            ((0, 26), 43),
541            ((0, 27), 199),
542            ((0, 28), 0),
543            ((0, 29), 0),
544            ((0, 30), 0),
545            ((0, 31), 0),
546            ((0, 32), 0),
547            ((0, 33), 1),
548            ((0, 34), 0),
549            ((0, 35), 0)
550        ];
551
552        memory.insert((0, 16).into(), Felt252::MAX).unwrap();
553
554        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
555
556        let result = builtin.deduce_memory_cell(Relocatable::from((0, 25)), &memory);
557
558        assert_eq!(
559            result,
560            Err(RunnerError::IntegerBiggerThanPowerOfTwo(Box::new((
561                (0, 16).into(),
562                BITS,
563                Felt252::MAX
564            ))))
565        );
566    }
567
568    #[test]
569    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
570    fn get_used_diluted_check_units_result() {
571        let builtin = KeccakBuiltinRunner::new(Some(2048), true);
572
573        let result: usize = builtin.get_used_diluted_check_units(16);
574
575        assert_eq!(result, 16384);
576    }
577
578    #[test]
579    fn keccak_f() {
580        let input_bytes = b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
581        let expected_output_bytes = b"\xf6\x98\x81\xe1\x00!\x1f.\xc4*\x8c\x0c\x7fF\xc8q8\xdf\xb9\xbe\x07H\xca7T1\xab\x16\x17\xa9\x11\xff-L\x87\xb2iY.\x96\x82x\xde\xbb\\up?uz:0\xee\x08\x1b\x15\xd6\n\xab\r\x0b\x87T:w\x0fH\xe7!f},\x08a\xe5\xbe8\x16\x13\x9a?\xad~<9\xf7\x03`\x8b\xd8\xa3F\x8aQ\xf9\n9\xcdD\xb7.X\xf7\x8e\x1f\x17\x9e \xe5i\x01rr\xdf\xaf\x99k\x9f\x8e\x84\\\xday`\xf1``\x02q+\x8e\xad\x96\xd8\xff\xff3<\xb6\x01o\xd7\xa6\x86\x9d\xea\xbc\xfb\x08\xe1\xa3\x1c\x06z\xab@\xa1\xc1\xb1xZ\x92\x96\xc0.\x01\x13g\x93\x87!\xa6\xa8z\x9c@\x0bY'\xe7\xa7Qr\xe5\xc1\xa3\xa6\x88H\xa5\xc0@9k:y\xd1Kw\xd5";
582        let output_bytes = KeccakBuiltinRunner::keccak_f(input_bytes);
583        assert_eq!(output_bytes, Ok(expected_output_bytes.to_vec()));
584    }
585
586    #[test]
587    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
588    fn get_air_private_input() {
589        let builtin: BuiltinRunner = KeccakBuiltinRunner::new(Some(2048), true).into();
590
591        let segments = segments![
592            ((0, 0), 0),
593            ((0, 1), 1),
594            ((0, 2), 2),
595            ((0, 3), 3),
596            ((0, 4), 4),
597            ((0, 5), 5),
598            ((0, 6), 6),
599            ((0, 7), 7)
600        ];
601        assert_eq!(
602            builtin.air_private_input(&segments),
603            (vec![PrivateInput::KeccakState(PrivateInputKeccakState {
604                index: 0,
605                input_s0: 0.into(),
606                input_s1: 1.into(),
607                input_s2: 2.into(),
608                input_s3: 3.into(),
609                input_s4: 4.into(),
610                input_s5: 5.into(),
611                input_s6: 6.into(),
612                input_s7: 7.into()
613            }),]),
614        );
615    }
616}