Skip to content

Commit

Permalink
refactor!: use BFieldElements everywhere
Browse files Browse the repository at this point in the history
Accept only `BFieldElement`s, not `u64`s, in the methods for proving and
verifying Triton VM executions.

Since any and all computation happens on `BFieldElement`s, and because
there is no 1-to-1 mapping between the two types, it is a potential
source of confusion to accept `u64`s.
  • Loading branch information
jan-ferdinand committed Mar 20, 2024
1 parent 15a8cd7 commit 05bd271
Show file tree
Hide file tree
Showing 14 changed files with 273 additions and 581 deletions.
46 changes: 25 additions & 21 deletions triton-vm/benches/proof_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,24 @@ use triton_vm::prove_program;
/// Ties together a program and its inputs.
struct ProgramAndInput {
program: Program,
public_input: Vec<u64>,
non_determinism: NonDeterminism<u64>,
public_input: PublicInput,
non_determinism: NonDeterminism,
}

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

#[must_use]
fn with_input<I: Into<PublicInput>>(mut self, public_input: I) -> Self {
self.public_input = public_input.into();
self
}
}

/// The measurement unit for Criterion.
Expand Down Expand Up @@ -149,29 +165,17 @@ fn program_verify_sudoku() -> ProgramAndInput {
6, 7, 8, /**/ 9, 1, 2, /**/ 3, 4, 5, //
9, 1, 2, /**/ 3, 4, 5, /**/ 6, 7, 8, //
];
ProgramAndInput {
program: VERIFY_SUDOKU.clone(),
public_input: sudoku.to_vec(),
non_determinism: [].into(),
}
ProgramAndInput::new(VERIFY_SUDOKU.clone()).with_input(sudoku.map(|b| bfe!(b)))
}

/// The program for computing some Fibonacci number, accepting as input which number of the
/// sequence to compute.
fn program_fib(nth_element: u64) -> ProgramAndInput {
ProgramAndInput {
program: FIBONACCI_SEQUENCE.clone(),
public_input: vec![nth_element],
non_determinism: [].into(),
}
ProgramAndInput::new(FIBONACCI_SEQUENCE.clone()).with_input([bfe!(nth_element)])
}

fn program_halt() -> ProgramAndInput {
ProgramAndInput {
program: triton_program!(halt),
public_input: vec![],
non_determinism: [].into(),
}
ProgramAndInput::new(triton_program!(halt))
}

