powdr-labs / powdr

A modular stack for zkVMs, with a focus on productivity, security and performance.
Apache License 2.0
338 stars 67 forks source link

Witgen annotations in PIL #1378

Open georgwiese opened 1 month ago

georgwiese commented 1 month ago

Motivation

For the most part, automatic witgen is a fairly generic solver for a given set of constraints. But there are some "ugly" machine detection parts: For example, the Double-sorted witness machine (aka read-write memory) relies on specific column names.

This appears to get worse when we implement permutation and lookup arguments in PIL. For example, what used to be:

lhs_selector { a1, a2 } is rhs_selector { b1, b2 };

then compiles to:

col witness stage(1) z;
(is_first * (main.z - 1)) = 0;
((beta1 - (rhs_selector * ((alpha1 * b1) + b2))) * z') = ((beta1 - (lhs_selector * ((alpha1 * a1) + a2))) * z);

(and that's in the simple case, where we're not working over extension fields (#1306))

It is not obvious how to robustly extract the information explicit in the native permutation constraint from the new constraints.

Another example is LogUp (#1374): Here, witgen actually has to do extra work (keep track of the multiplicities, which a generic solver would not know how to do). This is kind of similar to the double-sorted witness machine mentioned above.

PIL annotations

We could allow the user to pass information like this explicitly to witgen in PIL and ASM. I'm not sure what the exact syntax should be, but it could be some struct with the following fields:

With this approach, users would be able to mix and match custom machines with custom connection arguments.

It should be possible to return these annotation from PIL functions, just like it's possible to return constraints!

Assembly annotations

We should also be able to specify this in assembly already. Again, I'm not sure about the exact syntax, but it would makes sense that a machine's operations can have a custom_machine and custom_machine_args annotation.

chriseth commented 1 week ago

About the custom machine annotation: I think there should be some special statement inside the namespace that does this, like

prover {
  std::prover::suggest_machine("memory");
  // and now potentially some hints
}

For the lookups and multiplicities: The lookup information itself could be kept by just storing the original lookup struct somewhere. How to handle the multiplicities i don't know yet.