Bellman example not working

Hi, I am kind of confused at the moment. I am testing the code in bellman - Rust with some slight changes and the code I get is,

use bellman::{gadgets::{boolean::{AllocatedBit, Boolean},multipack,sha256::sha256,},groth16, Circuit, ConstraintSystem, SynthesisError};
use bls12_381::Bls12;//field used
use ff::PrimeField;
use pairing::Engine;
use rand::rngs::OsRng;
use sha2::{Digest, Sha256};
use bitvec::prelude::*;


struct MyCircuit {
    /// The input to SHA-256d we are proving that we know. Set to `None` when we
    /// are verifying a proof (and do not have the witness data).
	preimage: Option<[u8; 80]>,
}

fn main(){


	// Create parameters for our circuit. In a production deployment these would
	// be generated securely using a multiparty computation.
	let params = {
		let c = MyCircuit { preimage: None };
		groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
	};

	// Prepare the verification key (for proof verification).
	let pvk = groth16::prepare_verifying_key(&params.vk);

	// Pick a preimage and compute its hash.
	let preimage = [42; 80];
	let hash = Sha256::digest(&Sha256::digest(&preimage));

	// Create an instance of our circuit (with the preimage as a witness).
	let c = MyCircuit {
		preimage: Some(preimage),
	};

	// Create a Groth16 proof with our parameters.
	let proof = groth16::create_random_proof(c, &params, &mut OsRng).unwrap();

	// Pack the hash as inputs for proof verification.
	let hash_bits = multipack::bytes_to_bits_le(&hash);
	let inputs = multipack::compute_multipacking(&hash_bits);

	// Check the proof!
	assert!(groth16::verify_proof(&pvk, &proof, &inputs).is_ok());
}
//===================================================================================
//SHA256 gadget
fn sha256d<Scalar: PrimeField, CS: ConstraintSystem<Scalar>>(mut cs: CS,data: &[Boolean],) -> Result<Vec<Boolean>, SynthesisError> {
    // Flip endianness of each input byte
    let input: Vec<_> = data.chunks(8).map(|c| c.iter().rev()).flatten().cloned().collect();

    let mid = sha256(cs.namespace(|| "SHA-256(input)"), &input);
    let res = sha256(cs.namespace(|| "SHA-256(mid)"), &mid);

    // Flip endianness of each output byte
    Ok(res.chunks(8).map(|c| c.iter().rev()).flatten().cloned().collect())
}


//====================================================================================
// SHA256 circuit

impl<Scalar: PrimeField> Circuit<Scalar> for MyCircuit {
	fn synthesize<CS: ConstraintSystem<Scalar>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
	// Compute the values for the bits of the preimage. If we are verifying a proof,
        // we still need to create the same constraints, so we return an equivalent-size
        // Vec of None (indicating that the value of each bit is unknown).
        let bit_values = if let Some(preimage) = self.preimage {
            preimage.into_iter().map(|byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8)).flatten().map(|b| Some(b)).collect()
        } else {
            vec![None; 80 * 8]
        };
        assert_eq!(bit_values.len(), 80 * 8);

        // Witness the bits of the preimage.
	   // Allocate each bit.
        let preimage_bits = bit_values.into_iter().enumerate().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<_>, _>>()?;

        // Compute hash = SHA-256d(preimage).
        let hash = sha256d(cs.namespace(|| "SHA-256d(preimage)"), &preimage_bits)?;

        // Expose the vector of 32 boolean variables as compact public inputs.
        multipack::pack_into_inputs(cs.namespace(|| "pack hash"), &hash)
    }
}

But even though I added all the libraries on which dependency is based, I keep getting error that cannot compile bitvec and more confusing is that I did cargo add bitvec and then went to try again but it still does not work, so I still do not get it or understand what exactly is wrong, any help will be appreciated.
Thanks!

Can you paste the compiler output when it tries to compile bitvec? (If your IDE does not show you detailed compile errors from bitvec, try running cargo build in a terminal, in your project directory.)

One problem might be that bellman is not using the latest version of bitvec.

Try editing your Cargo.toml file to specify bitvec = "0.20.0", so you are using the same version as bellman.

I ran cargo build and the errors are like really long but the same ones, weird part is the error is not actually in my code but in some other library as I understand, I am confused if I have to add more things in the library.

~/project/sha$ cargo build
   Compiling bitvec v0.20.1
error[E0034]: multiple applicable items in scope
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/bitvec-0.20.1/src/field.rs:801:12
    |
