1use core::{fmt::Debug, mem::size_of};
2use std::{
3 borrow::{Borrow, BorrowMut},
4 ops::Range,
5};
6
7use deepsize2::DeepSizeOf;
8use itertools::Itertools;
9use serde::{Deserialize, Serialize};
10use slop_algebra::{AbstractField, PrimeField32};
11use sp1_primitives::consts::split_page_idx;
12
13use crate::{septic_curve::SepticCurve, septic_digest::SepticDigest, PROOF_MAX_NUM_PVS};
14
15#[cfg(feature = "mprotect")]
16use crate::addr_to_limbs;
17
18pub const SP1_PROOF_NUM_PV_ELTS: usize = size_of::<PublicValues<[u8; 4], [u8; 3], [u8; 4], u8>>();
20
21pub const PV_DIGEST_NUM_WORDS: usize = 8;
23
24pub const POSEIDON_NUM_WORDS: usize = 8;
26
27pub const PROOF_NONCE_NUM_WORDS: usize = 4;
29
30#[derive(Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq, DeepSizeOf)]
32#[repr(C)]
33pub struct PublicValues<W1, W2, W3, T> {
34 pub prev_committed_value_digest: [W1; PV_DIGEST_NUM_WORDS],
36
37 pub committed_value_digest: [W1; PV_DIGEST_NUM_WORDS],
39
40 pub prev_deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
42
43 pub deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
47
48 pub pc_start: W2,
50
51 pub next_pc: W2,
53
54 pub prev_exit_code: T,
56
57 pub exit_code: T,
60
61 pub is_execution_shard: T,
63
64 pub previous_init_addr: W2,
66
67 pub last_init_addr: W2,
69
70 pub previous_finalize_addr: W2,
72
73 pub last_finalize_addr: W2,
75
76 pub previous_init_page_idx: W2,
78
79 pub last_init_page_idx: W2,
81
82 pub previous_finalize_page_idx: W2,
84
85 pub last_finalize_page_idx: W2,
87
88 pub initial_timestamp: W3,
90
91 pub last_timestamp: W3,
93
94 pub is_timestamp_high_eq: T,
96
97 pub inv_timestamp_high: T,
99
100 pub is_timestamp_low_eq: T,
102
103 pub inv_timestamp_low: T,
105
106 pub global_init_count: T,
108
109 pub global_finalize_count: T,
111
112 pub global_page_prot_init_count: T,
114
115 pub global_page_prot_finalize_count: T,
117
118 pub global_count: T,
120
121 pub global_cumulative_sum: SepticDigest<T>,
123
124 pub prev_commit_syscall: T,
126
127 pub commit_syscall: T,
129
130 pub prev_commit_deferred_syscall: T,
132
133 pub commit_deferred_syscall: T,
135
136 pub initial_timestamp_inv: T,
138
139 pub last_timestamp_inv: T,
141
142 pub is_first_execution_shard: T,
144
145 pub is_untrusted_programs_enabled: T,
148
149 #[cfg(feature = "mprotect")]
151 pub enable_trap_handler: T,
152
153 #[cfg(feature = "mprotect")]
155 pub trap_context: [W2; 3],
156
157 #[cfg(feature = "mprotect")]
159 pub untrusted_memory: [W2; 2],
160
161 pub proof_nonce: [T; PROOF_NONCE_NUM_WORDS],
163
164 pub empty: [T; 4],
166}
167
168impl PublicValues<u32, u64, u64, u32> {
169 #[must_use]
172 pub fn to_vec<F: AbstractField>(&self) -> Vec<F> {
173 let mut ret = vec![F::zero(); PROOF_MAX_NUM_PVS];
174
175 let field_values = PublicValues::<[F; 4], [F; 3], [F; 4], F>::from(*self);
176 let ret_ref_mut: &mut PublicValues<[F; 4], [F; 3], [F; 4], F> =
177 ret.as_mut_slice().borrow_mut();
178 *ret_ref_mut = field_values;
179 ret
180 }
181
182 #[must_use]
186 pub fn range(&self) -> ShardRange {
187 ShardRange {
188 timestamp_range: (self.initial_timestamp, self.last_timestamp),
189 initialized_address_range: (self.previous_init_addr, self.last_init_addr),
190 finalized_address_range: (self.previous_finalize_addr, self.last_finalize_addr),
191 initialized_page_index_range: (self.previous_init_page_idx, self.last_init_page_idx),
192 finalized_page_index_range: (
193 self.previous_finalize_page_idx,
194 self.last_finalize_page_idx,
195 ),
196 deferred_proof_range: (0, 0),
197 }
198 }
199
200 #[must_use]
202 pub fn reset(&self) -> Self {
203 let mut copy = *self;
204 copy.pc_start = 0;
205 copy.next_pc = 0;
206 copy.previous_init_addr = 0;
207 copy.last_init_addr = 0;
208 copy.previous_finalize_addr = 0;
209 copy.last_finalize_addr = 0;
210 copy.previous_init_page_idx = 0;
211 copy.last_init_page_idx = 0;
212 copy.previous_finalize_page_idx = 0;
213 copy.last_finalize_page_idx = 0;
214 copy
215 }
216
217 #[must_use]
220 #[cfg_attr(not(feature = "mprotect"), allow(unused_variables))]
221 pub fn initialize(
222 &self,
223 pc_start_abs: u64,
224 enable_untrusted_programs: bool,
225 trap_context: Option<u64>,
226 untrusted_memory: Option<(u64, u64)>,
227 ) -> Self {
228 let mut state = *self;
229 state.pc_start = pc_start_abs;
230 state.next_pc = pc_start_abs;
231 state.initial_timestamp = 1;
232 state.last_timestamp = 1;
233 state.is_timestamp_high_eq = 1;
234 state.is_timestamp_low_eq = 1;
235 state.is_first_execution_shard = 0;
236 state.is_execution_shard = 0;
237 state.initial_timestamp_inv = 0;
238 state.last_timestamp_inv = 0;
239 state.is_untrusted_programs_enabled = enable_untrusted_programs as u32;
240 #[cfg(feature = "mprotect")]
241 {
242 state.enable_trap_handler = trap_context.is_some() as u32;
243 state.trap_context = trap_context.map_or([0, 0, 0], |addr| [addr, addr + 8, addr + 16]);
244 state.untrusted_memory = untrusted_memory.map_or([0, 0], |(start, end)| [start, end]);
245 }
246 state
247 }
248
249 pub fn update_state(&mut self, state: &PublicValues<u32, u64, u64, u32>) {
251 self.pc_start = state.pc_start;
252 self.next_pc = state.next_pc;
253 self.exit_code = state.exit_code;
254 self.initial_timestamp = state.initial_timestamp;
255 self.last_timestamp = state.last_timestamp;
256 self.is_timestamp_high_eq = state.is_timestamp_high_eq;
257 self.is_timestamp_low_eq = state.is_timestamp_low_eq;
258 self.last_timestamp_inv = state.last_timestamp_inv;
259 self.initial_timestamp_inv = state.initial_timestamp_inv;
260 self.is_first_execution_shard = state.is_first_execution_shard;
261 self.is_execution_shard = state.is_execution_shard;
262 self.is_untrusted_programs_enabled = state.is_untrusted_programs_enabled;
263 #[cfg(feature = "mprotect")]
264 {
265 self.enable_trap_handler = state.enable_trap_handler;
266 self.trap_context = state.trap_context;
267 self.untrusted_memory = state.untrusted_memory;
268 }
269 }
270
271 #[cfg_attr(not(feature = "mprotect"), allow(unused_variables))]
274 pub fn update_initialized_state(
275 &mut self,
276 pc_start_abs: u64,
277 enable_untrusted_programs: bool,
278 trap_context: Option<u64>,
279 untrusted_memory: Option<(u64, u64)>,
280 ) {
281 self.pc_start = pc_start_abs;
282 self.next_pc = pc_start_abs;
283 self.exit_code = 0;
284 self.initial_timestamp = 1;
285 self.last_timestamp = 1;
286 self.is_timestamp_high_eq = 1;
287 self.is_timestamp_low_eq = 1;
288 self.is_first_execution_shard = 0;
289 self.is_execution_shard = 0;
290 self.initial_timestamp_inv = 0;
291 self.last_timestamp_inv = 0;
292 self.is_untrusted_programs_enabled = enable_untrusted_programs as u32;
293 #[cfg(feature = "mprotect")]
294 {
295 self.enable_trap_handler = trap_context.is_some() as u32;
296 self.trap_context = trap_context.map_or([0, 0, 0], |addr| [addr, addr + 8, addr + 16]);
297 self.untrusted_memory = untrusted_memory.map_or([0, 0], |(start, end)| [start, end]);
298 }
299 }
300
301 #[allow(clippy::too_many_arguments)]
304 #[cfg_attr(not(feature = "mprotect"), allow(unused_variables))]
305 pub fn update_finalized_state(
306 &mut self,
307 timestamp: u64,
308 pc: u64,
309 exit_code: u32,
310 is_untrusted_programs_enabled: u32,
311 enable_trap_handler: u32,
312 trap_context: [u64; 3],
313 untrusted_memory: [u64; 2],
314 committed_value_digest: [u32; PV_DIGEST_NUM_WORDS],
315 deferred_proofs_digest: [u32; POSEIDON_NUM_WORDS],
316 nonce: [u32; PROOF_NONCE_NUM_WORDS],
317 ) {
318 self.pc_start = pc;
319 self.next_pc = pc;
320 self.exit_code = exit_code;
321 self.initial_timestamp = timestamp;
322 self.last_timestamp = timestamp;
323 self.is_timestamp_high_eq = 1;
324 self.is_timestamp_low_eq = 1;
325 self.is_first_execution_shard = 0;
326 self.is_execution_shard = 0;
327 self.initial_timestamp_inv = 0;
328 self.last_timestamp_inv = 0;
329 self.prev_committed_value_digest = committed_value_digest;
330 self.committed_value_digest = committed_value_digest;
331 self.prev_deferred_proofs_digest = deferred_proofs_digest;
332 self.deferred_proofs_digest = deferred_proofs_digest;
333 self.is_untrusted_programs_enabled = is_untrusted_programs_enabled;
334 #[cfg(feature = "mprotect")]
335 {
336 self.enable_trap_handler = enable_trap_handler;
337 self.trap_context = trap_context;
338 self.untrusted_memory = untrusted_memory;
339 }
340 self.prev_exit_code = exit_code;
341 self.prev_commit_syscall = 1;
342 self.commit_syscall = 1;
343 self.prev_commit_deferred_syscall = 1;
344 self.commit_deferred_syscall = 1;
345 self.proof_nonce = nonce;
346 }
347
348 pub fn update_finalized_state_from_public_values(
351 &mut self,
352 public_values: &PublicValues<u32, u64, u64, u32>,
353 ) {
354 #[cfg(feature = "mprotect")]
355 let (enable_trap_handler, trap_context, untrusted_memory) = (
356 public_values.enable_trap_handler,
357 public_values.trap_context,
358 public_values.untrusted_memory,
359 );
360 #[cfg(not(feature = "mprotect"))]
361 let (enable_trap_handler, trap_context, untrusted_memory) = (0, [0, 0, 0], [0, 0]);
362
363 self.update_finalized_state(
364 public_values.last_timestamp,
365 public_values.next_pc,
366 public_values.exit_code,
367 public_values.is_untrusted_programs_enabled,
368 enable_trap_handler,
369 trap_context,
370 untrusted_memory,
371 public_values.committed_value_digest,
372 public_values.deferred_proofs_digest,
373 public_values.proof_nonce,
374 );
375 }
376}
377
378#[inline]
383pub fn timestamp_from_limbs<F: PrimeField32>(limbs: &[F; 4]) -> u64 {
384 let mut timestamp = (limbs[0].as_canonical_u32() as u64) << 32;
385 timestamp += (limbs[1].as_canonical_u32() as u64) << 24;
386 timestamp += (limbs[2].as_canonical_u32() as u64) << 16;
387 timestamp += limbs[3].as_canonical_u32() as u64;
388 timestamp
389}
390
391pub type SP1CorePublicValues<F> = PublicValues<[F; 4], [F; 3], [F; 4], F>;
393
394impl<F: PrimeField32> PublicValues<[F; 4], [F; 3], [F; 4], F> {
395 pub fn commit_digest_bytes(&self) -> Vec<u8> {
397 self.committed_value_digest
398 .iter()
399 .flat_map(|w| w.iter().map(|f| f.as_canonical_u32() as u8))
400 .collect_vec()
401 }
402
403 pub fn initial_timestamp(&self) -> u64 {
405 timestamp_from_limbs(&self.initial_timestamp)
406 }
407
408 pub fn last_timestamp(&self) -> u64 {
410 timestamp_from_limbs(&self.last_timestamp)
411 }
412
413 pub fn previous_init_addr(&self) -> u64 {
415 self.previous_init_addr
416 .iter()
417 .rev()
418 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
419 }
420
421 pub fn last_init_addr(&self) -> u64 {
423 self.last_init_addr
424 .iter()
425 .rev()
426 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
427 }
428
429 pub fn previous_finalize_addr(&self) -> u64 {
431 self.previous_finalize_addr
432 .iter()
433 .rev()
434 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
435 }
436
437 pub fn last_finalize_addr(&self) -> u64 {
439 self.last_finalize_addr
440 .iter()
441 .rev()
442 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
443 }
444
445 pub fn previous_init_page_idx(&self) -> u64 {
447 self.previous_init_page_idx
448 .iter()
449 .rev()
450 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
451 }
452
453 pub fn last_init_page_idx(&self) -> u64 {
455 self.last_init_page_idx
456 .iter()
457 .rev()
458 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
459 }
460
461 pub fn previous_finalize_page_idx(&self) -> u64 {
463 self.previous_finalize_page_idx
464 .iter()
465 .rev()
466 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
467 }
468
469 pub fn last_finalize_page_idx(&self) -> u64 {
471 self.last_finalize_page_idx
472 .iter()
473 .rev()
474 .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
475 }
476
477 #[must_use]
479 pub fn range(&self) -> ShardRange {
480 let timestamp_range = (self.initial_timestamp(), self.last_timestamp());
481 let initialized_address_range = (self.previous_init_addr(), self.last_init_addr());
482 let finalized_address_range = (self.previous_finalize_addr(), self.last_finalize_addr());
483 let initialized_page_index_range =
484 (self.previous_init_page_idx(), self.last_init_page_idx());
485 let finalized_page_index_range =
486 (self.previous_finalize_page_idx(), self.last_finalize_page_idx());
487 let deferred_proof_range = (0, 0);
488
489 ShardRange {
490 timestamp_range,
491 initialized_address_range,
492 finalized_address_range,
493 initialized_page_index_range,
494 finalized_page_index_range,
495 deferred_proof_range,
496 }
497 }
498}
499
500impl<T: Clone> Borrow<PublicValues<[T; 4], [T; 3], [T; 4], T>> for [T] {
501 fn borrow(&self) -> &PublicValues<[T; 4], [T; 3], [T; 4], T> {
502 let size = std::mem::size_of::<PublicValues<[u8; 4], [u8; 3], [u8; 4], u8>>();
503 debug_assert!(self.len() >= size);
504 let slice = &self[0..size];
505 let (prefix, shorts, _suffix) =
506 unsafe { slice.align_to::<PublicValues<[T; 4], [T; 3], [T; 4], T>>() };
507 debug_assert!(prefix.is_empty(), "Alignment should match");
508 debug_assert_eq!(shorts.len(), 1);
509 &shorts[0]
510 }
511}
512
513impl<T: Clone> BorrowMut<PublicValues<[T; 4], [T; 3], [T; 4], T>> for [T] {
514 fn borrow_mut(&mut self) -> &mut PublicValues<[T; 4], [T; 3], [T; 4], T> {
515 let size = std::mem::size_of::<PublicValues<[u8; 4], [u8; 3], [u8; 4], u8>>();
516 debug_assert!(self.len() >= size);
517 let slice = &mut self[0..size];
518 let (prefix, shorts, _suffix) =
519 unsafe { slice.align_to_mut::<PublicValues<[T; 4], [T; 3], [T; 4], T>>() };
520 debug_assert!(prefix.is_empty(), "Alignment should match");
521 debug_assert_eq!(shorts.len(), 1);
522 &mut shorts[0]
523 }
524}
525
526impl<F: AbstractField> From<PublicValues<u32, u64, u64, u32>>
527 for PublicValues<[F; 4], [F; 3], [F; 4], F>
528{
529 #[allow(clippy::too_many_lines)]
530 fn from(value: PublicValues<u32, u64, u64, u32>) -> Self {
531 let PublicValues {
532 prev_committed_value_digest,
533 committed_value_digest,
534 prev_deferred_proofs_digest,
535 deferred_proofs_digest,
536 pc_start,
537 next_pc,
538 prev_exit_code,
539 exit_code,
540 is_execution_shard,
541 previous_init_addr,
542 last_init_addr,
543 previous_finalize_addr,
544 last_finalize_addr,
545 previous_init_page_idx,
546 last_init_page_idx,
547 previous_finalize_page_idx,
548 last_finalize_page_idx,
549 initial_timestamp,
550 last_timestamp,
551 is_timestamp_high_eq,
552 inv_timestamp_high,
553 is_timestamp_low_eq,
554 inv_timestamp_low,
555 global_init_count,
556 global_finalize_count,
557 global_page_prot_init_count,
558 global_page_prot_finalize_count,
559 global_count,
560 global_cumulative_sum,
561 prev_commit_syscall,
562 commit_syscall,
563 prev_commit_deferred_syscall,
564 commit_deferred_syscall,
565 is_untrusted_programs_enabled,
566 #[cfg(feature = "mprotect")]
567 enable_trap_handler,
568 #[cfg(feature = "mprotect")]
569 trap_context,
570 #[cfg(feature = "mprotect")]
571 untrusted_memory,
572 proof_nonce,
573 initial_timestamp_inv,
574 last_timestamp_inv,
575 is_first_execution_shard,
576 ..
577 } = value;
578
579 let prev_committed_value_digest: [_; PV_DIGEST_NUM_WORDS] = core::array::from_fn(|i| {
580 [
581 F::from_canonical_u32(prev_committed_value_digest[i] & 0xFF),
582 F::from_canonical_u32((prev_committed_value_digest[i] >> 8) & 0xFF),
583 F::from_canonical_u32((prev_committed_value_digest[i] >> 16) & 0xFF),
584 F::from_canonical_u32((prev_committed_value_digest[i] >> 24) & 0xFF),
585 ]
586 });
587
588 let committed_value_digest: [_; PV_DIGEST_NUM_WORDS] = core::array::from_fn(|i| {
589 [
590 F::from_canonical_u32(committed_value_digest[i] & 0xFF),
591 F::from_canonical_u32((committed_value_digest[i] >> 8) & 0xFF),
592 F::from_canonical_u32((committed_value_digest[i] >> 16) & 0xFF),
593 F::from_canonical_u32((committed_value_digest[i] >> 24) & 0xFF),
594 ]
595 });
596
597 let prev_deferred_proofs_digest: [_; POSEIDON_NUM_WORDS] =
598 core::array::from_fn(|i| F::from_canonical_u32(prev_deferred_proofs_digest[i]));
599
600 let deferred_proofs_digest: [_; POSEIDON_NUM_WORDS] =
601 core::array::from_fn(|i| F::from_canonical_u32(deferred_proofs_digest[i]));
602
603 let pc_start = [
604 F::from_canonical_u16((pc_start & 0xFFFF) as u16),
605 F::from_canonical_u16(((pc_start >> 16) & 0xFFFF) as u16),
606 F::from_canonical_u16(((pc_start >> 32) & 0xFFFF) as u16),
607 ];
608 let next_pc = [
609 F::from_canonical_u16((next_pc & 0xFFFF) as u16),
610 F::from_canonical_u16(((next_pc >> 16) & 0xFFFF) as u16),
611 F::from_canonical_u16(((next_pc >> 32) & 0xFFFF) as u16),
612 ];
613 let exit_code = F::from_canonical_u32(exit_code);
614 let prev_exit_code = F::from_canonical_u32(prev_exit_code);
615 let is_execution_shard = F::from_canonical_u32(is_execution_shard);
616 let previous_init_addr = [
617 F::from_canonical_u16((previous_init_addr & 0xFFFF) as u16),
618 F::from_canonical_u16(((previous_init_addr >> 16) & 0xFFFF) as u16),
619 F::from_canonical_u16(((previous_init_addr >> 32) & 0xFFFF) as u16),
620 ];
621 let last_init_addr = [
622 F::from_canonical_u16((last_init_addr & 0xFFFF) as u16),
623 F::from_canonical_u16(((last_init_addr >> 16) & 0xFFFF) as u16),
624 F::from_canonical_u16(((last_init_addr >> 32) & 0xFFFF) as u16),
625 ];
626 let previous_finalize_addr = [
627 F::from_canonical_u16((previous_finalize_addr & 0xFFFF) as u16),
628 F::from_canonical_u16(((previous_finalize_addr >> 16) & 0xFFFF) as u16),
629 F::from_canonical_u16(((previous_finalize_addr >> 32) & 0xFFFF) as u16),
630 ];
631 let last_finalize_addr = [
632 F::from_canonical_u16((last_finalize_addr & 0xFFFF) as u16),
633 F::from_canonical_u16(((last_finalize_addr >> 16) & 0xFFFF) as u16),
634 F::from_canonical_u16(((last_finalize_addr >> 32) & 0xFFFF) as u16),
635 ];
636 let previous_init_page_idx: [F; 3] = core::array::from_fn(|i| {
637 F::from_canonical_u16(split_page_idx(previous_init_page_idx)[i])
638 });
639 let last_init_page_idx: [F; 3] =
640 core::array::from_fn(|i| F::from_canonical_u16(split_page_idx(last_init_page_idx)[i]));
641 let previous_finalize_page_idx: [F; 3] = core::array::from_fn(|i| {
642 F::from_canonical_u16(split_page_idx(previous_finalize_page_idx)[i])
643 });
644 let last_finalize_page_idx: [F; 3] = core::array::from_fn(|i| {
645 F::from_canonical_u16(split_page_idx(last_finalize_page_idx)[i])
646 });
647 let initial_timestamp = [
648 F::from_canonical_u16((initial_timestamp >> 32) as u16),
649 F::from_canonical_u8(((initial_timestamp >> 24) & 0xFF) as u8),
650 F::from_canonical_u8(((initial_timestamp >> 16) & 0xFF) as u8),
651 F::from_canonical_u16((initial_timestamp & 0xFFFF) as u16),
652 ];
653 let last_timestamp = [
654 F::from_canonical_u16((last_timestamp >> 32) as u16),
655 F::from_canonical_u8(((last_timestamp >> 24) & 0xFF) as u8),
656 F::from_canonical_u8(((last_timestamp >> 16) & 0xFF) as u8),
657 F::from_canonical_u16((last_timestamp & 0xFFFF) as u16),
658 ];
659
660 let is_timestamp_high_eq = F::from_canonical_u32(is_timestamp_high_eq);
661 let inv_timestamp_high = F::from_canonical_u32(inv_timestamp_high);
662 let is_timestamp_low_eq = F::from_canonical_u32(is_timestamp_low_eq);
663 let inv_timestamp_low = F::from_canonical_u32(inv_timestamp_low);
664
665 let global_init_count = F::from_canonical_u32(global_init_count);
666 let global_finalize_count = F::from_canonical_u32(global_finalize_count);
667 let global_page_prot_init_count = F::from_canonical_u32(global_page_prot_init_count);
668 let global_page_prot_finalize_count =
669 F::from_canonical_u32(global_page_prot_finalize_count);
670 let global_count = F::from_canonical_u32(global_count);
671 let global_cumulative_sum =
672 SepticDigest(SepticCurve::convert(global_cumulative_sum.0, F::from_canonical_u32));
673
674 let prev_commit_syscall = F::from_canonical_u32(prev_commit_syscall);
675 let commit_syscall = F::from_canonical_u32(commit_syscall);
676 let prev_commit_deferred_syscall = F::from_canonical_u32(prev_commit_deferred_syscall);
677 let commit_deferred_syscall = F::from_canonical_u32(commit_deferred_syscall);
678
679 let initial_timestamp_inv = F::from_canonical_u32(initial_timestamp_inv);
680 let last_timestamp_inv = F::from_canonical_u32(last_timestamp_inv);
681 let is_first_execution_shard = F::from_canonical_u32(is_first_execution_shard);
682 let is_untrusted_programs_enabled = F::from_canonical_u32(is_untrusted_programs_enabled);
683
684 #[cfg(feature = "mprotect")]
685 let enable_trap_handler = F::from_canonical_u32(enable_trap_handler);
686 #[cfg(feature = "mprotect")]
687 let trap_context = [
688 addr_to_limbs::<F>(trap_context[0]),
689 addr_to_limbs::<F>(trap_context[1]),
690 addr_to_limbs::<F>(trap_context[2]),
691 ];
692 #[cfg(feature = "mprotect")]
693 let untrusted_memory =
694 [addr_to_limbs::<F>(untrusted_memory[0]), addr_to_limbs::<F>(untrusted_memory[1])];
695
696 let proof_nonce: [_; PROOF_NONCE_NUM_WORDS] =
697 core::array::from_fn(|i| F::from_canonical_u32(proof_nonce[i]));
698
699 Self {
700 prev_committed_value_digest,
701 committed_value_digest,
702 prev_deferred_proofs_digest,
703 deferred_proofs_digest,
704 pc_start,
705 next_pc,
706 prev_exit_code,
707 exit_code,
708 is_execution_shard,
709 previous_init_addr,
710 last_init_addr,
711 previous_finalize_addr,
712 last_finalize_addr,
713 previous_init_page_idx,
714 last_init_page_idx,
715 previous_finalize_page_idx,
716 last_finalize_page_idx,
717 initial_timestamp,
718 last_timestamp,
719 is_timestamp_high_eq,
720 inv_timestamp_high,
721 is_timestamp_low_eq,
722 inv_timestamp_low,
723 global_init_count,
724 global_finalize_count,
725 global_page_prot_init_count,
726 global_page_prot_finalize_count,
727 global_count,
728 global_cumulative_sum,
729 prev_commit_syscall,
730 commit_syscall,
731 prev_commit_deferred_syscall,
732 commit_deferred_syscall,
733 is_untrusted_programs_enabled,
734 #[cfg(feature = "mprotect")]
735 enable_trap_handler,
736 #[cfg(feature = "mprotect")]
737 trap_context,
738 #[cfg(feature = "mprotect")]
739 untrusted_memory,
740 initial_timestamp_inv,
741 last_timestamp_inv,
742 is_first_execution_shard,
743 proof_nonce,
744 empty: core::array::from_fn(|_| F::zero()),
745 }
746 }
747}
748
749#[derive(
751 Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
752)]
753#[repr(C)]
754pub struct ShardBoundary {
755 pub timestamp: u64,
757 pub initialized_address: u64,
759 pub finalized_address: u64,
761 pub initialized_page_index: u64,
763 pub finalized_page_index: u64,
765 pub deferred_proof: u64,
767}
768
769impl ShardBoundary {
770 #[inline]
774 #[must_use]
775 pub fn initial() -> Self {
776 Self {
777 timestamp: 1,
778 initialized_address: 0,
779 finalized_address: 0,
780 initialized_page_index: 0,
781 finalized_page_index: 0,
782 deferred_proof: 0,
783 }
784 }
785}
786
787#[derive(
789 Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
790)]
791#[repr(C)]
792pub struct ShardRange {
793 pub timestamp_range: (u64, u64),
795 pub initialized_address_range: (u64, u64),
797 pub finalized_address_range: (u64, u64),
799 pub initialized_page_index_range: (u64, u64),
801 pub finalized_page_index_range: (u64, u64),
803 pub deferred_proof_range: (u64, u64),
805}
806
807impl From<Range<ShardBoundary>> for ShardRange {
808 fn from(value: Range<ShardBoundary>) -> Self {
809 Self {
810 timestamp_range: (value.start.timestamp, value.end.timestamp),
811 initialized_address_range: (
812 value.start.initialized_address,
813 value.end.initialized_address,
814 ),
815 finalized_address_range: (value.start.finalized_address, value.end.finalized_address),
816 initialized_page_index_range: (
817 value.start.initialized_page_index,
818 value.end.initialized_page_index,
819 ),
820 finalized_page_index_range: (
821 value.start.finalized_page_index,
822 value.end.finalized_page_index,
823 ),
824 deferred_proof_range: (value.start.deferred_proof, value.end.deferred_proof),
825 }
826 }
827}
828
829impl ShardRange {
830 #[must_use]
832 #[inline]
833 pub fn start(&self) -> ShardBoundary {
834 ShardBoundary {
835 timestamp: self.timestamp_range.0,
836 initialized_address: self.initialized_address_range.0,
837 finalized_address: self.finalized_address_range.0,
838 initialized_page_index: self.initialized_page_index_range.0,
839 finalized_page_index: self.finalized_page_index_range.0,
840 deferred_proof: self.deferred_proof_range.0,
841 }
842 }
843
844 #[must_use]
846 #[inline]
847 pub fn end(&self) -> ShardBoundary {
848 ShardBoundary {
849 timestamp: self.timestamp_range.1,
850 initialized_address: self.initialized_address_range.1,
851 finalized_address: self.finalized_address_range.1,
852 initialized_page_index: self.initialized_page_index_range.1,
853 finalized_page_index: self.finalized_page_index_range.1,
854 deferred_proof: self.deferred_proof_range.1,
855 }
856 }
857
858 #[must_use]
863 #[inline]
864 pub fn precompile() -> Self {
865 Self {
866 timestamp_range: (1, 1),
867 initialized_address_range: (0, 0),
868 finalized_address_range: (0, 0),
869 initialized_page_index_range: (0, 0),
870 finalized_page_index_range: (0, 0),
871 deferred_proof_range: (0, 0),
872 }
873 }
874
875 #[must_use]
879 #[inline]
880 pub fn deferred(prev_deferred_proof: u64, deferred_proof: u64) -> Self {
881 ShardRange {
882 timestamp_range: (1, 1),
883 initialized_address_range: (0, 0),
884 finalized_address_range: (0, 0),
885 initialized_page_index_range: (0, 0),
886 finalized_page_index_range: (0, 0),
887 deferred_proof_range: (prev_deferred_proof, deferred_proof),
888 }
889 }
890}
891
892impl core::fmt::Display for ShardRange {
893 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
894 write!(f, "ShardRange:")?;
895 write!(f, "timestamp_range: {}..{}", self.timestamp_range.0, self.timestamp_range.1)?;
896 write!(
897 f,
898 "initialized_address_range: {}..{}",
899 self.initialized_address_range.0, self.initialized_address_range.1
900 )?;
901 write!(
902 f,
903 "finalized_address_range: {}..{}",
904 self.finalized_address_range.0, self.finalized_address_range.1
905 )?;
906 write!(
907 f,
908 "initialized_page_index_range: {}..{}",
909 self.initialized_page_index_range.0, self.initialized_page_index_range.1
910 )?;
911 write!(
912 f,
913 "finalized_page_index_range: {}..{}",
914 self.finalized_page_index_range.0, self.finalized_page_index_range.1
915 )?;
916 Ok(())
917 }
918}
919
920#[cfg(test)]
921mod tests {
922 use crate::air::public_values;
923
924 #[test]
926 fn test_public_values_digest_num_words_consistency_zkvm() {
927 assert_eq!(public_values::PV_DIGEST_NUM_WORDS, sp1_zkvm::PV_DIGEST_NUM_WORDS);
928 }
929}