13 / 19Module 2 – DappAdvanced
PLONK verification
This guide shows how the zkp-demo dapp verifies PLONK (Permutations over Lagrange-bases for Oecumenical Noninteractive arguments of Knowledge) proofs to protect the integrity of private token operations.
What is PLONK verification?
PLONK verification checks cryptographically that a zero-knowledge proof was produced correctly, without exposing the private data behind it. In this course, it confirms that private transfers, shielding, and unshielding are mathematically valid while the details stay hidden.
Core verification function: zkp.check_plonk_proof
Function overview
Chromia provides zkp.check_plonk_proof as a built-in function for verifying PLONK proofs inside blockchain operations:
/** * Checks whether or not the current transaction contains a valid PLONK proof. * * @param verification_key_id ID of the verification key that the proof must have been validated with * @param public_signals The public signals that the proof must have been validated with */function check_plonk_proof( verification_key_id: text, public_signals: list<big_integer>)Verification requirements
The dapp can only verify a proof if the transaction carries a zkp_plonk_verify GTX operation with these three parts:
- Verification key ID: Identifies a key that you have configured in
chromia.yml - PLONK proof: The proof data that the circuit produced
- Public signals: The public values the proof attests to
Dapp verification keys
Each operation in the course has its own verification key, for three keys in total:
# chromia.yml configurationzkp: plonk: verification_keys: private_transfer: # For anonymous transfers curve: bn128 nPublic: 5 shield_operation: # For converting public to private tokens curve: bn128 nPublic: 4 unshield_operation: # For converting private to public tokens curve: bn128 nPublic: 4Verification security features
Double-spending prevention
Verification also checks nullifiers, which stops a proof from being reused:
// Check if nullifier has been used beforerequire_not_exists(nullifier_registry @* { .nullifier == nullifier });// Register the nullifier after successful verificationcreate nullifier_registry(nullifier = nullifier, block_height = op_context.block_height);Signal integrity
When check_plonk_proof succeeds, you know that:
- The submitted public signals are exactly the ones the proof was built for
- The proof was produced under the correct circuit constraints
- Nothing was altered in transit
Circuit constraint validation
A valid PLONK proof gives a mathematical guarantee that:
- The prover holds the private key behind the commitment
- Arithmetic relationships, such as balances, are preserved
- The circuit logic ran correctly from start to finish
Together, these checks keep every private operation in the course both confidential and mathematically correct, and they underpin the secure private token transfer system.