801 |                     if M::BITS > T::Mem::BITS {
    |                           ^^^^ multiple `BITS` found
    |
note: candidate #1 is defined in the trait `BitMemory`
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/bitvec-0.20.1/src/mem.rs:44:2
    |
44  |     const BITS: u8 = mem::size_of::<Self>() as u8 * 8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in the trait `IsNumber`
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/funty-1.2.0/src/lib.rs:144:2
    |
144 |     const BITS: u32;
    |     ^^^^^^^^^^^^^^^^
help: disambiguate the associated constant for candidate #1
    |
801 |                     if BitMemory::BITS > T::Mem::BITS {
    |                        ^^^^^^^^^^^^^^^
help: disambiguate the associated constant for candidate #2
    |
801 |                     if IsNumber::BITS > T::Mem::BITS {
    |                        ^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/bitvec-0.20.1/src/field.rs:801:19
    |
765 |     fn load_le<M>(&self) -> M
    |                - this type parameter
...
801 |                     if M::BITS > T::Mem::BITS {
    |                                  ^^^^^^^^^^^^ expected type parameter `M`, found `u8`
    |
    = note: expected type parameter `M`
                         found type `u8`

error[E0034]: multiple applicable items in scope
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/bitvec-0.20.1/src/field.rs:809:12
    |
809 |                     if M::BITS > T::Mem::BITS - shamt {
    |                           ^^^^ multiple `BITS` found
    |
note: candidate #1 is defined in the trait `BitMemory`
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/bitvec-0.20.1/src/mem.rs:44:2
    |
44  |     const BITS: u8 = mem::size_of::<Self>() as u8 * 8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in the trait `IsNumber`
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/funty-1.2.0/src/lib.rs:144:2
    |
144 |     const BITS: u32;
    |     ^^^^^^^^^^^^^^^^
help: disambiguate the associated constant for candidate #1
    |
809 |                     if BitMemory::BITS > T::Mem::BITS - shamt {
    |                        ^^^^^^^^^^^^^^^
help: disambiguate the associated constant for candidate #2
    |
809 |                     if IsNumber::BITS > T::Mem::BITS - shamt {
    |                        ^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> /home/smith/.cargo/registry/src/github.com-1ecc6299db9ec823/bitvec-0.20.1/src/field.rs:809:19
    |
765 |     fn load_le<M>(&self) -> M
    |                - this type parameter
...
809 |                     if M::BITS > T::Mem::BITS - shamt {
    |                                  ^^^^^^^^^^^^^^^^^^^^ expected type parameter `M`, found `u8`
    |
    = note: expected type parameter `M`
                         found type `u8`
.....
error: aborting due to 60 previous errors

Some errors have detailed explanations: E0034, E0308.
For more information about an error, try `rustc --explain E0034`.
error: could not compile `bitvec`

To learn more, run the command again with --verbose.

It looks like there's a conflict between bitvec 0.20.1 and funty 1.2.0 (which bitvec depends on). The workaround for now is to downgrade to the previous version of funty by running this command in your project directory:

cargo update -p funty --precise 1.1.0

The long-term fix is for bellman and its dependencies to update their code to use bitvec version 0.21.

Details of the problem here: https://github.com/bitvecto-rs/bitvec/issues/105

I get

~/project/sha$ cargo update -p bitvec --precise 0.20.0
    Updating crates.io index
    Updating bitvec v0.20.1 -> v0.20.0
    Updating funty v1.1.0 -> v1.2.0

and when I try to do the command you suggested I get,

~/project/sha$ cargo update -p funty --precise 0.20.0
    Updating crates.io index
error: no matching package named `funty` found
location searched: registry `https://github.com/rust-lang/crates.io-index`
required by package `sha v0.1.0

But, I still get the same errors.

The command to run is:

cargo update -p funty --precise 1.1.0
1 Like

Yup that part is sorted. Sorry was stupid with the command I wrote.

Hey,

I was working with the code and it still does not run, which does not honestly make sense to me,

use bellman::{gadgets::{boolean::{AllocatedBit, Boolean},multipack,sha256::sha256,},groth16, Circuit, ConstraintSystem, SynthesisError};
use bls12_381::Bls12;//field used
use ff::PrimeField;
//use pairing::Engine;
use rand::rngs::OsRng;
use sha2::{Digest, Sha256};
//use bitvec::prelude::*;
use std::time::{Duration,Instant};

const LEN: usize = 80;
struct MyCircuit {
    /// The input to SHA-256d we are proving that we know. Set to `None` when we
    /// are verifying a proof (and do not have the witness data).
	preimage: Option<[u8; LEN]>,
}
 
fn main(){


	// Create parameters for our circuit. In a production deployment these would
	// be generated securely using a multiparty computation.
	println!("Parameter Generation...");
	let mut time_param = Duration::new(0,0);
	let mut time_prove = Duration::new(0,0);
	let mut time_verify = Duration::new(0,0);
	let start = Instant::now();	
	let params = {
		let c = MyCircuit { preimage: None };
		groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
	};
	//time accounting
	time_param += start.elapsed();
	let time_param_f =
        	 time_param.subsec_nanos() as f64 / 1_000_000_000f64 + (time_param.as_secs() as f64);

	println!("Parameter generation time: {:?}",time_param_f);	
	// Prepare the verification key (for proof verification).
	let pvk = groth16::prepare_verifying_key(&params.vk);

	// Pick a preimage and compute its hash.
	let preimage = [42; LEN];
	let hash = Sha256::digest(&Sha256::digest(&preimage));

	// Create an instance of our circuit (with the preimage as a witness).
	let c = MyCircuit {
		preimage: Some(preimage),
	};
	println!("Generating Proof...");
	// Create a Groth16 proof with our parameters.
	let proof = groth16::create_random_proof(c, &params, &mut OsRng).unwrap();
	time_prove += start.elapsed();
	let time_prove_f =
        	 time_prove.subsec_nanos() as f64 / 1_000_000_000f64 + (time_prove.as_secs() as f64);

	println!("Proof generation time: {:?}",time_prove_f);	

	// Pack the hash as inputs for proof verification.
	let hash_bits = multipack::bytes_to_bits_le(&hash);
	let inputs = multipack::compute_multipacking(&hash_bits);
	println!("Verification time...");
	// Check the proof!
	assert!(groth16::verify_proof(&pvk, &proof, &inputs).is_ok());
	time_verify += start.elapsed();
	let time_verify_f =
        	 time_verify.subsec_nanos() as f64 / 1_000_000_000f64 + (time_verify.as_secs() as f64);

	println!("Verification time: {:?}",time_verify_f);	

}
//===================================================================================
/// Our own SHA-256d gadget. Input and output are in little-endian bit order.
fn sha256d<Scalar: PrimeField, CS: ConstraintSystem<Scalar>>(
    mut cs: CS,
    data: &[Boolean],
) -> Result<Vec<Boolean>, SynthesisError> {
    // Flip endianness of each input byte
    let input: Vec<_> = data
        .chunks(8)
        .map(|c| c.iter().rev())
        .flatten()
        .cloned()
        .collect();

    let mid = sha256(cs.namespace(|| "SHA-256(input)"), &input)?;
    let res = sha256(cs.namespace(|| "SHA-256(mid)"), &mid)?;

    // Flip endianness of each output byte
    Ok(res
        .chunks(8)
        .map(|c| c.iter().rev())
        .flatten()
        .cloned()
        .collect())
}

//====================================================================================
// SHA256 circuit

impl<Scalar: PrimeField> Circuit<Scalar> for MyCircuit {
	fn synthesize<CS: ConstraintSystem<Scalar>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
	// Compute the values for the bits of the preimage. If we are verifying a proof,
        // we still need to create the same constraints, so we return an equivalent-size
        // Vec of None (indicating that the value of each bit is unknown).
        let bit_values = if let Some(preimage) = self.preimage {
            preimage.iter().map(|byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8)).flatten().map(|b| Some(b)).collect()
        } else {
            vec![None; LEN * 8]
        };
        assert_eq!(bit_values.len(), LEN * 8);

        // Witness the bits of the preimage.
	   // Allocate each bit.
        let preimage_bits = bit_values.into_iter().enumerate().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<_>, _>>()?;

        // Compute hash = SHA-256d(preimage).
        let hash = sha256d(cs.namespace(|| "SHA-256d(preimage)"), &preimage_bits)?;

        // Expose the vector of 32 boolean variables as compact public inputs.
        multipack::pack_into_inputs(cs.namespace(|| "pack hash"), &hash)
    }
}


It goes on to be,

~/project/sha$ cargo build
   Compiling sha v0.1.0 (/home/smith/project/sha)
    Finished dev [unoptimized + debuginfo] target(s) in 4.38s
...
~/project/sha$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/sha`
Parameter Generation...

Kindly let me know where I am going wrong.

Try running with optimizations enabled (cargo run --release).

On my Core i9 laptop in release mode, I get:

Parameter Generation...
Parameter generation time: 9.474669851
Generating Proof...
Proof generation time: 10.539158075
Verification time...
Verification time: 10.543371547

Thanks!!

A post was split to a new topic: How to print enum values

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.