use crate::DIGEST_SIZE;
use core::fmt::Debug;
use serde::{Deserialize, Serialize};
use slop_algebra::PrimeField32;
use sp1_derive::AlignedBorrow;
use sp1_hypercube::{
air::{timestamp_from_limbs, ShardRange, POSEIDON_NUM_WORDS, PROOF_NONCE_NUM_WORDS},
indices_arr,
septic_digest::SepticDigest,
PROOF_MAX_NUM_PVS,
};
use static_assertions::const_assert_eq;
use std::{
borrow::BorrowMut,
mem::{size_of, transmute, MaybeUninit},
};
pub const PV_DIGEST_NUM_WORDS: usize = 8;
pub const RECURSIVE_PROOF_NUM_PV_ELTS: usize = size_of::<RecursionPublicValues<u8>>();
const fn make_col_map() -> RecursionPublicValues<usize> {
let indices_arr = indices_arr::<RECURSIVE_PROOF_NUM_PV_ELTS>();
unsafe {
transmute::<[usize; RECURSIVE_PROOF_NUM_PV_ELTS], RecursionPublicValues<usize>>(indices_arr)
}
}
pub const RECURSION_PUBLIC_VALUES_COL_MAP: RecursionPublicValues<usize> = make_col_map();
pub const NUM_PV_ELMS_TO_HASH: usize = RECURSION_PUBLIC_VALUES_COL_MAP.digest[0];
const_assert_eq!(RECURSIVE_PROOF_NUM_PV_ELTS, PROOF_MAX_NUM_PVS);
#[derive(AlignedBorrow, Serialize, Deserialize, Clone, Copy, Default, Debug)]
#[repr(C)]
pub struct RecursionPublicValues<T> {
pub prev_committed_value_digest: [[T; 4]; PV_DIGEST_NUM_WORDS],
pub committed_value_digest: [[T; 4]; PV_DIGEST_NUM_WORDS],
pub prev_deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
pub deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
pub prev_deferred_proof: T,
pub deferred_proof: T,
pub pc_start: [T; 3],
pub next_pc: [T; 3],
pub initial_timestamp: [T; 4],
pub last_timestamp: [T; 4],
pub previous_init_addr: [T; 3],
pub last_init_addr: [T; 3],
pub previous_finalize_addr: [T; 3],
pub last_finalize_addr: [T; 3],
pub previous_init_page_idx: [T; 3],
pub last_init_page_idx: [T; 3],
pub previous_finalize_page_idx: [T; 3],
pub last_finalize_page_idx: [T; 3],
pub start_reconstruct_deferred_digest: [T; POSEIDON_NUM_WORDS],
pub end_reconstruct_deferred_digest: [T; POSEIDON_NUM_WORDS],
pub sp1_vk_digest: [T; DIGEST_SIZE],
pub vk_root: [T; DIGEST_SIZE],
pub global_cumulative_sum: SepticDigest<T>,
pub contains_first_shard: T,
pub num_included_shard: T,
pub is_complete: T,
pub prev_exit_code: T,
pub exit_code: T,
pub prev_commit_syscall: T,
pub commit_syscall: T,
pub prev_commit_deferred_syscall: T,
pub commit_deferred_syscall: T,
pub digest: [T; DIGEST_SIZE],
pub proof_nonce: [T; PROOF_NONCE_NUM_WORDS],
}
impl<F: Copy> RecursionPublicValues<F> {
pub fn as_array(&self) -> [F; RECURSIVE_PROOF_NUM_PV_ELTS] {
unsafe {
let mut ret = [MaybeUninit::<F>::zeroed().assume_init(); RECURSIVE_PROOF_NUM_PV_ELTS];
let pv: &mut RecursionPublicValues<F> = ret.as_mut_slice().borrow_mut();
*pv = *self;
ret
}
}
pub fn range(&self) -> ShardRange
where
F: PrimeField32,
{
let initial_timestamp = timestamp_from_limbs(&self.initial_timestamp);
let last_timestamp = timestamp_from_limbs(&self.last_timestamp);
let previous_init_addr = self
.previous_init_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let last_init_addr = self
.last_init_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let previous_finalize_addr = self
.previous_finalize_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let last_finalize_addr = self
.last_finalize_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let previous_init_page_idx = self
.previous_init_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let last_init_page_idx = self
.last_init_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let previous_finalize_page_idx = self
.previous_finalize_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let last_finalize_page_idx = self
.last_finalize_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64);
let prev_deferred_proof = self.prev_deferred_proof.as_canonical_u64();
let deferred_proof = self.deferred_proof.as_canonical_u64();
ShardRange {
timestamp_range: (initial_timestamp, last_timestamp),
initialized_address_range: (previous_init_addr, last_init_addr),
finalized_address_range: (previous_finalize_addr, last_finalize_addr),
initialized_page_index_range: (previous_init_page_idx, last_init_page_idx),
finalized_page_index_range: (previous_finalize_page_idx, last_finalize_page_idx),
deferred_proof_range: (prev_deferred_proof, deferred_proof),
}
}
}
impl<T: Copy> IntoIterator for RecursionPublicValues<T> {
type Item = T;
type IntoIter = std::array::IntoIter<T, RECURSIVE_PROOF_NUM_PV_ELTS>;
fn into_iter(self) -> Self::IntoIter {
self.as_array().into_iter()
}
}