> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metalntwx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Proof and Verification

> How verification keys identify circuit rules, how a sender proof is constructed, and how the pool verifies proofs against current state

## The circuit and its verification key

[Privacy Guarantees](https://docs.metalntwx.com/learn/mip410/privacy-guarantees.md#zero-knowledge-proofs-in-mip410)
introduces a circuit as the mathematical constraints expressing the rules to
be proven. MIP410's circuits are written in Noir and compiled into a form the proving
software can execute. The proving software,
[Barretenberg](https://barretenberg.aztec.network/docs/getting_started/),
generates a corresponding verification key for UltraHonk, the proof system
MIP410 uses, which lets the verifier check a proof that the private inputs
satisfy those rules for the supplied public inputs. The key contains numerical
parameters derived from the circuit's fixed structure. It can be reused to
verify proofs for many transactions, each with its own witness and public inputs.

The circuit verification key has a different role from the spend-verification
key `ak` introduced in [Keys and Addresses](https://docs.metalntwx.com/learn/mip410/key-and-addresses.md#key-hierarchy).
Inside the circuit, `ak` verifies the spending-key signature authorizing the
payment. The verifier uses the circuit verification key to check the resulting
proof, including that signature check. This verification key is public and shared across wallets using that circuit.

Verification requires the circuit's verification key, the proof, and its public
inputs. The key supplies the circuit-specific parameters UltraHonk needs to check
the proof without receiving the witness or executing the circuit on private
payment data. Metal supplies these parameters to a shared verifier that serves
different circuits. To ensure each transaction is checked against the expected
circuit, MIP410 configures circuit IDs for shielding, payment initiation,
payment resolution, unshielding, and policy-wrapper verification. Each circuit
ID identifies the backend and exact verification-key bytes. When requesting verification,
the pool selects the circuit ID required for that proof type.

## Constructing a proof for a payment

For payment initiation, the prover assembles the input note openings and
Merkle paths, the recipient and change note details, and the spending
authorization. Its private inputs also include the spend-verification key and
nullifier key, sanctions evidence, the identifier of the recipient virtual
asset service provider (VASP), and the payment payload. The prover also supplies the public inputs against which the
proof will be verified. These include the chain ID, pool contract address,
the note tree's Merkle root, input lock IDs, payment effect hash, recipient
VASP binding commitment, nonce, deadline, payload commitment, and sanctions root.
The payload commitment is a hash binding the private payment record and
associated identifiers to the payment.

The proving software executes the compiled circuit with these inputs to
compute the witness values needed for proof generation. The circuit enforces
the relationships between them:

| Check | Relationship established |
| - | - |
| Note membership | The input note openings produce commitments whose Merkle paths reach the note tree's Merkle root supplied as a public input. |
| Ownership and authorization | The input notes' diversified addresses derive from the supplied spend-verification and nullifier keys, and the spending-key signature verified using `ak` authorizes the initiation's public inputs. |
| Value conservation | The input notes use the same asset, and their amounts equal the recipient amount plus any change. |
| Input and output identifiers | The input lock IDs and nullifiers derive from the same input notes. Those nullifiers and the output note commitments reproduce the public payment effect hash. |
| Payment context | The recipient VASP binding commitment and payload commitment match this payment, and the sender passes the sanctions check against the supplied root. |

Barretenberg uses the compiled circuit and completed witness to generate the
UltraHonk proof. The submitter includes the proof in the initiation transaction.
The private inputs remain offchain. Initiation also requires a separate
policy-wrapper proof, described in
[Privacy-Preserving Policy](https://docs.metalntwx.com/learn/mip410/privacy-preserving-policy.md).

## Onchain verification

The pool constructs the public inputs used to verify each submitted proof.
The chain ID and pool contract address come from the execution environment.
Other inputs come from the transaction parameters and, where applicable, the
pool's stored records. For example, the recipient proof used for resolution is
checked against values recorded in the payment's hold. The pool selects the verification key
configured for the required proof type. It supplies the corresponding
circuit ID to the [Circuit Registry](https://docs.metalntwx.com/reference/privacy/circuit-registry.md),
which retrieves the registered key. The registry forwards the key, proof, and
public inputs to Metal's native UltraHonk verifier at `0xF2`. Validators
perform this verification as part of executing the transaction.

The pool also checks whether its current state permits the transaction.
For transactions that use existing notes, the pool checks their availability
against its onchain records. A payment resolution requires a hold that is still
pending and within its deadline. The pool also checks that roots referenced by
the proofs are accepted. A transaction succeeds only when all required proofs
and execution checks pass. Payment initiation requires a sender proof, while
resolution requires a recipient proof. Both stages also require a policy-wrapper
proof. Each proof is
verified using its own configured circuit ID and public inputs. If any required
proof or check fails, the transaction reverts and the pool's changes are rolled
back.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.