use base64ct::{Base64UrlUnpadded, Encoding};
use bulletproofs::{BulletproofGens, PedersenGens, RangeProof};
use merlin::Transcript;
use rand::thread_rng;
use std::env;
use elastic_elgamal::{
group::Ristretto, Ciphertext, CiphertextWithValue, CommitmentEquivalenceProof, Keypair,
SecretKey,
};
const BULLETPROOFS_CAPACITY: usize = 64;
fn main() {
let mut rng = thread_rng();
let (receiver, _) = Keypair::<Ristretto>::generate(&mut rng).into_tuple();
let value = env::args().nth(1).map_or(424_242, |arg| {
arg.parse().expect("cannot parse value as `u64` integer")
});
let ciphertext = CiphertextWithValue::new(value, &receiver, &mut rng).generalize();
println!("Encrypted value: {value}");
let commitment_gens = PedersenGens::default();
let bulletproof_gens = BulletproofGens::new(BULLETPROOFS_CAPACITY, 1);
let blinding = SecretKey::generate(&mut rng);
let mut transcript = Transcript::new(b"equiv_and_bulletproof");
let (equiv_proof, commitment) = CommitmentEquivalenceProof::new(
&ciphertext,
&receiver,
&blinding,
commitment_gens.B_blinding,
&mut transcript,
&mut rng,
);
let (range_proof, same_commitment) = RangeProof::prove_single_with_rng(
&bulletproof_gens,
&commitment_gens,
&mut transcript,
value,
blinding.expose_scalar(),
BULLETPROOFS_CAPACITY,
&mut rng,
)
.expect("failed creating proof");
assert_eq!(commitment.compress(), same_commitment);
let ciphertext = Ciphertext::from(ciphertext);
let combined = serde_json::json!({
"ciphertext": &ciphertext,
"commitment": Base64UrlUnpadded::encode_string(same_commitment.as_bytes()),
"equiv": equiv_proof,
"range": Base64UrlUnpadded::encode_string(&range_proof.to_bytes()),
});
println!(
"Created proof: {}",
serde_json::to_string_pretty(&combined).unwrap()
);
let mut transcript = Transcript::new(b"equiv_and_bulletproof");
equiv_proof
.verify(
&ciphertext,
&receiver,
commitment,
commitment_gens.B_blinding,
&mut transcript,
)
.unwrap();
range_proof
.verify_single(
&bulletproof_gens,
&commitment_gens,
&mut transcript,
&same_commitment,
BULLETPROOFS_CAPACITY,
)
.unwrap();
println!("Proofs successfully verified!");
}