sp1_recursion_core/air/
public_values.rs

1use crate::runtime::{DIGEST_SIZE, HASH_RATE, PERMUTATION_WIDTH};
2
3use core::fmt::Debug;
4use p3_challenger::DuplexChallenger;
5use p3_field::PrimeField32;
6use p3_symmetric::CryptographicPermutation;
7use serde::{Deserialize, Serialize};
8use sp1_core_machine::utils::indices_arr;
9use sp1_derive::AlignedBorrow;
10use sp1_stark::{air::POSEIDON_NUM_WORDS, septic_digest::SepticDigest, Word, PROOF_MAX_NUM_PVS};
11use static_assertions::const_assert_eq;
12use std::{
13    borrow::BorrowMut,
14    mem::{size_of, transmute, MaybeUninit},
15};
16
17pub const PV_DIGEST_NUM_WORDS: usize = 8;
18
19pub const CHALLENGER_STATE_NUM_ELTS: usize = size_of::<ChallengerPublicValues<u8>>();
20
21pub const RECURSIVE_PROOF_NUM_PV_ELTS: usize = size_of::<RecursionPublicValues<u8>>();
22
23const fn make_col_map() -> RecursionPublicValues<usize> {
24    let indices_arr = indices_arr::<RECURSIVE_PROOF_NUM_PV_ELTS>();
25    unsafe {
26        transmute::<[usize; RECURSIVE_PROOF_NUM_PV_ELTS], RecursionPublicValues<usize>>(indices_arr)
27    }
28}
29
30pub const RECURSION_PUBLIC_VALUES_COL_MAP: RecursionPublicValues<usize> = make_col_map();
31
32// All the fields before `digest` are hashed to produce the digest.
33pub const NUM_PV_ELMS_TO_HASH: usize = RECURSION_PUBLIC_VALUES_COL_MAP.digest[0];
34
35// Recursive proof has more public values than core proof, so the max number constant defined in
36// sp1_core should be set to `RECURSIVE_PROOF_NUM_PV_ELTS`.
37const_assert_eq!(RECURSIVE_PROOF_NUM_PV_ELTS, PROOF_MAX_NUM_PVS);
38
39#[derive(AlignedBorrow, Serialize, Deserialize, Clone, Copy, Default, Debug)]
40#[repr(C)]
41pub struct ChallengerPublicValues<T> {
42    pub sponge_state: [T; PERMUTATION_WIDTH],
43    pub num_inputs: T,
44    pub input_buffer: [T; PERMUTATION_WIDTH],
45    pub num_outputs: T,
46    pub output_buffer: [T; PERMUTATION_WIDTH],
47}
48
49impl<T: Clone> ChallengerPublicValues<T> {
50    pub fn set_challenger<P: CryptographicPermutation<[T; PERMUTATION_WIDTH]>>(
51        &self,
52        challenger: &mut DuplexChallenger<T, P, PERMUTATION_WIDTH, HASH_RATE>,
53    ) where
54        T: PrimeField32,
55    {
56        challenger.sponge_state = self.sponge_state;
57        let num_inputs = self.num_inputs.as_canonical_u32() as usize;
58        challenger.input_buffer = self.input_buffer[..num_inputs].to_vec();
59        let num_outputs = self.num_outputs.as_canonical_u32() as usize;
60        challenger.output_buffer = self.output_buffer[..num_outputs].to_vec();
61    }
62
63    pub fn as_array(&self) -> [T; CHALLENGER_STATE_NUM_ELTS]
64    where
65        T: Copy,
66    {
67        unsafe {
68            let mut ret = [MaybeUninit::<T>::zeroed().assume_init(); CHALLENGER_STATE_NUM_ELTS];
69            let pv: &mut ChallengerPublicValues<T> = ret.as_mut_slice().borrow_mut();
70            *pv = *self;
71            ret
72        }
73    }
74}
75
76/// The PublicValues struct is used to store all of a reduce proof's public values.
77#[derive(AlignedBorrow, Serialize, Deserialize, Clone, Copy, Default, Debug)]
78#[repr(C)]
79pub struct RecursionPublicValues<T> {
80    /// The hash of all the bytes that the program has written to public values.
81    pub committed_value_digest: [Word<T>; PV_DIGEST_NUM_WORDS],
82
83    /// The hash of all deferred proofs that have been witnessed in the VM.
84    pub deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
85
86    /// The start pc of shards being proven.
87    pub start_pc: T,
88
89    /// The expected start pc for the next shard.
90    pub next_pc: T,
91
92    /// First shard being proven.
93    pub start_shard: T,
94
95    /// Next shard that should be proven.
96    pub next_shard: T,
97
98    /// First execution shard being proven.
99    pub start_execution_shard: T,
100
101    /// Next execution shard that should be proven.
102    pub next_execution_shard: T,
103
104    /// Previous MemoryInit address bits.
105    pub previous_init_addr_bits: [T; 32],
106
107    /// Last MemoryInit address bits.
108    pub last_init_addr_bits: [T; 32],
109
110    /// Previous MemoryFinalize address bits.
111    pub previous_finalize_addr_bits: [T; 32],
112
113    /// Last MemoryFinalize address bits.
114    pub last_finalize_addr_bits: [T; 32],
115
116    /// Start state of reconstruct_deferred_digest.
117    pub start_reconstruct_deferred_digest: [T; POSEIDON_NUM_WORDS],
118
119    /// End state of reconstruct_deferred_digest.
120    pub end_reconstruct_deferred_digest: [T; POSEIDON_NUM_WORDS],
121
122    /// The commitment to the sp1 program being proven.
123    pub sp1_vk_digest: [T; DIGEST_SIZE],
124
125    /// The root of the vk merkle tree.
126    pub vk_root: [T; DIGEST_SIZE],
127
128    /// Current cumulative sum of lookup bus. Note that for recursive proofs for core proofs, this
129    /// contains the global cumulative sum.  
130    pub global_cumulative_sum: SepticDigest<T>,
131
132    /// Whether the proof completely proves the program execution.
133    pub is_complete: T,
134
135    /// Whether the proof represents a collection of shards which contain at least one execution
136    /// shard, i.e. a shard that contains the `cpu` chip.
137    pub contains_execution_shard: T,
138
139    /// The exit code of the program.
140    pub exit_code: T,
141
142    /// The digest of all the previous public values elements.
143    pub digest: [T; DIGEST_SIZE],
144}
145
146/// Converts the public values to an array of elements.
147impl<F: Copy> RecursionPublicValues<F> {
148    pub fn as_array(&self) -> [F; RECURSIVE_PROOF_NUM_PV_ELTS] {
149        unsafe {
150            let mut ret = [MaybeUninit::<F>::zeroed().assume_init(); RECURSIVE_PROOF_NUM_PV_ELTS];
151            let pv: &mut RecursionPublicValues<F> = ret.as_mut_slice().borrow_mut();
152            *pv = *self;
153            ret
154        }
155    }
156}
157
158impl<T: Copy> IntoIterator for RecursionPublicValues<T> {
159    type Item = T;
160    type IntoIter = std::array::IntoIter<T, RECURSIVE_PROOF_NUM_PV_ELTS>;
161
162    fn into_iter(self) -> Self::IntoIter {
163        self.as_array().into_iter()
164    }
165}
166
167impl<T: Copy> IntoIterator for ChallengerPublicValues<T> {
168    type Item = T;
169    type IntoIter = std::array::IntoIter<T, CHALLENGER_STATE_NUM_ELTS>;
170
171    fn into_iter(self) -> Self::IntoIter {
172        self.as_array().into_iter()
173    }
174}