openvm_sha2_circuit/sha2_chips/main_chip/
trace.rs1use openvm_circuit::{
2 arch::*,
3 system::memory::{
4 offline_checker::{MemoryReadAuxRecord, MemoryWriteBytesAuxRecord},
5 MemoryAuxColsFactory,
6 },
7 utils::next_power_of_two_or_zero,
8};
9use openvm_circuit_primitives::Chip;
10use openvm_cpu_backend::CpuBackend;
11use openvm_instructions::riscv::{RV32_CELL_BITS, RV32_REGISTER_NUM_LIMBS};
12use openvm_sha2_air::set_arrayview_from_u8_slice;
13use openvm_stark_backend::{
14 p3_field::{PrimeCharacteristicRing, PrimeField32},
15 p3_matrix::{dense::RowMajorMatrix, Matrix},
16 p3_maybe_rayon::prelude::*,
17 prover::AirProvingContext,
18 StarkProtocolConfig, Val,
19};
20
21use crate::{
22 Sha2ColsRefMut, Sha2Config, Sha2MainChip, Sha2Metadata, Sha2RecordLayout, Sha2RecordMut,
23 Sha2SharedRecords, SHA2_WRITE_SIZE,
24};
25
26impl<RA, SC: StarkProtocolConfig, C: Sha2Config> Chip<RA, CpuBackend<SC>>
29 for Sha2MainChip<Val<SC>, C>
30where
31 Val<SC>: PrimeField32,
32 SC: StarkProtocolConfig,
33 RA: RowMajorMatrixArena<Val<SC>> + Send + Sync,
34{
35 fn generate_proving_ctx(&self, arena: RA) -> AirProvingContext<CpuBackend<SC>> {
36 let rows_used = arena.trace_offset() / arena.width();
39
40 let height = next_power_of_two_or_zero(rows_used);
45 let trace = Val::<SC>::zero_vec(height * arena.width());
46 let mut trace_matrix = RowMajorMatrix::new(trace, arena.width());
47 let mem_helper = self.mem_helper.as_borrowed();
48
49 let mut records = arena.into_matrix();
50
51 self.fill_trace(&mem_helper, &mut trace_matrix, rows_used, &mut records);
52
53 *self.records.lock().unwrap() = Some(Sha2SharedRecords {
55 num_records: rows_used,
56 matrix: records,
57 });
58
59 AirProvingContext::simple_no_pis(trace_matrix)
60 }
61}
62
63impl<F: PrimeField32, C: Sha2Config> Sha2MainChip<F, C> {
66 pub fn fill_trace(
71 &self,
72 mem_helper: &MemoryAuxColsFactory<F>,
73 trace: &mut RowMajorMatrix<F>,
74 rows_used: usize,
75 records: &mut RowMajorMatrix<F>,
76 ) {
77 let width = trace.width();
78 trace.values[..rows_used * width]
79 .par_chunks_exact_mut(width)
80 .zip(records.par_rows_mut())
81 .enumerate()
82 .for_each(|(row_idx, (row_slice, record))| {
83 self.fill_trace_row_with_row_idx(mem_helper, row_slice, row_idx, record);
84 });
85 }
86
87 fn fill_trace_row_with_row_idx(
95 &self,
96 mem_helper: &MemoryAuxColsFactory<F>,
97 row_slice: &mut [F],
98 row_idx: usize,
99 mut record: &mut [F],
100 ) where
101 F: Clone,
102 {
103 let record: Sha2RecordMut = unsafe {
110 get_record_from_slice(
111 &mut record,
112 Sha2RecordLayout::new(Sha2Metadata {
113 variant: C::VARIANT,
114 }),
115 )
116 };
117
118 let vm_record = record.inner.clone();
121
122 let mut message_bytes = Vec::with_capacity(C::BLOCK_BYTES);
123 message_bytes.extend_from_slice(record.message_bytes);
124
125 let mut prev_state = Vec::with_capacity(C::STATE_BYTES);
126 prev_state.extend_from_slice(record.prev_state);
127
128 let mut new_state = Vec::with_capacity(C::STATE_BYTES);
129 new_state.extend_from_slice(record.new_state);
130
131 let mut input_reads_aux =
132 Vec::with_capacity(C::BLOCK_READS * size_of::<MemoryReadAuxRecord>());
133 input_reads_aux.extend_from_slice(record.input_reads_aux);
134
135 let mut state_reads_aux =
136 Vec::with_capacity(C::STATE_READS * size_of::<MemoryReadAuxRecord>());
137 state_reads_aux.extend_from_slice(record.state_reads_aux);
138
139 let mut write_aux = Vec::with_capacity(
140 C::STATE_WRITES * size_of::<MemoryWriteBytesAuxRecord<SHA2_WRITE_SIZE>>(),
141 );
142 write_aux.extend_from_slice(record.write_aux);
143
144 let mut cols = Sha2ColsRefMut::from::<C>(row_slice);
145
146 *cols.block.request_id = F::from_usize(row_idx);
147 set_arrayview_from_u8_slice(&mut cols.block.message_bytes, message_bytes);
148 set_arrayview_from_u8_slice(&mut cols.block.prev_state, prev_state);
149 set_arrayview_from_u8_slice(&mut cols.block.new_state, new_state);
150
151 *cols.instruction.is_enabled = F::ONE;
152 cols.instruction.from_state.timestamp = F::from_u32(vm_record.timestamp);
153 cols.instruction.from_state.pc = F::from_u32(vm_record.from_pc);
154 *cols.instruction.dst_reg_ptr = F::from_u32(vm_record.dst_reg_ptr);
155 *cols.instruction.state_reg_ptr = F::from_u32(vm_record.state_reg_ptr);
156 *cols.instruction.input_reg_ptr = F::from_u32(vm_record.input_reg_ptr);
157
158 let dst_ptr_limbs = vm_record.dst_ptr.to_le_bytes();
159 let state_ptr_limbs = vm_record.state_ptr.to_le_bytes();
160 let input_ptr_limbs = vm_record.input_ptr.to_le_bytes();
161 set_arrayview_from_u8_slice(&mut cols.instruction.dst_ptr_limbs, dst_ptr_limbs);
162 set_arrayview_from_u8_slice(&mut cols.instruction.state_ptr_limbs, state_ptr_limbs);
163 set_arrayview_from_u8_slice(&mut cols.instruction.input_ptr_limbs, input_ptr_limbs);
164 let needs_range_check = [
165 dst_ptr_limbs[RV32_REGISTER_NUM_LIMBS - 1],
166 state_ptr_limbs[RV32_REGISTER_NUM_LIMBS - 1],
167 input_ptr_limbs[RV32_REGISTER_NUM_LIMBS - 1],
168 input_ptr_limbs[RV32_REGISTER_NUM_LIMBS - 1],
169 ];
170 let shift: u32 = 1 << (RV32_REGISTER_NUM_LIMBS * RV32_CELL_BITS - self.pointer_max_bits);
171 for pair in needs_range_check.chunks_exact(2) {
172 self.bitwise_lookup_chip
173 .request_range(pair[0] as u32 * shift, pair[1] as u32 * shift);
174 }
175
176 let mut timestamp = vm_record.timestamp;
178 for (cols, vm_record) in cols
179 .mem
180 .register_aux
181 .iter_mut()
182 .zip(vm_record.register_reads_aux.iter())
183 {
184 mem_helper.fill(vm_record.prev_timestamp, timestamp, cols.as_mut());
185 timestamp += 1;
186 }
187
188 input_reads_aux.iter().zip(cols.mem.input_reads).for_each(
189 |(read_aux_record, read_aux_cols)| {
190 mem_helper.fill(
191 read_aux_record.prev_timestamp,
192 timestamp,
193 read_aux_cols.as_mut(),
194 );
195 timestamp += 1;
196 },
197 );
198
199 state_reads_aux.iter().zip(cols.mem.state_reads).for_each(
200 |(state_aux_record, state_aux_cols)| {
201 mem_helper.fill(
202 state_aux_record.prev_timestamp,
203 timestamp,
204 state_aux_cols.as_mut(),
205 );
206 timestamp += 1;
207 },
208 );
209
210 write_aux
211 .iter()
212 .zip(cols.mem.write_aux)
213 .for_each(|(write_aux_record, write_aux_cols)| {
214 write_aux_cols.set_prev_data(write_aux_record.prev_data.map(F::from_u8));
215 mem_helper.fill(
216 write_aux_record.prev_timestamp,
217 timestamp,
218 write_aux_cols.as_mut(),
219 );
220 timestamp += 1;
221 });
222 }
223}