use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use group::Group;
use rand::rngs::OsRng;
use sigma_proofs::{
composition::{ComposedRelation, ComposedWitness},
errors::Error,
LinearRelation,
};
type G = RistrettoPoint;
type ProofResult<T> = Result<T, Error>;
#[allow(non_snake_case)]
fn create_relation(P1: G, P2: G, Q: G, H: G) -> ComposedRelation<G> {
let mut rel1 = LinearRelation::<G>::new();
let x1 = rel1.allocate_scalar();
let G1 = rel1.allocate_element();
let P1_var = rel1.allocate_eq(x1 * G1);
rel1.set_element(G1, G::generator());
rel1.set_element(P1_var, P1);
let mut rel2 = LinearRelation::<G>::new();
let x2 = rel2.allocate_scalar();
let G2 = rel2.allocate_element();
let H_var = rel2.allocate_element();
let P2_var = rel2.allocate_eq(x2 * G2);
let Q_var = rel2.allocate_eq(x2 * H_var);
rel2.set_element(G2, G::generator());
rel2.set_element(H_var, H);
rel2.set_element(P2_var, P2);
rel2.set_element(Q_var, Q);
ComposedRelation::or([rel1.canonical().unwrap(), rel2.canonical().unwrap()])
}
#[allow(non_snake_case)]
fn prove(P1: G, x2: Scalar, H: G) -> ProofResult<Vec<u8>> {
let P2 = G::generator() * x2;
let Q = H * x2;
let instance = create_relation(P1, P2, Q, H);
let witness = ComposedWitness::Or(vec![
ComposedWitness::Simple(vec![Scalar::from(0u64)]),
ComposedWitness::Simple(vec![x2]),
]);
let nizk = instance.into_nizk(b"or_proof_example");
nizk.prove_batchable(&witness, &mut OsRng)
}
#[allow(non_snake_case)]
fn verify(P1: G, P2: G, Q: G, H: G, proof: &[u8]) -> ProofResult<()> {
let protocol = create_relation(P1, P2, Q, H);
let nizk = protocol.into_nizk(b"or_proof_example");
nizk.verify_batchable(proof)
}
#[allow(non_snake_case)]
fn main() {
let x1 = Scalar::random(&mut OsRng);
let x2 = Scalar::random(&mut OsRng);
let H = G::random(&mut OsRng);
let P1 = G::generator() * x1; let P2 = G::generator() * x2; let Q = H * x2;
println!("OR-proof example: Proving knowledge of x1 OR x2");
println!("(We only know x2, not x1)");
match prove(P1, x2, H) {
Ok(proof) => {
println!("Proof generated successfully");
println!("Proof (hex): {}", hex::encode(&proof));
match verify(P1, P2, Q, H, &proof) {
Ok(()) => println!("✓ Proof verified successfully!"),
Err(e) => println!("✗ Proof verification failed: {e:?}"),
}
}
Err(e) => println!("✗ Failed to generate proof: {e:?}"),
}
}