Skip to content

Commit

Permalink
Claim hash is no longer the proof id (#552)
Browse files Browse the repository at this point in the history
* claim hash is no longer the proof id

* eliminate unused function

* improve naming/structure and persisting robustness of commitments

* more renamings

* commit/hide API for Commitment

* add constant for non-hiding commitment secret; add Store::commit and use it elsewhere
  • Loading branch information
arthurpaulino authored Jul 24, 2023
1 parent 33ac476 commit d6d8dd6
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 42 deletions.
24 changes: 13 additions & 11 deletions src/cli/commitment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use lurk::{field::LurkField, z_ptr::ZExprPtr, z_store::ZStore};
use lurk::{field::LurkField, z_store::ZStore};
use serde::{Deserialize, Serialize};

use super::field_data::HasFieldModulus;
Expand All @@ -9,7 +9,7 @@ use super::field_data::HasFieldModulus;
/// hide the original payload.
#[derive(Serialize, Deserialize)]
pub struct Commitment<F: LurkField> {
pub(crate) hidden: ZExprPtr<F>,
pub(crate) hash: F,
pub(crate) zstore: ZStore<F>,
}

Expand All @@ -30,21 +30,23 @@ mod non_wasm {
use super::Commitment;

impl<F: LurkField> Commitment<F> {
pub fn new(secret: F, payload: Ptr<F>, store: &mut Store<F>) -> Result<Self> {
let hidden = store.hide(secret, payload);
pub fn new(secret: Option<F>, payload: Ptr<F>, store: &mut Store<F>) -> Result<Self> {
let comm_ptr = match secret {
Some(secret) => store.hide(secret, payload),
None => store.commit(payload),
};
let mut zstore = Some(ZStore::<F>::default());
let hidden = store.get_z_expr(&hidden, &mut zstore)?.0;
Ok(Self {
hidden,
zstore: zstore.unwrap(),
})
let hash = *store.get_z_expr(&comm_ptr, &mut zstore)?.0.value();
let zstore = zstore.unwrap();
Ok(Self { hash, zstore })
}
}

impl<F: LurkField + Serialize> Commitment<F> {
#[inline]
pub fn persist(self, hash: &str) -> Result<()> {
dump(self, commitment_path(hash))
pub fn persist(self) -> Result<()> {
let hash_str = &self.hash.hex_digits();
dump(self, commitment_path(hash_str))
}
}
}
16 changes: 8 additions & 8 deletions src/cli/lurk_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ mod non_wasm {

impl<F: LurkField + Serialize> LurkProofMeta<F> {
#[inline]
pub fn persist(self, id: &str) -> Result<()> {
dump(self, proof_meta_path(id))
pub fn persist(self, proof_key: &str) -> Result<()> {
dump(self, proof_meta_path(proof_key))
}
}

Expand All @@ -89,8 +89,8 @@ mod non_wasm {
Coproc<F>: Coprocessor<Pallas>,
{
#[inline]
pub fn persist(self, id: &str) -> Result<()> {
dump(self, proof_path(id))
pub fn persist(self, proof_key: &str) -> Result<()> {
dump(self, proof_path(proof_key))
}
}

Expand All @@ -112,12 +112,12 @@ mod non_wasm {
}
}

pub fn verify_proof(proof_id: &str) -> Result<()> {
let lurk_proof: LurkProof<'_, Pallas> = load(proof_path(proof_id))?;
pub fn verify_proof(proof_key: &str) -> Result<()> {
let lurk_proof: LurkProof<'_, Pallas> = load(proof_path(proof_key))?;
if lurk_proof.verify()? {
println!("✓ Proof \"{proof_id}\" verified");
println!("✓ Proof \"{proof_key}\" verified");
} else {
println!("✗ Proof \"{proof_id}\" failed on verification");
println!("✗ Proof \"{proof_key}\" failed on verification");
}
Ok(())
}
Expand Down
56 changes: 34 additions & 22 deletions src/cli/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,14 @@ impl Repl<F> {
])
}

#[allow(dead_code)]
fn proof_key(backend: &Backend, rc: &usize, claim_hash: &str) -> String {
let field = F::FIELD;
format!("{backend}_{field}_{rc}_{claim_hash}")
}

#[cfg(not(target_arch = "wasm32"))]
pub fn prove_last_frames(&mut self) -> Result<()> {
use ff::Field;

use crate::cli::{commitment::Commitment, paths::non_wasm::proof_path};

match self.evaluation.as_mut() {
Expand All @@ -207,16 +211,17 @@ impl Repl<F> {
let env_out = self.store.get_z_expr(&output.env, &mut zstore)?.0;
let cont_out = self.store.get_z_cont(&output.cont, &mut zstore)?.0;

let proof_claim = Self::proof_claim(
let claim = Self::proof_claim(
&mut self.store,
(input.expr, output.expr),
(input.env, output.env),
(cont.parts(), cont_out.parts()),
);
let commitment = Commitment::new(F::ZERO, proof_claim, &mut self.store)?;
let proof_id = &commitment.hidden.value().hex_digits();

let proof_path = proof_path(proof_id);
let claim_comm = Commitment::new(None, claim, &mut self.store)?;
let claim_hash = &claim_comm.hash.hex_digits();
let proof_key = &Self::proof_key(&self.backend, &self.rc, claim_hash);
let proof_path = proof_path(proof_key);

if proof_path.exists() {
info!("Proof already cached");
Expand Down Expand Up @@ -263,11 +268,12 @@ impl Repl<F> {
zstore: zstore.unwrap(),
};

lurk_proof.persist(proof_id)?;
lurk_proof_meta.persist(proof_id)?;
commitment.persist(proof_id)?;
lurk_proof.persist(proof_key)?;
lurk_proof_meta.persist(proof_key)?;
claim_comm.persist()?;
}
println!("Proof ID: \"{proof_id}\"");
println!("Claim hash: 0x{claim_hash}");
println!("Proof key: \"{proof_key}\"");
Ok(())
}
Backend::SnarkPackPlus => todo!(),
Expand All @@ -279,32 +285,38 @@ impl Repl<F> {
fn hide(&mut self, secret: F, payload: Ptr<F>) -> Result<()> {
use super::commitment::Commitment;

let commitment = Commitment::new(secret, payload, &mut self.store)?;
let hash = &commitment.hidden.value().hex_digits();
commitment.persist(hash)?;
let commitment = Commitment::new(Some(secret), payload, &mut self.store)?;
let hash_str = &commitment.hash.hex_digits();
commitment.persist()?;
println!(
"Data: {}\nHash: 0x{hash}",
"Data: {}\nHash: 0x{hash_str}",
payload.fmt_to_string(&self.store)
);
Ok(())
}

#[cfg(not(target_arch = "wasm32"))]
fn fetch(&mut self, hash: &str, print_data: bool) -> Result<()> {
fn fetch(&mut self, hash: &F, print_data: bool) -> Result<()> {
use lurk::z_ptr::ZExprPtr;

use super::{
commitment::Commitment, field_data::non_wasm::load, paths::non_wasm::commitment_path,
};

let commitment: Commitment<F> = load(commitment_path(hash))?;
if commitment.hidden.value().hex_digits() != hash {
let commitment: Commitment<F> = load(commitment_path(&hash.hex_digits()))?;
let comm_hash = commitment.hash;
if &comm_hash != hash {
bail!("Hash mismatch. Corrupted commitment file.")
} else {
let comm = self
// create a ZExprPtr with the intended hash
let comm_zptr = &ZExprPtr::from_parts(ExprTag::Comm, comm_hash);
// populate the REPL's store with the data
let comm_ptr = self
.store
.intern_z_expr_ptr(&commitment.hidden, &commitment.zstore)
.intern_z_expr_ptr(comm_zptr, &commitment.zstore)
.unwrap();
if print_data {
let data = self.store.fetch_comm(&comm).unwrap().1;
let data = self.store.fetch_comm(&comm_ptr).unwrap().1;
println!("{}", data.fmt_to_string(&self.store));
} else {
println!("Data is now available");
Expand Down Expand Up @@ -395,7 +407,7 @@ impl Repl<F> {
}

#[allow(dead_code)]
fn get_comm_hash(&mut self, cmd: &str, args: &Ptr<F>) -> Result<String> {
fn get_comm_hash(&mut self, cmd: &str, args: &Ptr<F>) -> Result<F> {
let first = self.peek1(cmd, args)?;
let n = self.store.lurk_sym("num");
let expr = self.store.list(&[n, first]);
Expand All @@ -406,7 +418,7 @@ impl Repl<F> {
.store
.fetch_num(&expr_io.expr)
.expect("must be a number");
Ok(hash.into_scalar().hex_digits())
Ok(hash.into_scalar())
}

fn handle_meta_cases(&mut self, cmd: &str, args: &Ptr<F>, pwd_path: &Path) -> Result<()> {
Expand Down
2 changes: 1 addition & 1 deletion src/eval/reduction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ fn apply_continuation<F: LurkField>(
ExprTag::Num | ExprTag::Comm => store.secret_mut(result)?,
_ => return Ok(Control::Error(result, env)),
},
Op1::Commit => store.hide(F::ZERO, result),
Op1::Commit => store.commit(result),
Op1::Num => match result.tag {
ExprTag::Num | ExprTag::Comm | ExprTag::Char | ExprTag::U64 => {
let z_ptr = store
Expand Down
3 changes: 3 additions & 0 deletions src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ pub trait LurkField: PrimeField + PrimeFieldBits {
/// The type of the field element's representation
const FIELD: LanguageField;

/// The default secret for non-hiding commitments
const NON_HIDING_COMMITMENT_SECRET: Self = Self::ZERO;

/// Converts the field element to a byte vector
fn to_bytes(self) -> Vec<u8> {
let repr = self.to_repr();
Expand Down
4 changes: 4 additions & 0 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ impl<F: LurkField> Store<F> {
self.intern_comm(secret, payload)
}

pub fn commit(&mut self, payload: Ptr<F>) -> Ptr<F> {
self.hide(F::NON_HIDING_COMMITMENT_SECRET, payload)
}

pub fn open(&self, ptr: Ptr<F>) -> Option<(F, Ptr<F>)> {
let p = match ptr.tag {
ExprTag::Comm => ptr,
Expand Down

0 comments on commit d6d8dd6

Please sign in to comment.