Skip to content

Commit

Permalink
fix: playing with sp1 atm
Browse files Browse the repository at this point in the history
  • Loading branch information
sebasti810 committed Sep 10, 2024
1 parent 2b7004f commit 2be4ec7
Show file tree
Hide file tree
Showing 13 changed files with 302 additions and 273 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ keystore-rs = "0.1.0"
toml = "0.8.14"
dirs = "5.0.1"
anyhow = "1.0.44"
jmt = { git = "https://github.com/deltadevsde/jmt", features = [
"mocks",
] } #{ version = "0.10.0", features = ["mocks"] }
bellpepper-core = { version = "0.4.0", default-features = false }
jmt = { path = "../jmt", features = ["mocks"]} #{ version = "0.10.0", features = ["mocks"] }
bellpepper-core = { version = "0.4.0" }
arecibo = { git = "https://github.com/deltadevsde/arecibo" }
itertools = "0.13.0" # zip_eq
sha2 = "0.10.8"
Expand Down
4 changes: 2 additions & 2 deletions src/circuits/hashchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct HashChainEntryCircuit {
pub chain: Vec<Scalar>,
}

impl HashChainEntryCircuit {
/* impl HashChainEntryCircuit {
pub fn create(value: &str, hashchain: Vec<HashchainEntry>) -> Result<HashChainEntryCircuit> {
let hashed_value = sha256_mod(value.as_bytes());
let parsed_value = hashed_value.try_into()?;
Expand All @@ -27,7 +27,7 @@ impl HashChainEntryCircuit {
chain: parsed_hashchain,
})
}
}
} */

impl Circuit<Scalar> for HashChainEntryCircuit {
fn synthesize<CS: ConstraintSystem<Scalar>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
Expand Down
2 changes: 1 addition & 1 deletion src/circuits/less_than.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl Circuit<Scalar> for LessThanCircuit {
// result * (1) = 1
cs.enforce(
|| "a < b",
|_| result.lc(CS::one(), Scalar::one()),
|_| result.lc(CS::one(), Scalar::from(1)),
|lc| lc + CS::one(),
|lc| lc + CS::one(),
);
Expand Down
76 changes: 46 additions & 30 deletions src/circuits/merkle_batch.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::{
circuits::{
merkle_insertion::prove_insertion, merkle_update::prove_update, InsertMerkleProofCircuit,
ProofVariantCircuit, UpdateCircuit,
merkle_insertion::prove_insertion, InsertMerkleProofCircuit, ProofVariantCircuit,
UpdateCircuit,
},
tree::Digest,
utils::{create_proof, verify_proof},
tree::{Digest, Proof},
utils::verify_proof,
};
use anyhow::Result;
use bellpepper_core::{Circuit, ConstraintSystem, SynthesisError};
use blstrs::{Bls12, Scalar};
use indexed_merkle_tree::tree::Proof;
use bellperson::{Circuit, ConstraintSystem, SynthesisError};
use blstrs::Scalar;

use super::utils::digest_to_scalar;

/// BatchMerkleProofCircuit represents a circuit for proving a batch of merkle proof circuits.
#[derive(Clone)]
Expand All @@ -21,40 +22,49 @@ pub struct BatchMerkleProofCircuit {

impl BatchMerkleProofCircuit {
pub fn new(
old_commitment: &Digest,
new_commitment: &Digest,
old_commitment: Scalar,
new_commitment: Scalar,
proofs: Vec<Proof>,
) -> Result<BatchMerkleProofCircuit> {
let parsed_old_commitment: Scalar = (*old_commitment).try_into()?;
let parsed_new_commitment: Scalar = (*new_commitment).try_into()?;
let mut proof_circuit_array: Vec<ProofVariantCircuit> = vec![];
for proof in proofs {
match proof {
Proof::Update(update_proof) => {
proof_circuit_array.push(ProofVariantCircuit::Update(UpdateCircuit::new(
&update_proof,
)?));
update_proof,
)));
}
Proof::Insert(insertion_proof) => {
proof_circuit_array.push(ProofVariantCircuit::Insert(
InsertMerkleProofCircuit::new(&insertion_proof)?,
InsertMerkleProofCircuit::new(insertion_proof),
));
}
}
}
Ok(BatchMerkleProofCircuit {
old_commitment: parsed_old_commitment,
new_commitment: parsed_new_commitment,
old_commitment,
new_commitment,
proofs: proof_circuit_array,
})
}

pub fn create_and_verify_snark(&self) -> Result<bool> {
/* pub fn create_and_verify_snark(&self) -> Result<bool> {
let scalars: Vec<Scalar> = vec![self.old_commitment, self.new_commitment];
let circuit = BatchMerkleProofCircuit::new(
self.old_commitment,
self.new_commitment,
self.proofs.clone(),
)?;
let params = load_params_from_storage()?;
let rng = &mut OsRng;
let proof = groth16::create_random_proof(circuit, &params, rng)?;
let proof = create_proof(self);
verify_proof(proof, &scalars)
}
} */
}

impl Circuit<Scalar> for BatchMerkleProofCircuit {
Expand All @@ -79,17 +89,24 @@ impl Circuit<Scalar> for BatchMerkleProofCircuit {

// before the calculations make sure that the old root is that of the first proof
let old_root = match &self.proofs[0] {
ProofVariantCircuit::Update(update_proof_circuit) => update_proof_circuit.old_root,
ProofVariantCircuit::Insert(insert_proof_circuit) => {
insert_proof_circuit.pre_insertion_root
ProofVariantCircuit::Update(update_proof_circuit) => {
update_proof_circuit.update_proof.old_root
}
ProofVariantCircuit::Batch(batch_proof_circuit) => batch_proof_circuit.old_commitment,
ProofVariantCircuit::Insert(insert_proof_circuit) => insert_proof_circuit
.insertion_proof
.non_membership_proof
.root
.into(),
/* ProofVariantCircuit::Batch(batch_proof_circuit) => batch_proof_circuit.old_commitment, */
};

let old_root_scalar =
digest_to_scalar(&old_root.into()).map_err(|_| SynthesisError::Unsatisfiable)?;

let provided_old_commitment =
cs.alloc_input(|| "provided old commitment", || Ok(self.old_commitment))?;
let old_commitment_from_proofs =
cs.alloc(|| "old commitment from proofs", || Ok(old_root))?;
cs.alloc(|| "old commitment from proofs", || Ok(old_root_scalar))?;

// old_commitment_from_proofs * (1) = provided_old_commitment
cs.enforce(
Expand All @@ -99,7 +116,7 @@ impl Circuit<Scalar> for BatchMerkleProofCircuit {
|lc| lc + provided_old_commitment,
);

let mut new_commitment: Scalar = Scalar::zero();
let mut new_commitment: Scalar = Scalar::from(0);
for proof in self.proofs {
// update the new_commitment for every proof, applying the constraints of the circuit each time
match proof {
Expand All @@ -108,12 +125,11 @@ impl Circuit<Scalar> for BatchMerkleProofCircuit {
}
ProofVariantCircuit::Insert(insert_proof_circuit) => {
new_commitment = prove_insertion(cs, insert_proof_circuit)?;
}
ProofVariantCircuit::Batch(_) => {
// Batches cannot be recursively constructed
// TODO: Should they be able to?
return Err(SynthesisError::Unsatisfiable);
}
} /* ProofVariantCircuit::Batch(_) => {
// Batches cannot be recursively constructed
// TODO: Should they be able to?
return Err(SynthesisError::Unsatisfiable);
} */
}
}

Expand Down
141 changes: 50 additions & 91 deletions src/circuits/merkle_insertion.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use crate::{
circuits::{
utils::{recalculate_hash_as_scalar, unpack_and_process},
LessThanCircuit, UpdateCircuit,
},
circuits::{LessThanCircuit, UpdateCircuit},
error::PrismError,
nova::insert,
tree::InsertProof,
utils::{create_proof, verify_proof},
utils::{load_params_from_storage, verify_proof},
};
use anyhow::Result;
use bellperson::{Circuit, ConstraintSystem, SynthesisError};
use bellperson::{groth16, Circuit, ConstraintSystem, SynthesisError};
use blstrs::Scalar;
use indexed_merkle_tree::node::{LeafNode, Node};
use rand::rngs::OsRng;

use super::utils::{allocate_bits_to_binary_number, digest_to_scalar, verify_membership_proof};

/// Represents a circuit for proving the insertion of a new leaf into a the IMT.
///
Expand All @@ -23,25 +24,25 @@ pub struct InsertMerkleProofCircuit {
}

impl InsertMerkleProofCircuit {
pub fn new(proof: &InsertProof) -> Result<InsertMerkleProofCircuit, PrismError> {
let (non_membership_root, non_membership_path) =
unpack_and_process(&proof.non_membership_proof.merkle_proof)?;

let first_merkle_circuit = UpdateCircuit::new(&proof.first_proof)?;
let second_merkle_circuit = UpdateCircuit::new(&proof.second_proof)?;

Ok(InsertMerkleProofCircuit {
pub fn new(proof: InsertProof) -> Self {
Self {
insertion_proof: proof,
})
}
}

pub fn create_and_verify_snark(&self) -> Result<bool> {
let non_membership_proorf_sc =
Scalar::from_bytes(&self.insertion_proof.non_membership_proof.root).unwrap();
let first_proof_sc = Scalar::from_bytes(&self.insertion_proof.new_root).unwrap();
digest_to_scalar(&self.insertion_proof.non_membership_proof.root).unwrap();
let first_proof_sc = digest_to_scalar(&self.insertion_proof.new_root).unwrap();
let scalars: Vec<Scalar> = vec![];

let proof = create_proof(self);
let circuit = InsertMerkleProofCircuit::new(self.insertion_proof.clone());

let params = load_params_from_storage()?;

let rng = &mut OsRng;
let proof = groth16::create_random_proof(circuit, &params, rng)?;

verify_proof(&proof, &scalars)
}
}
Expand All @@ -60,36 +61,36 @@ pub fn prove_insertion<CS: ConstraintSystem<Scalar>>(
cs: &mut CS,
insert_proof: InsertProof,
) -> Result<Scalar, SynthesisError> {
// Step 1: Prove non-membership
// This ensures that the new leaf we're trying to insert doesn't already exist in the tree.
insert_proof.non_membership_proof.verify()?;

insert_proof.membership_proof.verify()?;

// Step 2: Update the existing leaf
// This step updates the 'next' pointer of an existing leaf to point to our new leaf.
/* let updated_root_after_existing_leaf_update = prove_update(
cs,
existing_leaf_update.old_root,
&existing_leaf_update.old_path,
existing_leaf_update.updated_root,
&existing_leaf_update.updated_path,
)?;
// Step 3: Activate the new leaf
// This step converts an inactive (empty) leaf into our new active leaf,
// effectively inserting the new data into the tree.
let new_root = prove_update(
cs,
updated_root_after_existing_leaf_update,
&new_leaf_activation.old_path,
new_leaf_activation.updated_root,
&new_leaf_activation.updated_path,
)?; */

let new_root_sc = Scalar::from_bytes(&insert_proof.new_root).unwrap();

Ok(new_root_sc)
let pre_insertion_scalar = digest_to_scalar(&insert_proof.non_membership_proof.root)
.map_err(|_| SynthesisError::Unsatisfiable)?;
let pre_insertion_root = cs.alloc(|| "pre_insertion_root", || Ok(pre_insertion_scalar))?;

let new_root_scalar =
digest_to_scalar(&insert_proof.new_root).map_err(|_| SynthesisError::Unsatisfiable)?;
let new_root_variable = cs.alloc(|| "new_root", || Ok(new_root_scalar))?;
let new_root_bits =
allocate_bits_to_binary_number(cs, insert_proof.membership_proof.root_hash().0.to_vec())?;

// z[0] is part of the nova specific code so maybe we have to give the last root as an input
cs.enforce(
|| "old root == non membership root",
|lc| lc + new_root_variable,
|lc| lc + CS::one(),
|lc| lc + new_root_variable,
);

insert_proof
.verify()
.map_err(|_| SynthesisError::Unsatisfiable)?;

let leaf = insert_proof
.membership_proof
.leaf()
.ok_or(SynthesisError::AssignmentMissing)?;

verify_membership_proof(cs, &insert_proof.membership_proof, &new_root_bits, leaf);

Ok(new_root_scalar)
}

/// Generates constraints to prove non-membership of a new leaf in the Merkle tree.
Expand All @@ -114,49 +115,7 @@ pub fn prove_non_membership<CS: ConstraintSystem<Scalar>>(
insertion_path: &[Node],
new_leaf_node: LeafNode,
) -> Result<(), SynthesisError> {
// Ensure that the label of the new leaf node lies between the first element of the path
// and its next pointer. This guarantees that no other node with a label between these values exists.
let existing_leaf_label: Scalar = insertion_path[0]
.get_label()
.try_into()
.map_err(|_| SynthesisError::Unsatisfiable)?;
let existing_leaf_next: Scalar = insertion_path[0]
.get_next()
.try_into()
.map_err(|_| SynthesisError::Unsatisfiable)?;
let new_leaf_label: Scalar = new_leaf_node
.label
.try_into()
.map_err(|_| SynthesisError::Unsatisfiable)?;

// Enforce: existing_leaf_label < new_leaf_label < existing_leaf_next
LessThanCircuit::new(existing_leaf_label, new_leaf_label)
.synthesize(cs)
.expect("Failed to synthesize existing_leaf_label < new_leaf_label");
LessThanCircuit::new(new_leaf_label, existing_leaf_next)
.synthesize(cs)
.expect("Failed to synthesize new_leaf_label < existing_leaf_next");

let allocated_pre_insertion_root =
cs.alloc(|| "pre_insertion_root", || Ok(pre_insertion_root))?;

let recalculated_root =
recalculate_hash_as_scalar(insertion_path).map_err(|_| SynthesisError::Unsatisfiable)?;

let allocated_recalculated_root = cs.alloc(
|| "recalculated_pre_insertion_root",
|| Ok(recalculated_root),
)?;

// Enforce that the provided pre-insertion root matches the recalculated root.
// This ensures that the ordered structure of the tree is maintained in the path.
// (allocated_pre_insertion_root) * (1) = allocated_recalculated_root
cs.enforce(
|| "pre_insertion_root_verification",
|lc| lc + allocated_pre_insertion_root,
|lc| lc + CS::one(),
|lc| lc + allocated_recalculated_root,
);
//TODO implement this function

Ok(())
}
Loading

0 comments on commit 2be4ec7

Please sign in to comment.