You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello! I am trying to implement a set membership proof circuit and I am having some trouble. I basically get the following error when generating the proof:
thread 'main' panicked at src/main.rs:217:70:
called `Result::unwrap()` on an `Err` value: IoError(Custom { kind: UnexpectedEof, error: "expected more bases from source" })note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Here's my main.rs code:
use bellman::{
gadgets::{
boolean::{AllocatedBit,Boolean},
multipack,
sha256::sha256,},
groth16,Circuit,ConstraintSystem,SynthesisError,};use bls12_381::Bls12;use ff::PrimeField;use merkle_tree::{NodeOrder,ProofListItem};use rand::rngs::OsRng;use sha2::{Digest,Sha256};usecrate::merkle_tree::MerkleTree;mod merkle_tree;mod utils;/// Our own SHA-256d gadget. Input and output are in little-endian bit order.fnsha256d<Scalar:PrimeField,CS:ConstraintSystem<Scalar>>(mutcs:CS,data:&[Boolean],) -> Result<Vec<Boolean>,SynthesisError>{// Flip endianness of each input bytelet input:Vec<_> = data
.chunks(8).map(|c| c.iter().rev()).flatten().cloned().collect();let res = sha256(cs.namespace(|| "SHA-256(input)"),&input)?;// Flip endianness of each output byteOk(res
.chunks(8).map(|c| c.iter().rev()).flatten().cloned().collect())}fnmerkle_proofd<Scalar:PrimeField,CS:ConstraintSystem<Scalar>>(mutcs:CS,mutproof_list:Vec<ProofListItem>,hashed_file_contents:&[Boolean],) -> Result<Vec<Boolean>,SynthesisError>{if proof_list.len() < 2{returnOk(Vec::new());}let res = contains_hash(
cs.namespace(|| "SHA-256(res)"),&mut proof_list,&hashed_file_contents,);match res {Ok(Boolean::Constant(false)) | Err(_) => {returnOk(Vec::new());}
_ => {}}while proof_list.len() != 1{let h1 = proof_list.pop().unwrap();let h2 = proof_list.pop().unwrap();match h2.order{Some(NodeOrder::Left) => {let combined = [&h2.hash[..],&h1.hash[..]].concat();let hash = sha256d(cs.namespace(|| "SHA-256(left_leaf)"),&combined).unwrap();
proof_list.push(ProofListItem::new(hash,None));}Some(NodeOrder::Right) => {let combined = [&h1.hash[..],&h2.hash[..]].concat();let hash = sha256d(cs.namespace(|| "SHA-256(right_leaf)"),&combined).unwrap();
proof_list.push(ProofListItem::new(hash,None));}None => {panic!("Should not be None");}}}Ok(proof_list.pop().unwrap().hash)}fnboolean_or<Scalar:PrimeField,CS:ConstraintSystem<Scalar>>(mutcs:CS,a:&Boolean,b:&Boolean,) -> Result<Boolean,SynthesisError>{let not_a = Boolean::not(a);let not_b = Boolean::not(b);let not_a_and_not_b = Boolean::and(cs.namespace(|| "not A AND not B"),¬_a,¬_b)?;Ok(Boolean::not(¬_a_and_not_b))}fncontains_hash<Scalar:PrimeField,CS:ConstraintSystem<Scalar>>(mutcs:CS,proof_list:&mutVec<ProofListItem>,hash:&[Boolean],) -> Result<Boolean,SynthesisError>{letmut found = Boolean::constant(false);// Initially, no match is found.for(i, item)in proof_list.iter().enumerate(){if item.hash.len() != hash.len(){continue;// Skip if lengths differ, cannot be equal.}letmut is_equal = Boolean::constant(true);// Assume equal until proven otherwise.for(j,(a, b))in item.hash.iter().zip(hash).enumerate(){let equal_bits =
Boolean::xor(cs.namespace(|| format!("bit {} in item {}", j, i)), a, b)?;let not_equal_bits = Boolean::not(&equal_bits);
is_equal = Boolean::and(
cs.namespace(|| format!("aggregate equality for item {}", i)),&is_equal,¬_equal_bits,)?;}// Aggregate the results with OR across all items using the custom OR function
found = boolean_or(
cs.namespace(|| format!("aggregate found status after item {}", i)),&found,&is_equal,)?;}Ok(found)}structMerkleProofCircuit{proof_list:Option<Vec<ProofListItem>>,hashed_file_contents:Option<Vec<u8>>,}impl<Scalar:PrimeField>Circuit<Scalar>forMerkleProofCircuit{fnsynthesize<CS:ConstraintSystem<Scalar>>(self,cs:&mutCS) -> Result<(),SynthesisError>{let proof_list = self.proof_list.unwrap_or_default();let bit_values = ifletSome(hashed_file_contents) = self.hashed_file_contents{
hashed_file_contents
.into_iter().map(|byte| (0..8).map(move |i| (byte >> i)&1u8 == 1u8)).flatten().map(|b| Some(b)).collect()}else{vec![None; 32 * 8]};assert_eq!(bit_values.len(), 32 * 8);// Witness the bits of the preimage.let hashed_file_content_bits = bit_values
.into_iter().enumerate()// Allocate each bit..map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("preimage bit {}", i)), b))// Convert the AllocatedBits into Booleans (required for the sha256 gadget)..map(|b| b.map(Boolean::from)).collect::<Result<Vec<_>,_>>()?;// Now process proof_list, merkle_root, and file_contents in the merkle_proofd function// Ensure merkle_proofd can handle dummy values correctlylet merkle_root = merkle_proofd(
cs.namespace(|| "merkle_root"),
proof_list,&hashed_file_content_bits,)?;
multipack::pack_into_inputs(cs.namespace(|| "pack hash"),&merkle_root)}}fnmain(){let params = {let c = MerkleProofCircuit{proof_list:None,hashed_file_contents:None,};
groth16::generate_random_parameters::<Bls12,_,_>(c,&mutOsRng).unwrap()};let pvk = groth16::prepare_verifying_key(¶ms.vk);// These are the factors we are proving knowledge oflet files = (1..=8).map(|i| {let file_name = format!("file{}.txt", i);let file_content = format!("File {} contents", i).into_bytes();(file_name, file_content)}).collect();let merkle_tree = MerkleTree::new(&files);let merkle_root = merkle_tree.get_root_hash();let merkle_proof = merkle_tree
.generate_merkle_proof("file1.txt",&files).unwrap();let file_contents = files.get("file1.txt").unwrap().clone();let hashed_file_contents:Vec<u8> = Sha256::digest(&file_contents).to_vec();// Create an instance of our circuit (with the preimage as a witness).let c = MerkleProofCircuit{proof_list:Some(merkle_proof),hashed_file_contents:Some(hashed_file_contents),};// Pack the hash as inputs for proof verification.let hash_bits = multipack::bytes_to_bits_le(&merkle_root);let inputs = multipack::compute_multipacking(&hash_bits);let proof = groth16::create_random_proof(c,¶ms,&mutOsRng).unwrap();// assert!(groth16::verify_proof(&pvk, &proof, &[public_input]).is_ok());println!("{:?}", groth16::verify_proof(&pvk, &proof, &inputs));println!("Merkle Tree Proof verified!");}
Can anyone guide me to how to accomplish this? I didn't find any documentation or anything like that just a sha256 example and tried to modify that. I have a very high level understanding of how ZKP works so if its required to dig deeper please let me know. The circuit is supposed to implement the computation of a merkle root from a set of leaves. I assume that root is a public output and the verifier can check their merkle root against it?
The text was updated successfully, but these errors were encountered:
Hello! I am trying to implement a set membership proof circuit and I am having some trouble. I basically get the following error when generating the proof:
Here's my
main.rs
code:and some auxiliary items
Can anyone guide me to how to accomplish this? I didn't find any documentation or anything like that just a sha256 example and tried to modify that. I have a very high level understanding of how ZKP works so if its required to dig deeper please let me know. The circuit is supposed to implement the computation of a merkle root from a set of leaves. I assume that root is a public output and the verifier can check their merkle root against it?
The text was updated successfully, but these errors were encountered: