use crate::{ProofOptions, TraceInfo, TraceLayout};
use core::cmp;
use fri::FriProof;
use math::log2;
use utils::{
collections::Vec, ByteReader, Deserializable, DeserializationError, Serializable, SliceReader,
};
mod context;
pub use context::Context;
mod commitments;
pub use commitments::Commitments;
mod queries;
pub use queries::Queries;
mod ood_frame;
pub use ood_frame::OodFrame;
mod table;
pub use table::Table;
const GRINDING_CONTRIBUTION_FLOOR: u32 = 80;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct StarkProof {
pub context: Context,
pub commitments: Commitments,
pub trace_queries: Vec<Queries>,
pub constraint_queries: Queries,
pub ood_frame: OodFrame,
pub fri_proof: FriProof,
pub pow_nonce: u64,
}
impl StarkProof {
pub fn options(&self) -> &ProofOptions {
self.context.options()
}
pub fn trace_layout(&self) -> &TraceLayout {
self.context.trace_layout()
}
pub fn trace_length(&self) -> usize {
self.context.trace_length()
}
pub fn get_trace_info(&self) -> TraceInfo {
self.context.get_trace_info()
}
pub fn lde_domain_size(&self) -> usize {
self.context.lde_domain_size()
}
pub fn security_level(&self, conjectured: bool) -> u32 {
if conjectured {
get_conjectured_security(
self.context.options(),
self.context.num_modulus_bits(),
self.lde_domain_size() as u64,
)
} else {
unimplemented!("proven security estimation has not been implement yet")
}
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::new();
self.context.write_into(&mut result);
self.commitments.write_into(&mut result);
self.trace_queries.write_into(&mut result);
self.constraint_queries.write_into(&mut result);
self.ood_frame.write_into(&mut result);
self.fri_proof.write_into(&mut result);
result.extend_from_slice(&self.pow_nonce.to_le_bytes());
result
}
pub fn from_bytes(source: &[u8]) -> Result<Self, DeserializationError> {
let mut source = SliceReader::new(source);
let context = Context::read_from(&mut source)?;
let commitments = Commitments::read_from(&mut source)?;
let num_trace_segments = context.trace_layout().num_segments();
let mut trace_queries = Vec::with_capacity(num_trace_segments);
for _ in 0..num_trace_segments {
trace_queries.push(Queries::read_from(&mut source)?);
}
let proof = StarkProof {
context,
commitments,
trace_queries,
constraint_queries: Queries::read_from(&mut source)?,
ood_frame: OodFrame::read_from(&mut source)?,
fri_proof: FriProof::read_from(&mut source)?,
pow_nonce: source.read_u64()?,
};
if source.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
}
Ok(proof)
}
}
fn get_conjectured_security(
options: &ProofOptions,
base_field_bits: u32,
lde_domain_size: u64,
) -> u32 {
let field_size = base_field_bits * options.field_extension().degree();
let field_security = field_size - lde_domain_size.trailing_zeros();
let hash_fn_security = options.hash_fn().collision_resistance();
let security_per_query = log2(options.blowup_factor());
let mut query_security = security_per_query * options.num_queries() as u32;
if query_security >= GRINDING_CONTRIBUTION_FLOOR {
query_security += options.grinding_factor();
}
cmp::min(
cmp::min(field_security, query_security) - 1,
hash_fn_security,
)
}