use core::{fmt::Debug, mem::size_of};
use std::{
borrow::{Borrow, BorrowMut},
ops::Range,
};
use deepsize2::DeepSizeOf;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use slop_algebra::{AbstractField, PrimeField32};
use sp1_primitives::consts::split_page_idx;
use crate::{septic_curve::SepticCurve, septic_digest::SepticDigest, PROOF_MAX_NUM_PVS};
#[cfg(feature = "mprotect")]
use crate::addr_to_limbs;
pub const SP1_PROOF_NUM_PV_ELTS: usize = size_of::<PublicValues<[u8; 4], [u8; 3], [u8; 4], u8>>();
pub const PV_DIGEST_NUM_WORDS: usize = 8;
pub const POSEIDON_NUM_WORDS: usize = 8;
pub const PROOF_NONCE_NUM_WORDS: usize = 4;
#[derive(Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq, DeepSizeOf)]
#[repr(C)]
pub struct PublicValues<W1, W2, W3, T> {
pub prev_committed_value_digest: [W1; PV_DIGEST_NUM_WORDS],
pub committed_value_digest: [W1; PV_DIGEST_NUM_WORDS],
pub prev_deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
pub deferred_proofs_digest: [T; POSEIDON_NUM_WORDS],
pub pc_start: W2,
pub next_pc: W2,
pub prev_exit_code: T,
pub exit_code: T,
pub is_execution_shard: T,
pub previous_init_addr: W2,
pub last_init_addr: W2,
pub previous_finalize_addr: W2,
pub last_finalize_addr: W2,
pub previous_init_page_idx: W2,
pub last_init_page_idx: W2,
pub previous_finalize_page_idx: W2,
pub last_finalize_page_idx: W2,
pub initial_timestamp: W3,
pub last_timestamp: W3,
pub is_timestamp_high_eq: T,
pub inv_timestamp_high: T,
pub is_timestamp_low_eq: T,
pub inv_timestamp_low: T,
pub global_init_count: T,
pub global_finalize_count: T,
pub global_page_prot_init_count: T,
pub global_page_prot_finalize_count: T,
pub global_count: T,
pub global_cumulative_sum: SepticDigest<T>,
pub prev_commit_syscall: T,
pub commit_syscall: T,
pub prev_commit_deferred_syscall: T,
pub commit_deferred_syscall: T,
pub initial_timestamp_inv: T,
pub last_timestamp_inv: T,
pub is_first_execution_shard: T,
pub is_untrusted_programs_enabled: T,
#[cfg(feature = "mprotect")]
pub enable_trap_handler: T,
#[cfg(feature = "mprotect")]
pub trap_context: [W2; 3],
#[cfg(feature = "mprotect")]
pub untrusted_memory: [W2; 2],
pub proof_nonce: [T; PROOF_NONCE_NUM_WORDS],
pub empty: [T; 4],
}
impl PublicValues<u32, u64, u64, u32> {
#[must_use]
pub fn to_vec<F: AbstractField>(&self) -> Vec<F> {
let mut ret = vec![F::zero(); PROOF_MAX_NUM_PVS];
let field_values = PublicValues::<[F; 4], [F; 3], [F; 4], F>::from(*self);
let ret_ref_mut: &mut PublicValues<[F; 4], [F; 3], [F; 4], F> =
ret.as_mut_slice().borrow_mut();
*ret_ref_mut = field_values;
ret
}
#[must_use]
pub fn range(&self) -> ShardRange {
ShardRange {
timestamp_range: (self.initial_timestamp, self.last_timestamp),
initialized_address_range: (self.previous_init_addr, self.last_init_addr),
finalized_address_range: (self.previous_finalize_addr, self.last_finalize_addr),
initialized_page_index_range: (self.previous_init_page_idx, self.last_init_page_idx),
finalized_page_index_range: (
self.previous_finalize_page_idx,
self.last_finalize_page_idx,
),
deferred_proof_range: (0, 0),
}
}
#[must_use]
pub fn reset(&self) -> Self {
let mut copy = *self;
copy.pc_start = 0;
copy.next_pc = 0;
copy.previous_init_addr = 0;
copy.last_init_addr = 0;
copy.previous_finalize_addr = 0;
copy.last_finalize_addr = 0;
copy.previous_init_page_idx = 0;
copy.last_init_page_idx = 0;
copy.previous_finalize_page_idx = 0;
copy.last_finalize_page_idx = 0;
copy
}
#[must_use]
#[cfg_attr(not(feature = "mprotect"), allow(unused_variables))]
pub fn initialize(
&self,
pc_start_abs: u64,
enable_untrusted_programs: bool,
trap_context: Option<u64>,
untrusted_memory: Option<(u64, u64)>,
) -> Self {
let mut state = *self;
state.pc_start = pc_start_abs;
state.next_pc = pc_start_abs;
state.initial_timestamp = 1;
state.last_timestamp = 1;
state.is_timestamp_high_eq = 1;
state.is_timestamp_low_eq = 1;
state.is_first_execution_shard = 0;
state.is_execution_shard = 0;
state.initial_timestamp_inv = 0;
state.last_timestamp_inv = 0;
state.is_untrusted_programs_enabled = enable_untrusted_programs as u32;
#[cfg(feature = "mprotect")]
{
state.enable_trap_handler = trap_context.is_some() as u32;
state.trap_context = trap_context.map_or([0, 0, 0], |addr| [addr, addr + 8, addr + 16]);
state.untrusted_memory = untrusted_memory.map_or([0, 0], |(start, end)| [start, end]);
}
state
}
pub fn update_state(&mut self, state: &PublicValues<u32, u64, u64, u32>) {
self.pc_start = state.pc_start;
self.next_pc = state.next_pc;
self.exit_code = state.exit_code;
self.initial_timestamp = state.initial_timestamp;
self.last_timestamp = state.last_timestamp;
self.is_timestamp_high_eq = state.is_timestamp_high_eq;
self.is_timestamp_low_eq = state.is_timestamp_low_eq;
self.last_timestamp_inv = state.last_timestamp_inv;
self.initial_timestamp_inv = state.initial_timestamp_inv;
self.is_first_execution_shard = state.is_first_execution_shard;
self.is_execution_shard = state.is_execution_shard;
self.is_untrusted_programs_enabled = state.is_untrusted_programs_enabled;
#[cfg(feature = "mprotect")]
{
self.enable_trap_handler = state.enable_trap_handler;
self.trap_context = state.trap_context;
self.untrusted_memory = state.untrusted_memory;
}
}
#[cfg_attr(not(feature = "mprotect"), allow(unused_variables))]
pub fn update_initialized_state(
&mut self,
pc_start_abs: u64,
enable_untrusted_programs: bool,
trap_context: Option<u64>,
untrusted_memory: Option<(u64, u64)>,
) {
self.pc_start = pc_start_abs;
self.next_pc = pc_start_abs;
self.exit_code = 0;
self.initial_timestamp = 1;
self.last_timestamp = 1;
self.is_timestamp_high_eq = 1;
self.is_timestamp_low_eq = 1;
self.is_first_execution_shard = 0;
self.is_execution_shard = 0;
self.initial_timestamp_inv = 0;
self.last_timestamp_inv = 0;
self.is_untrusted_programs_enabled = enable_untrusted_programs as u32;
#[cfg(feature = "mprotect")]
{
self.enable_trap_handler = trap_context.is_some() as u32;
self.trap_context = trap_context.map_or([0, 0, 0], |addr| [addr, addr + 8, addr + 16]);
self.untrusted_memory = untrusted_memory.map_or([0, 0], |(start, end)| [start, end]);
}
}
#[allow(clippy::too_many_arguments)]
#[cfg_attr(not(feature = "mprotect"), allow(unused_variables))]
pub fn update_finalized_state(
&mut self,
timestamp: u64,
pc: u64,
exit_code: u32,
is_untrusted_programs_enabled: u32,
enable_trap_handler: u32,
trap_context: [u64; 3],
untrusted_memory: [u64; 2],
committed_value_digest: [u32; PV_DIGEST_NUM_WORDS],
deferred_proofs_digest: [u32; POSEIDON_NUM_WORDS],
nonce: [u32; PROOF_NONCE_NUM_WORDS],
) {
self.pc_start = pc;
self.next_pc = pc;
self.exit_code = exit_code;
self.initial_timestamp = timestamp;
self.last_timestamp = timestamp;
self.is_timestamp_high_eq = 1;
self.is_timestamp_low_eq = 1;
self.is_first_execution_shard = 0;
self.is_execution_shard = 0;
self.initial_timestamp_inv = 0;
self.last_timestamp_inv = 0;
self.prev_committed_value_digest = committed_value_digest;
self.committed_value_digest = committed_value_digest;
self.prev_deferred_proofs_digest = deferred_proofs_digest;
self.deferred_proofs_digest = deferred_proofs_digest;
self.is_untrusted_programs_enabled = is_untrusted_programs_enabled;
#[cfg(feature = "mprotect")]
{
self.enable_trap_handler = enable_trap_handler;
self.trap_context = trap_context;
self.untrusted_memory = untrusted_memory;
}
self.prev_exit_code = exit_code;
self.prev_commit_syscall = 1;
self.commit_syscall = 1;
self.prev_commit_deferred_syscall = 1;
self.commit_deferred_syscall = 1;
self.proof_nonce = nonce;
}
pub fn update_finalized_state_from_public_values(
&mut self,
public_values: &PublicValues<u32, u64, u64, u32>,
) {
#[cfg(feature = "mprotect")]
let (enable_trap_handler, trap_context, untrusted_memory) = (
public_values.enable_trap_handler,
public_values.trap_context,
public_values.untrusted_memory,
);
#[cfg(not(feature = "mprotect"))]
let (enable_trap_handler, trap_context, untrusted_memory) = (0, [0, 0, 0], [0, 0]);
self.update_finalized_state(
public_values.last_timestamp,
public_values.next_pc,
public_values.exit_code,
public_values.is_untrusted_programs_enabled,
enable_trap_handler,
trap_context,
untrusted_memory,
public_values.committed_value_digest,
public_values.deferred_proofs_digest,
public_values.proof_nonce,
);
}
}
#[inline]
pub fn timestamp_from_limbs<F: PrimeField32>(limbs: &[F; 4]) -> u64 {
let mut timestamp = (limbs[0].as_canonical_u32() as u64) << 32;
timestamp += (limbs[1].as_canonical_u32() as u64) << 24;
timestamp += (limbs[2].as_canonical_u32() as u64) << 16;
timestamp += limbs[3].as_canonical_u32() as u64;
timestamp
}
pub type SP1CorePublicValues<F> = PublicValues<[F; 4], [F; 3], [F; 4], F>;
impl<F: PrimeField32> PublicValues<[F; 4], [F; 3], [F; 4], F> {
pub fn commit_digest_bytes(&self) -> Vec<u8> {
self.committed_value_digest
.iter()
.flat_map(|w| w.iter().map(|f| f.as_canonical_u32() as u8))
.collect_vec()
}
pub fn initial_timestamp(&self) -> u64 {
timestamp_from_limbs(&self.initial_timestamp)
}
pub fn last_timestamp(&self) -> u64 {
timestamp_from_limbs(&self.last_timestamp)
}
pub fn previous_init_addr(&self) -> u64 {
self.previous_init_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
pub fn last_init_addr(&self) -> u64 {
self.last_init_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
pub fn previous_finalize_addr(&self) -> u64 {
self.previous_finalize_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
pub fn last_finalize_addr(&self) -> u64 {
self.last_finalize_addr
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
pub fn previous_init_page_idx(&self) -> u64 {
self.previous_init_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
pub fn last_init_page_idx(&self) -> u64 {
self.last_init_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
pub fn previous_finalize_page_idx(&self) -> u64 {
self.previous_finalize_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
pub fn last_finalize_page_idx(&self) -> u64 {
self.last_finalize_page_idx
.iter()
.rev()
.fold(0, |acc, x| acc * (1 << 16) + x.as_canonical_u32() as u64)
}
#[must_use]
pub fn range(&self) -> ShardRange {
let timestamp_range = (self.initial_timestamp(), self.last_timestamp());
let initialized_address_range = (self.previous_init_addr(), self.last_init_addr());
let finalized_address_range = (self.previous_finalize_addr(), self.last_finalize_addr());
let initialized_page_index_range =
(self.previous_init_page_idx(), self.last_init_page_idx());
let finalized_page_index_range =
(self.previous_finalize_page_idx(), self.last_finalize_page_idx());
let deferred_proof_range = (0, 0);
ShardRange {
timestamp_range,
initialized_address_range,
finalized_address_range,
initialized_page_index_range,
finalized_page_index_range,
deferred_proof_range,
}
}
}
impl<T: Clone> Borrow<PublicValues<[T; 4], [T; 3], [T; 4], T>> for [T] {
fn borrow(&self) -> &PublicValues<[T; 4], [T; 3], [T; 4], T> {
let size = std::mem::size_of::<PublicValues<[u8; 4], [u8; 3], [u8; 4], u8>>();
debug_assert!(self.len() >= size);
let slice = &self[0..size];
let (prefix, shorts, _suffix) =
unsafe { slice.align_to::<PublicValues<[T; 4], [T; 3], [T; 4], T>>() };
debug_assert!(prefix.is_empty(), "Alignment should match");
debug_assert_eq!(shorts.len(), 1);
&shorts[0]
}
}
impl<T: Clone> BorrowMut<PublicValues<[T; 4], [T; 3], [T; 4], T>> for [T] {
fn borrow_mut(&mut self) -> &mut PublicValues<[T; 4], [T; 3], [T; 4], T> {
let size = std::mem::size_of::<PublicValues<[u8; 4], [u8; 3], [u8; 4], u8>>();
debug_assert!(self.len() >= size);
let slice = &mut self[0..size];
let (prefix, shorts, _suffix) =
unsafe { slice.align_to_mut::<PublicValues<[T; 4], [T; 3], [T; 4], T>>() };
debug_assert!(prefix.is_empty(), "Alignment should match");
debug_assert_eq!(shorts.len(), 1);
&mut shorts[0]
}
}
impl<F: AbstractField> From<PublicValues<u32, u64, u64, u32>>
for PublicValues<[F; 4], [F; 3], [F; 4], F>
{
#[allow(clippy::too_many_lines)]
fn from(value: PublicValues<u32, u64, u64, u32>) -> Self {
let PublicValues {
prev_committed_value_digest,
committed_value_digest,
prev_deferred_proofs_digest,
deferred_proofs_digest,
pc_start,
next_pc,
prev_exit_code,
exit_code,
is_execution_shard,
previous_init_addr,
last_init_addr,
previous_finalize_addr,
last_finalize_addr,
previous_init_page_idx,
last_init_page_idx,
previous_finalize_page_idx,
last_finalize_page_idx,
initial_timestamp,
last_timestamp,
is_timestamp_high_eq,
inv_timestamp_high,
is_timestamp_low_eq,
inv_timestamp_low,
global_init_count,
global_finalize_count,
global_page_prot_init_count,
global_page_prot_finalize_count,
global_count,
global_cumulative_sum,
prev_commit_syscall,
commit_syscall,
prev_commit_deferred_syscall,
commit_deferred_syscall,
is_untrusted_programs_enabled,
#[cfg(feature = "mprotect")]
enable_trap_handler,
#[cfg(feature = "mprotect")]
trap_context,
#[cfg(feature = "mprotect")]
untrusted_memory,
proof_nonce,
initial_timestamp_inv,
last_timestamp_inv,
is_first_execution_shard,
..
} = value;
let prev_committed_value_digest: [_; PV_DIGEST_NUM_WORDS] = core::array::from_fn(|i| {
[
F::from_canonical_u32(prev_committed_value_digest[i] & 0xFF),
F::from_canonical_u32((prev_committed_value_digest[i] >> 8) & 0xFF),
F::from_canonical_u32((prev_committed_value_digest[i] >> 16) & 0xFF),
F::from_canonical_u32((prev_committed_value_digest[i] >> 24) & 0xFF),
]
});
let committed_value_digest: [_; PV_DIGEST_NUM_WORDS] = core::array::from_fn(|i| {
[
F::from_canonical_u32(committed_value_digest[i] & 0xFF),
F::from_canonical_u32((committed_value_digest[i] >> 8) & 0xFF),
F::from_canonical_u32((committed_value_digest[i] >> 16) & 0xFF),
F::from_canonical_u32((committed_value_digest[i] >> 24) & 0xFF),
]
});
let prev_deferred_proofs_digest: [_; POSEIDON_NUM_WORDS] =
core::array::from_fn(|i| F::from_canonical_u32(prev_deferred_proofs_digest[i]));
let deferred_proofs_digest: [_; POSEIDON_NUM_WORDS] =
core::array::from_fn(|i| F::from_canonical_u32(deferred_proofs_digest[i]));
let pc_start = [
F::from_canonical_u16((pc_start & 0xFFFF) as u16),
F::from_canonical_u16(((pc_start >> 16) & 0xFFFF) as u16),
F::from_canonical_u16(((pc_start >> 32) & 0xFFFF) as u16),
];
let next_pc = [
F::from_canonical_u16((next_pc & 0xFFFF) as u16),
F::from_canonical_u16(((next_pc >> 16) & 0xFFFF) as u16),
F::from_canonical_u16(((next_pc >> 32) & 0xFFFF) as u16),
];
let exit_code = F::from_canonical_u32(exit_code);
let prev_exit_code = F::from_canonical_u32(prev_exit_code);
let is_execution_shard = F::from_canonical_u32(is_execution_shard);
let previous_init_addr = [
F::from_canonical_u16((previous_init_addr & 0xFFFF) as u16),
F::from_canonical_u16(((previous_init_addr >> 16) & 0xFFFF) as u16),
F::from_canonical_u16(((previous_init_addr >> 32) & 0xFFFF) as u16),
];
let last_init_addr = [
F::from_canonical_u16((last_init_addr & 0xFFFF) as u16),
F::from_canonical_u16(((last_init_addr >> 16) & 0xFFFF) as u16),
F::from_canonical_u16(((last_init_addr >> 32) & 0xFFFF) as u16),
];
let previous_finalize_addr = [
F::from_canonical_u16((previous_finalize_addr & 0xFFFF) as u16),
F::from_canonical_u16(((previous_finalize_addr >> 16) & 0xFFFF) as u16),
F::from_canonical_u16(((previous_finalize_addr >> 32) & 0xFFFF) as u16),
];
let last_finalize_addr = [
F::from_canonical_u16((last_finalize_addr & 0xFFFF) as u16),
F::from_canonical_u16(((last_finalize_addr >> 16) & 0xFFFF) as u16),
F::from_canonical_u16(((last_finalize_addr >> 32) & 0xFFFF) as u16),
];
let previous_init_page_idx: [F; 3] = core::array::from_fn(|i| {
F::from_canonical_u16(split_page_idx(previous_init_page_idx)[i])
});
let last_init_page_idx: [F; 3] =
core::array::from_fn(|i| F::from_canonical_u16(split_page_idx(last_init_page_idx)[i]));
let previous_finalize_page_idx: [F; 3] = core::array::from_fn(|i| {
F::from_canonical_u16(split_page_idx(previous_finalize_page_idx)[i])
});
let last_finalize_page_idx: [F; 3] = core::array::from_fn(|i| {
F::from_canonical_u16(split_page_idx(last_finalize_page_idx)[i])
});
let initial_timestamp = [
F::from_canonical_u16((initial_timestamp >> 32) as u16),
F::from_canonical_u8(((initial_timestamp >> 24) & 0xFF) as u8),
F::from_canonical_u8(((initial_timestamp >> 16) & 0xFF) as u8),
F::from_canonical_u16((initial_timestamp & 0xFFFF) as u16),
];
let last_timestamp = [
F::from_canonical_u16((last_timestamp >> 32) as u16),
F::from_canonical_u8(((last_timestamp >> 24) & 0xFF) as u8),
F::from_canonical_u8(((last_timestamp >> 16) & 0xFF) as u8),
F::from_canonical_u16((last_timestamp & 0xFFFF) as u16),
];
let is_timestamp_high_eq = F::from_canonical_u32(is_timestamp_high_eq);
let inv_timestamp_high = F::from_canonical_u32(inv_timestamp_high);
let is_timestamp_low_eq = F::from_canonical_u32(is_timestamp_low_eq);
let inv_timestamp_low = F::from_canonical_u32(inv_timestamp_low);
let global_init_count = F::from_canonical_u32(global_init_count);
let global_finalize_count = F::from_canonical_u32(global_finalize_count);
let global_page_prot_init_count = F::from_canonical_u32(global_page_prot_init_count);
let global_page_prot_finalize_count =
F::from_canonical_u32(global_page_prot_finalize_count);
let global_count = F::from_canonical_u32(global_count);
let global_cumulative_sum =
SepticDigest(SepticCurve::convert(global_cumulative_sum.0, F::from_canonical_u32));
let prev_commit_syscall = F::from_canonical_u32(prev_commit_syscall);
let commit_syscall = F::from_canonical_u32(commit_syscall);
let prev_commit_deferred_syscall = F::from_canonical_u32(prev_commit_deferred_syscall);
let commit_deferred_syscall = F::from_canonical_u32(commit_deferred_syscall);
let initial_timestamp_inv = F::from_canonical_u32(initial_timestamp_inv);
let last_timestamp_inv = F::from_canonical_u32(last_timestamp_inv);
let is_first_execution_shard = F::from_canonical_u32(is_first_execution_shard);
let is_untrusted_programs_enabled = F::from_canonical_u32(is_untrusted_programs_enabled);
#[cfg(feature = "mprotect")]
let enable_trap_handler = F::from_canonical_u32(enable_trap_handler);
#[cfg(feature = "mprotect")]
let trap_context = [
addr_to_limbs::<F>(trap_context[0]),
addr_to_limbs::<F>(trap_context[1]),
addr_to_limbs::<F>(trap_context[2]),
];
#[cfg(feature = "mprotect")]
let untrusted_memory =
[addr_to_limbs::<F>(untrusted_memory[0]), addr_to_limbs::<F>(untrusted_memory[1])];
let proof_nonce: [_; PROOF_NONCE_NUM_WORDS] =
core::array::from_fn(|i| F::from_canonical_u32(proof_nonce[i]));
Self {
prev_committed_value_digest,
committed_value_digest,
prev_deferred_proofs_digest,
deferred_proofs_digest,
pc_start,
next_pc,
prev_exit_code,
exit_code,
is_execution_shard,
previous_init_addr,
last_init_addr,
previous_finalize_addr,
last_finalize_addr,
previous_init_page_idx,
last_init_page_idx,
previous_finalize_page_idx,
last_finalize_page_idx,
initial_timestamp,
last_timestamp,
is_timestamp_high_eq,
inv_timestamp_high,
is_timestamp_low_eq,
inv_timestamp_low,
global_init_count,
global_finalize_count,
global_page_prot_init_count,
global_page_prot_finalize_count,
global_count,
global_cumulative_sum,
prev_commit_syscall,
commit_syscall,
prev_commit_deferred_syscall,
commit_deferred_syscall,
is_untrusted_programs_enabled,
#[cfg(feature = "mprotect")]
enable_trap_handler,
#[cfg(feature = "mprotect")]
trap_context,
#[cfg(feature = "mprotect")]
untrusted_memory,
initial_timestamp_inv,
last_timestamp_inv,
is_first_execution_shard,
proof_nonce,
empty: core::array::from_fn(|_| F::zero()),
}
}
}
#[derive(
Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(C)]
pub struct ShardBoundary {
pub timestamp: u64,
pub initialized_address: u64,
pub finalized_address: u64,
pub initialized_page_index: u64,
pub finalized_page_index: u64,
pub deferred_proof: u64,
}
impl ShardBoundary {
#[inline]
#[must_use]
pub fn initial() -> Self {
Self {
timestamp: 1,
initialized_address: 0,
finalized_address: 0,
initialized_page_index: 0,
finalized_page_index: 0,
deferred_proof: 0,
}
}
}
#[derive(
Serialize, Deserialize, Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(C)]
pub struct ShardRange {
pub timestamp_range: (u64, u64),
pub initialized_address_range: (u64, u64),
pub finalized_address_range: (u64, u64),
pub initialized_page_index_range: (u64, u64),
pub finalized_page_index_range: (u64, u64),
pub deferred_proof_range: (u64, u64),
}
impl From<Range<ShardBoundary>> for ShardRange {
fn from(value: Range<ShardBoundary>) -> Self {
Self {
timestamp_range: (value.start.timestamp, value.end.timestamp),
initialized_address_range: (
value.start.initialized_address,
value.end.initialized_address,
),
finalized_address_range: (value.start.finalized_address, value.end.finalized_address),
initialized_page_index_range: (
value.start.initialized_page_index,
value.end.initialized_page_index,
),
finalized_page_index_range: (
value.start.finalized_page_index,
value.end.finalized_page_index,
),
deferred_proof_range: (value.start.deferred_proof, value.end.deferred_proof),
}
}
}
impl ShardRange {
#[must_use]
#[inline]
pub fn start(&self) -> ShardBoundary {
ShardBoundary {
timestamp: self.timestamp_range.0,
initialized_address: self.initialized_address_range.0,
finalized_address: self.finalized_address_range.0,
initialized_page_index: self.initialized_page_index_range.0,
finalized_page_index: self.finalized_page_index_range.0,
deferred_proof: self.deferred_proof_range.0,
}
}
#[must_use]
#[inline]
pub fn end(&self) -> ShardBoundary {
ShardBoundary {
timestamp: self.timestamp_range.1,
initialized_address: self.initialized_address_range.1,
finalized_address: self.finalized_address_range.1,
initialized_page_index: self.initialized_page_index_range.1,
finalized_page_index: self.finalized_page_index_range.1,
deferred_proof: self.deferred_proof_range.1,
}
}
#[must_use]
#[inline]
pub fn precompile() -> Self {
Self {
timestamp_range: (1, 1),
initialized_address_range: (0, 0),
finalized_address_range: (0, 0),
initialized_page_index_range: (0, 0),
finalized_page_index_range: (0, 0),
deferred_proof_range: (0, 0),
}
}
#[must_use]
#[inline]
pub fn deferred(prev_deferred_proof: u64, deferred_proof: u64) -> Self {
ShardRange {
timestamp_range: (1, 1),
initialized_address_range: (0, 0),
finalized_address_range: (0, 0),
initialized_page_index_range: (0, 0),
finalized_page_index_range: (0, 0),
deferred_proof_range: (prev_deferred_proof, deferred_proof),
}
}
}
impl core::fmt::Display for ShardRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ShardRange:")?;
write!(f, "timestamp_range: {}..{}", self.timestamp_range.0, self.timestamp_range.1)?;
write!(
f,
"initialized_address_range: {}..{}",
self.initialized_address_range.0, self.initialized_address_range.1
)?;
write!(
f,
"finalized_address_range: {}..{}",
self.finalized_address_range.0, self.finalized_address_range.1
)?;
write!(
f,
"initialized_page_index_range: {}..{}",
self.initialized_page_index_range.0, self.initialized_page_index_range.1
)?;
write!(
f,
"finalized_page_index_range: {}..{}",
self.finalized_page_index_range.0, self.finalized_page_index_range.1
)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::air::public_values;
#[test]
fn test_public_values_digest_num_words_consistency_zkvm() {
assert_eq!(public_values::PV_DIGEST_NUM_WORDS, sp1_zkvm::PV_DIGEST_NUM_WORDS);
}
}