Writing Arithmetic Circuits

πŸ’‘ Circuit Structure: Original circuit code consists of two key parts:

  • πŸ’» Computation: Determines how values are calculated during proof generation
  • πŸ”’ Constraints: Verifies the correctness of those calculations

While we typically write these together in our code, the compiler separates them. The constraints are fixed during the setup phase and become the core verification logic, while the computation part runs with private and public inputs during each proof generation.

Circuit Compilation Plonk Script

Plonkish Arithmetic Circuits

Plonkish arithmetic circuits are different from R1CS-like circuits in that they are designed to resemble a table, rather than a simple list of computations. This design makes the circuit more complex to reason about, but also provides some advantages in terms of computational efficiency.

  • πŸ“Š Table Design

    • A column is a polynomial
    • A row is a root of unity
    • A cell is the evaluation of a polynomial at a root of unity
  • πŸ“‹ Column Types

    • πŸ”’ Advice: Advice columns, private inputs and intermediate data, all private data
    • πŸ“Œ Fixed: Constant columns, fixed values when creating the circuit, public data
    • πŸ”˜ Selector: Selector columns, virtual columns, essentially constant columns, binary used to switch custom gate circuits
    • πŸ“’ Instance: Instance columns, store public inputs (and public outputs)
  • πŸ”„ Arithmetic Circuit

    • ✨ Custom gates
    • πŸ” Lookup table
    • πŸ”— Copy constraints
Plonkish Constraints Overview

Custom Gates

  • ✨ Custom gates are expressions that constrain multiple cells
  • πŸ”˜ Selectors are essentially fixed constant columns. They are boolean, used to enable or disable gates
  • πŸ”„ We can reference cells from the previous row, next row, but max to 7 in halo2.
  • πŸ“ In our examples, we use b[1] to represent the next row
Custom Gate Constraints

Copy Constraints

  • πŸ”— Copy constraints bind two cells together, ensuring their values must be the same
  • ⚑ These are the most efficient constraints. We can use them as much as we want
Copy Constraints

Lookup Tables

Lookup tables are very efficient for range checks and bit operations

⚑ XOR Example:

Instead of using complex constraints to implement XOR, we can use a lookup table:

aba βŠ• b
000
011
101
110

Using a lookup gate, we can verify that for any inputs (a, b) and output c, the triplet (a, b, c) appears in our XOR truth table, making bit operations much more efficient than implementing them with arithmetic constraints.

Lookup Tables

Gate Tricks

🎨 Writing circuits in Plonkish is totally different from writing circuits in R1CS (Circom) or zkVM program.

Here are some tricks that might help you write circuits in Plonkish.

Limiting Values

Sometimes we need to limit a value to a specific set of values. For example, we might want to ensure that a value is either 1, 2, or 3.

πŸ”’ Limiting Value Gate:

sΓ—(aβˆ’1)(aβˆ’2)(aβˆ’3)=0s \times (a - 1)(a - 2)(a - 3) = 0
  • This gate enforces that aa can only take one of the values 1, 2, or 3 when s=1s = 1.
  • If a=1a = 1, the first term (aβˆ’1)(a - 1) becomes 0, making the entire expression 0.
  • If a=2a = 2, the second term (aβˆ’2)(a - 2) becomes 0, making the entire expression 0.
  • If a=4a = 4 or a=99a = 99, none of the terms become 0, so the expression will not be 0.
  • Similarly, if aa is any other value, the gate will not satisfy the equation unless s=0s = 0, which means the selector is disabled.
Limiting Value Gate

If-Else Condition

Implementing conditional logic in ZK circuits requires special techniques. Here’s how to implement an if-else condition:

πŸ”€ Conditional Output Gate:

sΓ—(cΓ—a+(1βˆ’c)Γ—bβˆ’out)=0s \times (c \times a + (1 - c) \times b - out) = 0
  • This gate enforces that the output outout is either aa or bb depending on the value of cc.
  • If c=1c = 1, the output will be aa.
  • If c=0c = 0, the output will be bb.

πŸ” Selector Validity Gate (Boolean Gate):

sΓ—cΓ—(1βˆ’c)=0s \times c \times (1 - c) = 0
  • This gate ensures that cc is a valid boolean value (either 0 or 1).

Together, these gates implement the conditional logic ifΒ cΒ thenΒ aΒ elseΒ b\text{if}\ c\ \text{then}\ a\ \text{else}\ b.

If-Else Condition

Is-Zero Check

Checking if a value is zero is a common operation in ZK circuits, but it requires special handling:

πŸ” Is-Zero Definition:

The invinv value is defined as:

inv={0ifΒ input=01inputelseinv = \begin{cases} 0 & \text{if } \text{input} = 0 \\ \frac{1}{\text{input}} & \text{else} \end{cases}

The output is calculated as:

output=βˆ’inputΓ—inv+1\text{output} = -\text{input} \times \text{inv} + 1

With the constraint:

inputΓ—output=0\text{input} \times \text{output} = 0

This technique allows us to check if a value is zero and produce a boolean result (1 for zero, 0 for non-zero).

Case input inv output input Γ— output
Non-zero input 4 1/4 0 0
Zero input 0 0 1 0
Non-zero input (malicious inv) 4 1/5 1/5 4/5
Zero input (malicious inv) 0 1/5 1 0

If-Equal Condition

The if-equal condition implements: out = a == b ? c : (a - b). This technique combined the tricks from is-zero and if-else.

πŸ”€ Gate 1: Equality Check (via is-zero)

sΓ—(aβˆ’b)Γ—(1βˆ’((aβˆ’b)Γ—inv))=0s \times (a - b) \times (1 - ((a - b) \times inv)) = 0

  • This gate ensures that if a=ba = b, the expression becomes 0.
  • From is-zero, we know that input=aβˆ’binput = a - b and invinv is the inverse of aβˆ’ba - b.
  • When aβ‰ ba \neq b, the gate enforces the calculation based on aβˆ’ba - b and its inverse.

πŸ”€ Gate 2: Output Assignment

sΓ—(1βˆ’(aβˆ’b)Γ—inv)Γ—(outβˆ’c)=0s \times (1 - (a - b) \times inv) \times (out - c) = 0

  • This gate enforces that when a=ba = b, the output outout must equal cc.
  • If aβ‰ ba \neq b, this constraint is automatically satisfied.

πŸ”€ Gate 3: Alternative Output

sΓ—(1βˆ’(1βˆ’(aβˆ’b)Γ—inv))Γ—(outβˆ’(aβˆ’b))=0s \times (1 - (1 - (a - b) \times inv)) \times (out - (a - b)) = 0

  • This gate enforces that when aβ‰ ba \neq b, the output outout is set to aβˆ’ba - b.
  • If a=ba = b, this constraint is automatically satisfied.

πŸ’‘ Together, these three gates implement the conditional structure:

  • When a=ba = b: The output outout is set to cc.
  • When aβ‰ ba \neq b: The output outout is set to aβˆ’ba - b.
If-Equal Condition
Under Construction

More tricks to come

More circuit tricks and techniques will be added soon.