Skip to content

Increase testability of constraint failures #351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1.0"
strum = { version = "0.27", features = ["derive"] }
syn = "2.0"
test-strategy = "0.4.0"
test-strategy = "0.4.1"
thiserror = "2.0"
twenty-first = "0.48.0"
unicode-width = "0.2"
Expand Down
13 changes: 4 additions & 9 deletions triton-vm/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ pub(crate) fn cache_lde_trace() -> Option<CacheDecision> {
mod tests {
use crate::example_programs::FIBONACCI_SEQUENCE;
use crate::prelude::*;
use crate::shared_tests::DEFAULT_LOG2_FRI_EXPANSION_FACTOR_FOR_TESTS;
use crate::shared_tests::ProgramAndInput;
use crate::shared_tests::prove_and_verify;
use crate::shared_tests::TestableProgram;

use super::*;

Expand All @@ -110,11 +108,8 @@ mod tests {
}

fn prove_and_verify_a_triton_vm_program() {
let program_and_input = ProgramAndInput::new(FIBONACCI_SEQUENCE.clone())
.with_input(PublicInput::from(bfe_array![100]));
prove_and_verify(
program_and_input,
DEFAULT_LOG2_FRI_EXPANSION_FACTOR_FOR_TESTS,
);
TestableProgram::new(FIBONACCI_SEQUENCE.clone())
.with_input(PublicInput::from(bfe_array![100]))
.prove_and_verify();
}
}
176 changes: 105 additions & 71 deletions triton-vm/src/shared_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ use proptest::collection::vec;
use proptest::prelude::*;
use proptest_arbitrary_interop::arb;
use rand::Rng;
use rand::prelude::*;
use rand::SeedableRng;
use rand::prelude::StdRng;
use test_strategy::Arbitrary;
use twenty_first::prelude::*;

use crate::aet::AlgebraicExecutionTrace;
use crate::challenges::Challenges;
use crate::error::VMError;
use crate::fri::AuthenticationStructure;
use crate::prelude::*;
use crate::profiler::profiler;
use crate::proof_item::FriResponse;
use crate::table::master_table::MasterAuxTable;
use crate::table::master_table::MasterMainTable;

pub(crate) const DEFAULT_LOG2_FRI_EXPANSION_FACTOR_FOR_TESTS: usize = 2;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Arbitrary)]
#[filter(!#self.0.is_zero())]
struct NonZeroXFieldElement(#[strategy(arb())] XFieldElement);
Expand Down Expand Up @@ -95,84 +95,23 @@ impl LeavedMerkleTreeTestData {
}
}

/// Prove correct execution of the supplied program, then verify said proof.
/// Also print the [`VMPerformanceProfile`][profile] for both proving and
/// verification to standard out.
///
/// [profile]: crate::profiler::VMPerformanceProfile
pub(crate) fn prove_and_verify(
program_and_input: ProgramAndInput,
log_2_fri_expansion_factor: usize,
) {
let ProgramAndInput {
program,
public_input,
non_determinism,
} = program_and_input;

crate::profiler::start("");
profiler!(start "Pre-flight");
let claim = Claim::about_program(&program).with_input(public_input.clone());
let (aet, public_output) = VM::trace_execution(program, public_input, non_determinism).unwrap();
let claim = claim.with_output(public_output);
let stark = low_security_stark(log_2_fri_expansion_factor);
profiler!(stop "Pre-flight");

profiler!(start "Prove");
let proof = stark.prove(&claim, &aet).unwrap();
profiler!(stop "Prove");

profiler!(start "Verify");
assert!(let Ok(()) = stark.verify(&claim, &proof));
profiler!(stop "Verify");
let profile = crate::profiler::finish();

let_assert!(Ok(padded_height) = proof.padded_height());
let fri = stark.fri(padded_height).unwrap();
let profile = profile
.with_padded_height(padded_height)
.with_fri_domain_len(fri.domain.length);
println!("{profile}");
}

pub(crate) fn low_security_stark(log_expansion_factor: usize) -> Stark {
let security_level = 32;
Stark::new(security_level, log_expansion_factor)
}

