← Back to blog

Selective disclosure in 200 lines of Noir.

Rahul Vaidya · Apr 18, 2026 · 9 min read · Engineering

If you want to prove a statement about your data without revealing the data itself, zero-knowledge proofs are the tool. If you want to do it without three months of circuit engineering, Noir is the language. This post walks through the smallest useful proof in our stack: "I paid less than the regulatory cap" — in about 200 lines.

The setup

A transfer carries an encrypted amount c and a Pedersen commitment C. The sender wants to convince a public verifier that the committed amount is below a threshold T set by policy — for example, the $10,000 travel-rule threshold. Nobody should learn the actual amount.

The circuit

Noir gives us named witnesses and a assert-style constraint syntax. The body is almost embarrassingly short:

fn main(amount: Field, blinding: Field, threshold: pub Field, commitment: pub Field) {
    let expected = pedersen_commit([amount, blinding]);
    assert(expected == commitment);
    assert(amount as u64 < threshold as u64);
}

Four lines of logic. The verifier learns two things: the commitment is well-formed, and the committed value is below T. They learn nothing else.

Wiring it up

Our runtime compiles this to a PLONK proof (~280 ms on an M2 Pro). We attach the proof to the transaction, and the network refuses to accept the transfer unless it verifies. A regulator with subpoena power can later request the blinding factor from custody and reconstruct the exact amount — selective disclosure, by construction.

Next post: how to chain multiple assertions (amount cap + jurisdiction check + counterparty type) in a single proof without blowing up prover time. See you there.