Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
Every Circom circuit has two groups of signals: private (inputs the prover knows, verifier never sees) and public (inputs both sides know, plus the outputs). Getting this boundary right IS the zero-knowledge property. Accidentally making a secret public exposes your user's balance; accidentally making a public input private means the verifier can't check against external data. In Circom, public inputs are declared at the component main line. This is easy to get wrong and there's no compiler warning.
A preimage verifier: prove 'I know x such that Poseidon(x) = hash' where hash is PUBLIC and x is PRIVATE. Declaring which is which lives in the component main line: component main { public [hash] } = PreimageCheck();. Anything not listed is implicitly private.
pragma circom 2.1.6;
include "circomlib/circuits/poseidon.circom";
template PreimageCheck() {
signal input x; // private — the preimage
signal input hash; // PUBLIC — the commitment
component poseidon = Poseidon(1);
poseidon.inputs[0] <== x;
poseidon.out === hash; // the ZK statement: x hashes to the known value
}
component main { public [hash] } = PreimageCheck();
// Generate proof:
// input.json = { "x": 42, "hash": <Poseidon(42)> }
// Verifier sees only 'hash' — never 'x'.signal input r) representing a blinding factor. Observe that it doesn't appear in the public-signals list unless you explicitly declare it.