pub(crate) fn construct_master_main_table(
stark: Stark,
aet: &AlgebraicExecutionTrace,
) -> MasterMainTable {
let padded_height = aet.padded_height();
let fri = stark.fri(padded_height).unwrap();
let max_degree = stark.max_degree(padded_height);
let quotient_domain = Prover::quotient_domain(fri.domain, max_degree).unwrap();
let seed = StdRng::seed_from_u64(6718321586953195571).random();

MasterMainTable::new(
aet,
quotient_domain,
fri.domain,
stark.num_trace_randomizers,
seed,
)
}

/// Program and associated inputs.
/// Program and associated inputs, as well as parameters with which to prove
/// correct execution.
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) struct ProgramAndInput {
pub(crate) struct TestableProgram {
pub program: Program,
pub public_input: PublicInput,
pub non_determinism: NonDeterminism,
pub stark: Stark,
}

impl ProgramAndInput {
impl TestableProgram {
pub fn new(program: Program) -> Self {
Self {
program,
public_input: PublicInput::default(),
non_determinism: NonDeterminism::default(),
stark: Stark::low_security(),
}
}

Expand All @@ -188,6 +127,12 @@ impl ProgramAndInput {
self
}

#[must_use]
pub fn use_stark(mut self, stark: Stark) -> Self {
self.stark = stark;
self
}

pub fn public_input(&self) -> PublicInput {
self.public_input.clone()
}
Expand All @@ -202,4 +147,93 @@ impl ProgramAndInput {
let non_determinism = self.non_determinism();
VM::run(self.program, public_input, non_determinism)
}

/// Prove correct execution of the program, then verify said proof.
///
/// Also print the [`VMPerformanceProfile`][profile] for both proving and
/// verification to standard out.
///
/// [profile]: crate::profiler::VMPerformanceProfile
pub fn prove_and_verify(self) {
let Self {
program,
public_input,
non_determinism,
stark,
} = self;

crate::profiler::start("");
profiler!(start "Pre-flight");
let claim = Claim::about_program(&program).with_input(public_input.clone());
let (aet, public_output) =
VM::trace_execution(program, public_input, non_determinism).unwrap();
let claim = claim.with_output(public_output);
profiler!(stop "Pre-flight");

profiler!(start "Prove");
let proof = stark.prove(&claim, &aet).unwrap();
profiler!(stop "Prove");

profiler!(start "Verify");
assert!(let Ok(()) = stark.verify(&claim, &proof));
profiler!(stop "Verify");
let profile = crate::profiler::finish();

let_assert!(Ok(padded_height) = proof.padded_height());
assert!(aet.padded_height() == padded_height);

let fri = stark.fri(padded_height).unwrap();
let profile = profile
.with_cycle_count(aet.height_of_table(TableId::Processor))
.with_padded_height(padded_height)
.with_fri_domain_len(fri.domain.length);
println!("{profile}");
}

pub fn generate_proof_artifacts(self) -> ProofArtifacts {
let Self {
program,
public_input,
non_determinism,
stark,
} = self;

let claim = Claim::about_program(&program).with_input(public_input.clone());
let (aet, stdout) = VM::trace_execution(program, public_input, non_determinism).unwrap();
let claim = claim.with_output(stdout);

// construct master main table
let padded_height = aet.padded_height();
let fri_domain = stark.fri(padded_height).unwrap().domain;
let max_degree = stark.max_degree(padded_height);

let mut master_main_table = MasterMainTable::new(
&aet,
Prover::quotient_domain(fri_domain, max_degree).unwrap(),
fri_domain,
stark.num_trace_randomizers,
StdRng::seed_from_u64(6718321586953195571).random(),
);
master_main_table.pad();
let master_main_table = master_main_table;

let challenges = Challenges::placeholder(&claim);
let master_aux_table = master_main_table.extend(&challenges);

ProofArtifacts {
claim,
master_main_table,
master_aux_table,
challenges,
}
}
}

/// Various intermediate artifacts required for proof generation.
#[must_use]
pub struct ProofArtifacts {
pub claim: Claim,
pub master_main_table: MasterMainTable,
pub master_aux_table: MasterAuxTable,
pub challenges: Challenges,
}
Loading
Loading