Skip to main content

sp1_recursion_executor/
public_values.rs

1use crate::DIGEST_SIZE;
2use core::fmt::Debug;
3use serde::{Deserialize, Serialize};
4use slop_algebra::PrimeField32;
5use sp1_derive::AlignedBorrow;
6use sp1_hypercube::{
7    air::{timestamp_from_limbs, ShardRange, POSEIDON_NUM_WORDS, PROOF_NONCE_NUM_WORDS},
8    indices_arr,
9    septic_digest::SepticDigest,
10    PROOF_MAX_NUM_PVS,
11};
12use static_assertions::const_assert_eq;
13use std::{
14    borrow::BorrowMut,
15    mem::{size_of, transmute, MaybeUninit},
16};
17
18pub const PV_DIGEST_NUM_WORDS: usize = 8;
19
20pub const RECURSIVE_PROOF_NUM_PV_ELTS: usize = size_of::<RecursionPublicValues<u8>>();
21
22const fn make_col_map() -> RecursionPublicValues<usize> {
23    let indices_arr = indices_arr::<RECURSIVE_PROOF_NUM_PV_ELTS>();
24    unsafe {
25        transmute::<[usize; RECURSIVE_PROOF_NUM_PV_ELTS], RecursionPublicValues<usize>>(indices_arr)
26    }
27}
28
29pub const RECURSION_PUBLIC_VALUES_COL_MAP: RecursionPublicValues<usize> = make_col_map();
30
31// All the fields before `digest` are hashed to produce the digest.
32pub const NUM_PV_ELMS_TO_HASH: usize = RECURSION_PUBLIC_VALUES_COL_MAP.digest[0];
33
34// Recursive proof has more public values than core proof, so the max number constant defined in
35// sp1_core should be set to `RECURSIVE_PROOF_NUM_PV_ELTS`.
36const_assert_eq!(RECURSIVE_PROOF_NUM_PV_ELTS, PROOF_MAX_NUM_PVS);
37
38/// The PublicValues struct is used to store all of a recursion proof's public values.
39#[derive(AlignedBorrow, Serialize, Deserialize, Clone, Copy, Default, Debug)]
40#[repr(C)]
41pub struct RecursionPublicValues<T> {
42    /// The `committed_value_digest` before this shard.
43    pub prev_committed_value_digest: [[T; 4]; PV_DIGEST_NUM_WORDS],
44
45    /// The hash of all the bytes that the program has written to public values.
46    pub committed_value_digest: [[T; 4]; PV_DIGEST_NUM_WORDS],
47
48    /// The `deferred_proofs_digest` before this shard.
49    pub prev_deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
50
51    /// The hash of all deferred proofs that have been witnessed in the VM.
52    pub deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
53
54    /// The deferred proof index before this shard.
55    pub prev_deferred_proof: T,
56
57    /// The deferred proof index after this shard.
58    pub deferred_proof: T,
59
60    /// The start pc of shards being proven.
61    pub pc_start: [T; 3],
62
63    /// The expected start pc for the next shard.
64    pub next_pc: [T; 3],
65
66    /// The initial timestamp.
67    pub initial_timestamp: [T; 4],
68
69    /// The last timestamp.
70    pub last_timestamp: [T; 4],
71
72    /// Previous MemoryInit address.
73    pub previous_init_addr: [T; 3],
74
75    /// Last MemoryInit address.
76    pub last_init_addr: [T; 3],
77
78    /// Previous MemoryFinalize address.
79    pub previous_finalize_addr: [T; 3],
80
81    /// Last MemoryFinalize address.
82    pub last_finalize_addr: [T; 3],
83
84    /// Previous PageProtInit page index.
85    pub previous_init_page_idx: [T; 3],
86
87    /// Last PageProtInit page index.
88    pub last_init_page_idx: [T; 3],
89
90    /// Previous PageProtFinalize page index.
91    pub previous_finalize_page_idx: [T; 3],
92
93    /// Last PageProtFinalize page index.
94    pub last_finalize_page_idx: [T; 3],
95
96    /// Start state of reconstruct_deferred_digest.
97    pub start_reconstruct_deferred_digest: [T; POSEIDON_NUM_WORDS],
98
99    /// End state of reconstruct_deferred_digest.
100    pub end_reconstruct_deferred_digest: [T; POSEIDON_NUM_WORDS],
101
102    /// The commitment to the sp1 program being proven.
103    pub sp1_vk_digest: [T; DIGEST_SIZE],
104
105    /// The root of the vk merkle tree.
106    pub vk_root: [T; DIGEST_SIZE],
107
108    /// Current cumulative sum of lookup bus. Note that for recursive proofs for core proofs, this
109    /// contains the global cumulative sum.  
110    pub global_cumulative_sum: SepticDigest<T>,
111
112    /// Whether or not the first shard is inside the compress proof.
113    pub contains_first_shard: T,
114
115    /// The total number of included core shards inside the compress proof.
116    pub num_included_shard: T,
117
118    /// Whether the proof completely proves the program execution.
119    pub is_complete: T,
120
121    /// The expected exit code of the program before this shard.
122    pub prev_exit_code: T,
123
124    /// The expected exit code of the program up to this shard.
125    pub exit_code: T,
126
127    /// The `commit_syscall` value of the previous shard.
128    pub prev_commit_syscall: T,
129
130    /// Whether `COMMIT` syscall has been called up to this shard.
131    pub commit_syscall: T,
132
133    /// The `commit_deferred_syscall` value of the previous shard.
134    pub prev_commit_deferred_syscall: T,
135
136    /// Whether `COMMIT_DEFERRED` syscall has been called up to this shard.
137    pub commit_deferred_syscall: T,
138
139    /// The digest of all the previous public values elements.
140    pub digest: [T; DIGEST_SIZE],
141
142    /// The nonce used for this proof.
143    pub proof_nonce: [T; PROOF_NONCE_NUM_WORDS],
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    pub fn range(&self) -> ShardRange
158    where
159        F: PrimeField32,
160    {
161        let initial_timestamp = timestamp_from_limbs(&self.initial_timestamp);
162        let last_timestamp = timestamp_from_limbs(&self.last_timestamp);
163        let previous_init_addr = self
164            .previous_init_addr
165            .iter()
166            .rev()
167            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
168        let last_init_addr = self
169            .last_init_addr
170            .iter()
171            .rev()
172            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
173        let previous_finalize_addr = self
174            .previous_finalize_addr
175            .iter()
176            .rev()
177            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
178        let last_finalize_addr = self
179            .last_finalize_addr
180            .iter()
181            .rev()
182            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
183        let previous_init_page_idx = self
184            .previous_init_page_idx
185            .iter()
186            .rev()
187            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
188        let last_init_page_idx = self
189            .last_init_page_idx
190            .iter()
191            .rev()
192            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
193        let previous_finalize_page_idx = self
194            .previous_finalize_page_idx
195            .iter()
196            .rev()
197            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
198        let last_finalize_page_idx = self
199            .last_finalize_page_idx
200            .iter()
201            .rev()
202            .fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
203
204        let prev_deferred_proof = self.prev_deferred_proof.as_canonical_u64();
205        let deferred_proof = self.deferred_proof.as_canonical_u64();
206
207        ShardRange {
208            timestamp_range: (initial_timestamp, last_timestamp),
209            initialized_address_range: (previous_init_addr, last_init_addr),
210            finalized_address_range: (previous_finalize_addr, last_finalize_addr),
211            initialized_page_index_range: (previous_init_page_idx, last_init_page_idx),
212            finalized_page_index_range: (previous_finalize_page_idx, last_finalize_page_idx),
213            deferred_proof_range: (prev_deferred_proof, deferred_proof),
214        }
215    }
216}
217
218impl<T: Copy> IntoIterator for RecursionPublicValues<T> {
219    type Item = T;
220    type IntoIter = std::array::IntoIter<T, RECURSIVE_PROOF_NUM_PV_ELTS>;
221
222    fn into_iter(self) -> Self::IntoIter {
223        self.as_array().into_iter()
224    }
225}