Hi all, I heard a lot of custom gates in plonk, but can’t find anything about what it is, how it does, and any related projects that use it. I would be every thankful if someone could point that out.

In “vanilla Plonk”, the prover convinces the verifier that this constraint vanishes on H:

The idea of custom gates is just to generalize this. As a basic example, if we wanted to evaluate MiMC more efficiently, we could add a cubic term:

We could then make the i’th gate a cube gate by setting (q_{L3})_i = 1, (q_O)_i = -1, and the rest 0.

We can also use more than three wires, more than one constraint, constraints on more than one row, etc. With such generalizations, it can end up looking more like an AIR instance (as in the STARK paper) than a circuit.

As an example, Dmitry Khovratovich wrote up an adaptation of Plonk tailored to Poseidon. We also have various examples of custom gates in plonky.

Thank you for your kind and detailed answer.

So ‘custom gate’ is a feature that comes from original PLONK, not turbo-plonk?

I found some Zac Williamson’s speak on Zero Knowledge, I quote:

PLONK’s strength is these things we call custom gates. It’s basically you can define your own custom bit arithmetic operations. I guess you can call them mini gadgets. That are extremely efficient to evaluate inside a PLONK circuit. So you can do things like do elliptical curve point addition in a gate. You can do things like efficient Poseidon hashes, Pedersen hashes. You can do parts of a SHA-256 hash. You can do things like 8-bit logical XOR operations. All these like explicit instructions which are needed for real world circuits, but they’re all quite custom.

So Zac’s `'define your own custom bit arithmetic operations'`

is what you mean setting different selectors with 1, -1 and 0?

And what’re the meanings of do `'parts of a SHA-256 hash'`

and others, how to do that?

Happy to help

My understanding is that TurboPLONK is just a name for “PLONK with the addition of custom gates”.

I would think of setting selectors to 1 or 0 as enabling or disabling a certain gate. Like with (q_{L3})_i = 1, (q_O)_i = -1, and the rest zero, our constraint just becomes x_{c_i} = x_{a_i}^3. I.e. the i’th gate’s output wire must equal the cube of its left input wire.

I think what Zac was getting at was just that we could also add custom gates for binary functions. If we wanted an xor gate for example, we could add a term

leveraging the fact that P \oplus Q = (P \lor Q) \land \lnot(P \land Q). Then we could make the i’th gate an xor gate by setting (q_\oplus)_i = 1 and (q_O)_i = -1, which simplifies our constraint to

(I’m assuming the inputs are already known to be in \{0, 1\}. If not, we can enforce that with a couple extra constraints.)

Thank you for your help, I really learned a lot.

One more thing, here:

You mean this, right?

(q_⊕)_i({x_a}_i+{x_b}_i−{x_a}_i{x_b}_i) + (q_O)_i {x_c}_i = 0

Hm, that would work if we wanted a circuit with just xor gates. I was thinking of adding an xor gate as an extra option, while still keeping the “standard” terms/gates to support additions, multiplications, etc. So I was thinking we would keep all the usual terms like (q_O)_i \, x_{c_i}, and add (q_\oplus)_i \, (x_{a_i} + x_{b_i} - x_{a_i} x_{b_i}) as an extra term.

Hey…

turbo-plonk is indeed sometimes used informally to mean “plonk with custom gates”

but see here for an attempt to formalize it : https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf

and a more recent attempt to get the terminology in order, and connect it to STARKWARE’s airs:

Good point! Thank you for your patient answer.

Thanks Ariel for your answer and great work of PLONK btw.

I know it’s kind of off topic, but I have some questions about PLONKup too. When you bring lookup into PLONK, where do you put lookup in PLONK? I mean how PLONK is effectively combined with lookup? And why lookup?

So we haven’t released our plookup integration yet…there’s definitely some design space on how to integrate it exactly

Looking forward to it~