Skip to content

Commit

Permalink
don't include Claim in Proof, require it explicitly for verify()
Browse files Browse the repository at this point in the history
The `Claim` is still considered in the Fiat-Shamir heuristic.
  • Loading branch information
jan-ferdinand committed Jul 5, 2023
1 parent 5b9a70b commit 741c6d8
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 91 deletions.
4 changes: 2 additions & 2 deletions triton-vm/benches/proof_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ fn sum_of_proof_lengths_for_source_code(
) -> ProofSize {
let mut sum_of_proof_lengths = 0;
for _ in 0..num_iterations {
let (_, proof) =
let (_, _, proof) =
prove_from_source(&source.source_code, &source.input, &source.secret_input).unwrap();
sum_of_proof_lengths += proof.encode().len();
}
Expand All @@ -238,7 +238,7 @@ fn generate_proof_and_benchmark_id(
program_name: &str,
program_halt: &SourceCodeAndInput,
) -> (Proof, BenchmarkId) {
let (parameters, proof) = prove_from_source(
let (parameters, _, proof) = prove_from_source(
&program_halt.source_code,
&program_halt.input,
&program_halt.secret_input,
Expand Down
4 changes: 2 additions & 2 deletions triton-vm/benches/verify_halt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn verify_halt(criterion: &mut Criterion) {
};

let mut profiler = Some(TritonProfiler::new("Verify Halt"));
let verdict = Stark::verify(&parameters, &proof, &mut profiler)
let verdict = Stark::verify(&parameters, &claim, &proof, &mut profiler)
.map_err(|e| panic!("The Verifier is unhappy! {e}"))
.unwrap();
assert!(verdict);
Expand All @@ -67,7 +67,7 @@ fn verify_halt(criterion: &mut Criterion) {
group.sample_size(10);
group.bench_function(bench_id, |bencher| {
bencher.iter(|| {
let _ = Stark::verify(&parameters, &proof, &mut None);
let _ = Stark::verify(&parameters, &claim, &proof, &mut None);
});
});
group.finish();
Expand Down
18 changes: 9 additions & 9 deletions triton-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn prove_from_source(
source_code: &str,
public_input: &[u64],
secret_input: &[u64],
) -> Result<(StarkParameters, Proof)> {
) -> Result<(StarkParameters, Claim, Proof)> {
let canonical_representation_error =
"input must contain only elements in canonical representation, i.e., \
elements smaller than the prime field's modulus 2^64 - 2^32 + 1.";
Expand Down Expand Up @@ -99,7 +99,7 @@ pub fn prove_from_source(
// Generate the proof.
let proof = Stark::prove(&parameters, &claim, &aet, &mut None);

Ok((parameters, proof))
Ok((parameters, claim, proof))
}

/// A convenience function for proving a [`Claim`] and the program that claim corresponds to.
Expand All @@ -123,8 +123,9 @@ pub fn prove(
}

/// Verify a proof generated by [`prove`] or [`prove_from_source`].
pub fn verify(parameters: &StarkParameters, proof: &Proof) -> bool {
Stark::verify(parameters, proof, &mut None).unwrap_or(false)
#[must_use]
pub fn verify(parameters: &StarkParameters, claim: &Claim, proof: &Proof) -> bool {
Stark::verify(parameters, claim, proof, &mut None).unwrap_or(false)
}

#[cfg(test)]
Expand Down Expand Up @@ -167,14 +168,13 @@ mod public_interface_tests {
17174585125955027015,
];

let (parameters, proof) =
let (parameters, claim, proof) =
prove_from_source(source_code, &public_input, &secret_input).unwrap();
assert_eq!(
StarkParameters::default(),
parameters,
"Prover must return default STARK parameters"
);
let claim = proof.claim();
let program = Program::from_code(source_code).unwrap();
let expected_program_digest = StarkHasher::hash_varlen(&program.to_bwords());
assert_eq!(
Expand All @@ -190,7 +190,7 @@ mod public_interface_tests {
claim.output.is_empty(),
"Output must be empty for program that doesn't write to output"
);
let verdict = verify(&parameters, &proof);
let verdict = verify(&parameters, &claim, &proof);
assert!(verdict);
}

Expand All @@ -208,7 +208,7 @@ mod public_interface_tests {
};

let proof = prove(&parameters, &claim, &program, &[]).unwrap();
let verdict = verify(&parameters, &proof);
let verdict = verify(&parameters, &claim, &proof);
assert!(verdict);
}

Expand All @@ -220,7 +220,7 @@ mod public_interface_tests {
}

let source_code = "nop halt";
let (_, proof) = prove_from_source(source_code, &[], &[]).unwrap();
let (_, _, proof) = prove_from_source(source_code, &[], &[]).unwrap();

save_proof(filename, proof.clone()).unwrap();
let loaded_proof = load_proof(filename).unwrap();
Expand Down
13 changes: 0 additions & 13 deletions triton-vm/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,6 @@ impl Proof {
}
log_2_padded_height.expect("The proof must contain a log_2_padded_height.")
}

/// The [`Claim`] that this proof is for.
pub fn claim(&self) -> Claim {
let proof_stream = ProofStream::<stark::StarkHasher>::try_from(self).unwrap();
let mut claim = None;
for item in proof_stream.items {
if let Ok(found_claim) = item.as_claim() {
assert!(claim.is_none(), "The proof must contain exactly one claim.");
claim = Some(found_claim);
}
}
claim.expect("The proof must contain a claim.")
}
}

/// Contains the public information of a verifiably correct computation.
Expand Down
14 changes: 0 additions & 14 deletions triton-vm/src/proof_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ use twenty_first::shared_math::bfield_codec::BFieldCodec;
use twenty_first::shared_math::tip5::Digest;
use twenty_first::shared_math::x_field_element::XFieldElement;

use crate::Claim;

type AuthenticationStructure = Vec<Digest>;

/// A `FriResponse` is an [`AuthenticationStructure`] together with the values of the
Expand All @@ -34,7 +32,6 @@ pub enum ProofItem {
RevealedCombinationElements(Vec<XFieldElement>),
FriCodeword(Vec<XFieldElement>),
FriResponse(FriResponse),
Claim(Claim),
}

impl ProofItem {
Expand All @@ -52,7 +49,6 @@ impl ProofItem {
RevealedCombinationElements(_) => 7,
FriCodeword(_) => 8,
FriResponse(_) => 9,
Claim(_) => 10,
};
BFieldElement::new(discriminant)
}
Expand All @@ -71,7 +67,6 @@ impl ProofItem {
MerkleRoot(_) => true,
OutOfDomainBaseRow(_) => true,
OutOfDomainExtRow(_) => true,
Claim(_) => true,
// all of the following are implied by a corresponding Merkle root
AuthenticationStructure(_) => false,
MasterBaseTableRows(_) => false,
Expand Down Expand Up @@ -152,13 +147,6 @@ impl ProofItem {
other => bail!("expected FRI proof, but got {other:?}"),
}
}

pub fn as_claim(&self) -> Result<Claim> {
match self {
Self::Claim(claim) => Ok(claim.to_owned()),
other => bail!("expected claim, but got {other:?}"),
}
}
}

impl BFieldCodec for ProofItem {
Expand All @@ -182,7 +170,6 @@ impl BFieldCodec for ProofItem {
7 => Self::RevealedCombinationElements(*Vec::<XFieldElement>::decode(str)?),
8 => Self::FriCodeword(*Vec::<XFieldElement>::decode(str)?),
9 => Self::FriResponse(*FriResponse::decode(str)?),
10 => Self::Claim(*Claim::decode(str)?),
i => bail!("Unknown discriminant {i} for ProofItem."),
};
Ok(Box::new(item))
Expand Down Expand Up @@ -216,7 +203,6 @@ impl BFieldCodec for ProofItem {
RevealedCombinationElements(something) => something.encode(),
FriCodeword(something) => something.encode(),
FriResponse(something) => something.encode(),
Claim(something) => something.encode(),
};
[discriminant, encoding].concat()
}
Expand Down
49 changes: 18 additions & 31 deletions triton-vm/src/proof_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ where
b_field_elements.len()
}

fn encode_and_pad_item(item: &ProofItem) -> Vec<BFieldElement> {
fn encode_and_pad_item(item: &impl BFieldCodec) -> Vec<BFieldElement> {
let encoding = item.encode();
let last_chunk_len = (encoding.len() + 1) % H::RATE;
let num_padding_zeros = match last_chunk_len {
Expand All @@ -63,6 +63,19 @@ where
.concat()
}

/// Alters the Fiat-Shamir's sponge state with the encoding of the given item.
/// Does _not_ record the given item in the proof stream.
/// This is useful for items that are not sent to the verifier, _e.g._, the
/// [`Claim`](crate::proof::Claim).
///
/// See also [`Self::enqueue()`] and [`Self::dequeue()`].
pub fn alter_fiat_shamir_state_with(&mut self, item: &impl BFieldCodec) {
H::absorb_repeatedly(
&mut self.sponge_state,
Self::encode_and_pad_item(item).iter(),
)
}

/// Send a proof item as prover to verifier.
/// Some items do not need to be included in the Fiat-Shamir heuristic, _i.e._, they do not
/// need to modify the sponge state. For those items, namely those that evaluate to `false`
Expand All @@ -75,10 +88,7 @@ where
/// round of interaction, no further items need to be hashed.
pub fn enqueue(&mut self, item: &ProofItem) {
if item.include_in_fiat_shamir_heuristic() {
H::absorb_repeatedly(
&mut self.sponge_state,
Self::encode_and_pad_item(item).iter(),
)
self.alter_fiat_shamir_state_with(item);
}
self.items.push(item.clone());
}
Expand All @@ -89,14 +99,12 @@ where
let Some(item) = self.items.get(self.items_index) else {
bail!("Queue must be non-empty in order to dequeue.");
};
let item = item.to_owned();
if item.include_in_fiat_shamir_heuristic() {
H::absorb_repeatedly(
&mut self.sponge_state,
Self::encode_and_pad_item(item).iter(),
)
self.alter_fiat_shamir_state_with(&item);
}
self.items_index += 1;
Ok(item.clone())
Ok(item)
}

/// Given an `upper_bound` that is a power of 2, produce `num_indices` uniform random numbers
Expand Down Expand Up @@ -183,7 +191,6 @@ where

#[cfg(test)]
mod proof_stream_typed_tests {
use crate::Claim;
use itertools::Itertools;
use rand::distributions::Standard;
use rand::prelude::Distribution;
Expand Down Expand Up @@ -258,15 +265,6 @@ mod proof_stream_typed_tests {
revealed_leaves,
};

let program_digest = random_elements(rng.next_u64(), 1)[0];
let input = random_elements(rng.next_u64(), 5);
let output = random_elements(rng.next_u64(), 5);
let claim = Claim {
program_digest,
input,
output,
};

let mut sponge_states = VecDeque::new();
let mut proof_stream = ProofStream::<H>::new();

Expand All @@ -291,8 +289,6 @@ mod proof_stream_typed_tests {
sponge_states.push_back(proof_stream.sponge_state.state);
proof_stream.enqueue(&ProofItem::FriResponse(fri_response.clone()));
sponge_states.push_back(proof_stream.sponge_state.state);
proof_stream.enqueue(&ProofItem::Claim(claim.clone()));
sponge_states.push_back(proof_stream.sponge_state.state);

let proof = proof_stream.into();
let mut proof_stream: ProofStream<H> =
Expand Down Expand Up @@ -383,15 +379,6 @@ mod proof_stream_typed_tests {
_ => panic!(),
};

assert_eq!(
sponge_states.pop_front(),
Some(proof_stream.sponge_state.state)
);
match proof_stream.dequeue().unwrap() {
ProofItem::Claim(claim_) => assert_eq!(claim, claim_),
_ => panic!(),
};

assert_eq!(
sponge_states.pop_front(),
Some(proof_stream.sponge_state.state)
Expand Down
Loading

0 comments on commit 741c6d8

Please sign in to comment.