# ZK Examples

## Example: PLONK

There are various options of what kind of front-end to use to design a ZK circuit. The [PLONK](https://eprint.iacr.org/2019/953.pdf) system is one such way. We will describe it below, and it will be a good way of preparing us for the full [PLONKish arithmetization](https://hackmd.io/@aztec-network/plonk-arithmetiization-air) used in [halo2](broken://pages/o7HNOSdFpTaZ5hh4ojtv), which is what Axiom uses in production.

A PLONK circuit consists of a table/matrix with the following fixed columns and nearly arbitrary number of rows:

<table><thead><tr><th width="79">a</th><th width="73">b</th><th width="71">c</th><th>q_L</th><th>q_R</th><th>q_M</th><th>q_C</th><th>q_O</th></tr></thead><tbody><tr><td>.</td><td>.</td><td>.</td><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>

where the numbers in the columns $$q\_L, \dotsc, q\_O$$ are **fixed** once and for all at compile time. Meanwhile the numbers in columns $$a, b, c$$ are called **witnesses** and specified by the prover each time a new proof is generated. What makes the circuit meaningful, and not a random collection of numbers, is that for each row $$i$$, the following equation is guaranteed to hold:

$$
q\_L \cdot a + q\_R \cdot b + q\_M \cdot a \cdot b + q\_C = q\_O \cdot c
$$

Since the $$q$$ columns are fixed once and for all, specifying these numbers allows you to "mold" the circuit to constrain the witnesses $$a, b, c$$ to perform certain computations.

For example, if you want to add $$a\_i + b\_i = c\_i$$ in row $$i$$, put:

<table><thead><tr><th width="87">a</th><th width="71">b</th><th width="77">c</th><th>q_L</th><th width="104">q_R</th><th>q_M</th><th>q_C</th><th>q_O</th></tr></thead><tbody><tr><td>a_i</td><td>b_i</td><td>c_i</td><td>1</td><td>1</td><td>0</td><td>0</td><td>1</td></tr></tbody></table>

To multiply $$a\_i \cdot b\_i = c\_i$$ in row $$i$$, put:

<table><thead><tr><th width="86">a</th><th width="74">b</th><th width="72">c</th><th width="106">q_L</th><th>q_R</th><th>q_M</th><th>q_C</th><th>q_O</th></tr></thead><tbody><tr><td>a_i</td><td>b_i</td><td>c_i</td><td>0</td><td>0</td><td>1</td><td>0</td><td>1</td></tr></tbody></table>

To force $$a\_i$$ to be a known constant $$C$$, put:

<table><thead><tr><th width="86">a</th><th width="74">b</th><th width="72">c</th><th>q_L</th><th>q_R</th><th>q_M</th><th>q_C</th><th>q_O</th></tr></thead><tbody><tr><td>a_i</td><td>*</td><td>*</td><td>1</td><td>0</td><td>0</td><td><span class="math">-C</span></td><td>0</td></tr></tbody></table>

Note that $$b\_i, c\_i$$ can be any numbers and it doesn't matter.

So far, we can use the above to do single line computations. There is one more ingredient: one can also specify once and for all that certain predetermined cells in the table above are always equal. For example, for some $$i\_0$$, we must have $$c\_{i\_0} = a\_{i\_0 + 1}$$. This now allows us to carry results of previous computations into new computations, "chaining" to create longer computations.

### Summary

To summarize, creating a ZK proof involves the following steps:

Once and for all, specify the circuit itself:

* Specify all cells in columns $$q\_L, q\_R, \dotsc, q\_O$$.
* Specify any equality constraints between cells.
* The verifier receives the above information in a *compressed* form.
* The prover holds onto a copy of the above information itself.

To submit a proof:

* Do the computation itself, i.e., generate the witnesses $$a\_i, b\_i, c\_i$$.

### Backend

While circuit design involves just filling out a table using some front end, to actually create a proof there is a backend that takes the PLONK table above and does a bunch of computations involving polynomial commitment schemes. This part is largely independent of the circuit design, but different backends lead to different performance characteristics, which become important to understand for production use cases.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://intrinsic-1.gitbook.io/axiomv2-sdk/zero-knowledge-proofs/zk-examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
