How to print enum values

Hey,

I was wondering if I want to print the values in enum, how does one do that?

A simple way to do it is #[derive(Debug)]. For example:

#[derive(Debug)]
enum Message {
    Text(String),
    Number(i32),
}

fn main() {
    let msg = Message::Number(5);    
    println!("{:?}", msg);
}

(Playground)

For more information, see the std::fmt documentation.

1 Like

Note that the output generated from this is unstable, so shouldn't be relied on for anything other than programmer-facing output.

If you need user-facing output you will typically implement Display for your enum, which unlike Debug must be implemented manually, for example:

use std::fmt::{self, Display, Formatter};

enum Priority {
    Low,
    Medium,
    High { reason: String },
}

impl Display for Priority {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::Low => write!(f, "Low priority"),
            Self::Medium => write!(f, "Medium priority"),
            Self::High { reason } => write!(f, "High priority: {}", reason),
        }
    }
}

let priority = Priority::High { reason: "xyz".to_owned() };
assert_eq!(priority.to_string(), "High priority: xyz");

Another way of generating stable, customizable output automatically is to use serde and #[derive(Serialize)].

1 Like

Ah alright. Actually for me,

let proof = groth16::create_random_proof(c, &params, &mut OsRng).unwrap();

I have this line of code I kind of want to see the elements of proof, upon googling I understand that the function create random proof outputs an enum, but it is important for me to obtain the proof as an output as I want to make changes to the proof and then check further if it still gets verified.

My entire code 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::*;
use std::time::{Duration,Instant};

const LEN: usize = 160;
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.
	//samples a u8 array of lenght LEN with initial value 42
	let preimage = [42; LEN];
	//for i in 1..LEN{
	//	println!("{}",preimage[i]);
	//}
	//digest is from built in function for verifier
	let hash = Sha256::digest(&preimage);
	//let hash = 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();
		
	//println!("Proof: {:?}", proof);
	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!("Time after proof generation: {:?}",time_prove_f - time_param_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!("Time after verification: {:?}",time_verify_f - time_prove_f);	

}
//===================================================================================
/// Our own SHA-256d gadget. Input and output are in little-endian bit order.
// Now this is sha256 gadget and only takes hash once
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
      Ok(mid
        .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)
    }
}


So it looks like your question is how to print a bellman::groth16::Proof<bls12_381::Bls12>.

The Proof<E> type does not implement the Debug trait or provide any other way to get human-readable output, but it does expose all of its fields, which have type E::G1Affine.

For your program, this type is bls12_381::G1Affine, which does implement Debug. So you can print the fields like this:

println!("Proof: a = {:?}, b = {:?}, c = {:?}", proof.a, proof.b, proof.c);

Oh okay, I will give it a go, thanks !!!

So can I assume that all the standard libraries in rust do have debug implemented? Like, here I can print directly the elements. So, when do I know such a situation works. I just wanna know if I do face similar condition again. I don't understand why it is not sort of standard way to print an enum value?

The standard way to print any value for logging/debugging is the Debug trait. You can look in the documentation to see which types implement Debug or Display. For example, it's listed in the bls12_381 docs here.

It's generally a good practice for library authors to implement Debug for all of their public types, but not all library authors follow this practice. If a library doesn't provide some way to inspect a type, you could always submit a bug report or patch to fix this. For example, you could ask the author of the bellman crate to implement Debug for Proof<E>.

(Also, just a note: Proof<E> and G1Affine are structs, not enums.)

Oh alright. I am sorry, I am not sure why I called it an enum.

Thanks !!!