#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Claim {
pub program_hash: Vec<u64>,
pub public_input: Vec<u64>,
pub public_output: Vec<u64>,
}
pub fn padded_height(max_table_rows: u64) -> u64 {
if max_table_rows == 0 {
return 1;
}
max_table_rows.next_power_of_two()
}
pub fn merkle_depth(padded_height: u64) -> u32 {
if padded_height <= 1 {
return 0;
}
64 - (padded_height - 1).leading_zeros()
}
pub fn ntt_domain_size(padded_height: u64, blowup_factor: u64) -> u64 {
padded_height.saturating_mul(blowup_factor)
}
pub fn fri_query_count(security_bits: u32, blowup_factor: u64) -> u32 {
if blowup_factor <= 1 {
return security_bits;
}
let log2_blowup = 63 - blowup_factor.leading_zeros();
if log2_blowup == 0 {
return security_bits;
}
(security_bits + log2_blowup - 1) / log2_blowup
}
pub fn estimate_proof_size(
padded_height: u64,
column_count: u64,
field_bytes: u64,
blowup_factor: u64,
security_bits: u32,
) -> u64 {
let queries = fri_query_count(security_bits, blowup_factor) as u64;
let depth = merkle_depth(padded_height) as u64;
let hash_size: u64 = 32; let per_query = column_count * field_bytes + depth * hash_size;
queries * per_query
}
pub fn estimate_proving_ns(padded_height: u64, column_count: u64) -> u64 {
if padded_height == 0 || column_count == 0 {
return 0;
}
let log_h = 64 - padded_height.leading_zeros() as u64;
padded_height
.saturating_mul(column_count)
.saturating_mul(log_h)
.saturating_mul(3)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn padded_height_powers_of_two() {
assert_eq!(padded_height(0), 1);
assert_eq!(padded_height(1), 1);
assert_eq!(padded_height(2), 2);
assert_eq!(padded_height(3), 4);
assert_eq!(padded_height(5), 8);
assert_eq!(padded_height(1024), 1024);
assert_eq!(padded_height(1025), 2048);
}
#[test]
fn merkle_depth_correct() {
assert_eq!(merkle_depth(1), 0);
assert_eq!(merkle_depth(2), 1);
assert_eq!(merkle_depth(4), 2);
assert_eq!(merkle_depth(1024), 10);
assert_eq!(merkle_depth(1 << 20), 20);
}
#[test]
fn fri_queries_typical() {
assert_eq!(fri_query_count(128, 4), 64);
assert_eq!(fri_query_count(128, 8), 43);
assert_eq!(fri_query_count(128, 2), 128);
assert_eq!(fri_query_count(128, 1), 128);
}
#[test]
fn proof_size_reasonable() {
let size = estimate_proof_size(1 << 20, 200, 8, 4, 128);
assert!(size > 100_000, "proof too small: {}", size);
assert!(size < 100_000_000, "proof too large: {}", size);
}
#[test]
fn proving_time_nonzero() {
let ns = estimate_proving_ns(1 << 20, 200);
assert!(ns > 0);
assert!(ns > 1_000_000_000, "estimate too fast: {} ns", ns);
}
#[test]
fn proving_time_zero_inputs() {
assert_eq!(estimate_proving_ns(0, 100), 0);
assert_eq!(estimate_proving_ns(100, 0), 0);
}
}