Skip to main content

PreimageCircuit

Proves knowledge of a Poseidon preimage: "I know x such that Poseidon(x) == hash."

  • 1 public input: hash
  • 1 private witness: preimage
  • Single constraint: poseidon(preimage) == hash

Struct​

#[derive(Clone)]
pub struct PreimageCircuit {
pub preimage: Option<Fr>,
}

Constraint Generation​

impl ConstraintSynthesizer<Fr> for PreimageCircuit {
fn generate_constraints(self, cs: ConstraintSystemRef<Fr>) -> Result<(), SynthesisError> {
// Public input: hash
let hash_pub = FpVar::new_input(cs.clone(), || {
let x = self.preimage.ok_or(SynthesisError::AssignmentMissing)?;
Ok(r14_poseidon::poseidon_hash(&[x]))
})?;

// Witness: preimage
let preimage_var = FpVar::new_witness(cs.clone(), || {
self.preimage.ok_or(SynthesisError::AssignmentMissing)
})?;

// Constraint: poseidon(preimage) == hash
let computed = poseidon_hash_var(cs, &[preimage_var])?;
computed.enforce_equal(&hash_pub)?;

Ok(())
}
}

The public input hash is computed from the witness during allocation. The circuit then independently recomputes it in-circuit using poseidon_hash_var and enforces equality.

Public Inputs​

pub struct PublicInputs {
pub hash: Fr,
}

impl PublicInputs {
pub fn to_vec(&self) -> Vec<Fr> {
vec![self.hash]
}
}

API​

setup(rng) -> (ProvingKey, VerifyingKey)​

Groth16 trusted setup with an empty circuit (witness = None).

pub fn setup<R: RngCore + CryptoRng>(
rng: &mut R,
) -> (ProvingKey<Bls12_381>, VerifyingKey<Bls12_381>)

prove(pk, preimage, rng) -> (Proof, PublicInputs)​

Hashes the preimage natively to produce the public hash, then generates the Groth16 proof.

pub fn prove<R: RngCore + CryptoRng>(
pk: &ProvingKey<Bls12_381>,
preimage: Fr,
rng: &mut R,
) -> (ark_groth16::Proof<Bls12_381>, PublicInputs)

verify_offchain(vk, proof, pi) -> bool​

Off-chain verification using PreparedVerifyingKey.

pub fn verify_offchain(
vk: &VerifyingKey<Bls12_381>,
proof: &ark_groth16::Proof<Bls12_381>,
pi: &PublicInputs,
) -> bool

constraint_count() -> usize​

Returns the R1CS constraint count. Expected range: 100-1000.

pub fn constraint_count() -> usize