/// The base 2, integer logarithm of the FRI domain length.
Expand Down Expand Up @@ -238,8 +242,8 @@ fn sum_of_proof_lengths_for_source_code(
for _ in 0..num_iterations {
let (_, _, proof) = prove_program(
&program_and_input.program,
&program_and_input.public_input,
&program_and_input.non_determinism,
program_and_input.public_input.clone(),
program_and_input.non_determinism.clone(),
)
.unwrap();
sum_of_proof_lengths += proof.encode().len();
Expand All @@ -255,8 +259,8 @@ fn generate_proof_and_benchmark_id(
) -> (Proof, BenchmarkId) {
let (stark, _, proof) = prove_program(
&program_and_input.program,
&program_and_input.public_input,
&program_and_input.non_determinism,
program_and_input.public_input.clone(),
program_and_input.non_determinism.clone(),
)
.unwrap();
let log_2_fri_domain_length = log_2_fri_domain_length(stark, &proof);
Expand Down
4 changes: 2 additions & 2 deletions triton-vm/benches/prove_fib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use triton_vm::prelude::*;
use triton_vm::profiler::Report;
use triton_vm::profiler::TritonProfiler;

const FIBONACCI_INDEX: u64 = 100;
const FIBONACCI_INDEX: BFieldElement = BFieldElement::new(100);

/// cargo criterion --bench prove_fib
fn prove_fib(criterion: &mut Criterion) {
Expand Down Expand Up @@ -52,7 +52,7 @@ fn prover_timing_report(claim: &Claim, aet: &AlgebraicExecutionTrace) -> Report

fn trace_execution() -> (Claim, AlgebraicExecutionTrace) {
let program = FIBONACCI_SEQUENCE.clone();
let public_input: PublicInput = vec![FIBONACCI_INDEX].into();
let public_input = PublicInput::from([FIBONACCI_INDEX]);
let (aet, output) = program
.trace_execution(public_input.clone(), [].into())
.unwrap();
Expand Down
16 changes: 7 additions & 9 deletions triton-vm/examples/factorial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
//!
//! [Triton VM]: https://triton-vm.org/
use triton_vm::prelude::triton_program;
use triton_vm::prelude::NonDeterminism;
use triton_vm::prelude::*;

fn main() {
// The program that is to be run in Triton VM. Written in Triton assembly.
// The given example program computes the factorial of the public input.
// Note that all arithmetic is in the prime field with 2^64 - 2^32 + 1 elements.
let factorial_program = triton_program!(
// op stack:
read_io 1 // n
Expand All @@ -34,10 +32,9 @@ fn main() {
recurse
);

// Note: since arithmetic is in the prime field, all input must be in canonical representation,
// i.e., smaller than the prime field's modulus 2^64 - 2^32 + 1.
// Otherwise, proof generation will be aborted.
let public_input = [1_000];
// Note that all arithmetic is in the prime field with 2^64 - 2^32 + 1 elements.
// The `bfe!` macro is used to create elements of this field.
let public_input = PublicInput::from([bfe!(1_000)]);

// The execution of the factorial program is already fully determined by the public input.
// Hence, in this case, there is no need for specifying non-determinism.
Expand All @@ -58,13 +55,14 @@ fn main() {
//
// Triton VM's default parameters give a (conjectured) security level of 160 bits.
let (stark, claim, proof) =
triton_vm::prove_program(&factorial_program, &public_input, &non_determinism).unwrap();
triton_vm::prove_program(&factorial_program, public_input, non_determinism).unwrap();

let verdict = triton_vm::verify(stark, &claim, &proof);
assert!(verdict);

println!("Successfully verified proof.");
println!("Verifiably correct output: {:?}", claim.public_output());
let claimed_output = claim.output.iter().map(|o| o.value());
println!("Verifiably correct output: {claimed_output:?}");

let conjectured_security_level = stark.security_level;
println!("Conjectured security level is {conjectured_security_level} bits.");
Expand Down
22 changes: 0 additions & 22 deletions triton-vm/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,25 +205,6 @@ pub enum ProgramDecodingError {
MissingArgument(usize, Instruction),
}

const CANONICAL_REPRESENTATION_ERROR_MESSAGE: &str =
"must contain only elements in canonical representation, i.e., \
elements smaller than the prime field's modulus 2^64 - 2^32 + 1";

#[derive(Debug, Copy, Clone, Eq, PartialEq, Error)]
pub enum CanonicalRepresentationError {
#[error("public input {CANONICAL_REPRESENTATION_ERROR_MESSAGE}")]
PublicInput,

#[error("secret input {CANONICAL_REPRESENTATION_ERROR_MESSAGE}")]
NonDeterminismIndividualTokens,

#[error("RAM addresses {CANONICAL_REPRESENTATION_ERROR_MESSAGE}")]
NonDeterminismRamKeys,

#[error("RAM values {CANONICAL_REPRESENTATION_ERROR_MESSAGE}")]
NonDeterminismRamValues,
}

#[non_exhaustive]
#[derive(Debug, Clone, Eq, PartialEq, Error)]
pub enum ProvingError {
Expand All @@ -233,9 +214,6 @@ pub enum ProvingError {
#[error("claimed public output does not match actual public output")]
PublicOutputMismatch,

#[error(transparent)]
CanonicalRepresentationError(#[from] CanonicalRepresentationError),

#[error("expected row of length {expected_len} but got {actual_len}")]
TableRowConversionError {
expected_len: usize,
Expand Down
8 changes: 4 additions & 4 deletions triton-vm/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ mod tests {

use crate::instruction::*;
use crate::op_stack::NUM_OP_STACK_REGISTERS;
use crate::program::PublicInput;
use crate::triton_asm;
use crate::triton_program;
use crate::vm::tests::test_program_for_call_recurse_return;
Expand Down Expand Up @@ -1076,10 +1077,9 @@ mod tests {
}

fn terminal_op_stack_size_for_program(program: Program) -> usize {
let public_input = vec![bfe!(0)].into();
let mock_digests = vec![Digest::default()];
let non_determinism: NonDeterminism<_> = vec![bfe!(0)].into();
let non_determinism = non_determinism.with_digests(mock_digests);
let public_input = PublicInput::from([bfe!(0)]);
let mock_digests = [Digest::default()];
let non_determinism = NonDeterminism::from([bfe!(0)]).with_digests(mock_digests);

let mut vm_state = VMState::new(&program, public_input, non_determinism);
let_assert!(Ok(()) = vm_state.run());
Expand Down
Loading

0 comments on commit 05bd271

Please sign in to comment.