Open georgwiese opened 1 month ago
Note that if publics were just scalars that can be used in constraints (as they natively are in Plonky3) instead of cells in the trace (as they natively are in Halo2, and is also what we currently implement), this would be a lot cheaper. We would just:
alpha_local_public
alpha_local_public = alpha_local
alpha
and use it in the constraints that expect a shared challengeNo need to add any columns.
Another reason to move away from publics as cells to publics as scalars.
A good test for this is the block_to_block_with_bus_composite
test introduced in #1628. It is marked as should_panic
until this issue is resolved.
With #1603 demonstrating how shared challenges can be computed when computing proofs in the
CompositeBackend
, we still have to do the same in the verification algorithm. However, theBackend::verify
function does not currently give us access to the challenges (unlikeprove
, where we could manipulate thewitgen_callback
to access them).Here, I want to sketch how we can anyway emulate shared challenges using any backend.
Background
Let's say two machines request a shared challenge
alpha
of a particular ID, like so:Then, this challenge should depend on all phase stage-0 witness columns of both machines. But in the composite proof, the proving backend is invoked independently for each machine, so it is not aware of the other machine's columns.
A way to emulate challenges anyway is this:
alpha_local1
andalpha_local2
, depending only on the local stage-0 witness columns.1603 does this in the proving stage: It intercepts the otherwise independent machine proofs and modifies the challenges to be equal to the sum of local challenges.
A verifier with shared challenges
CompositeBackend::verify
just callsBackend::verify
for each machine proof, so it would not have direct access to the local challenges.However, we do the following:
CompositeBackend::verify
, verify all machine proofs and also check that the shared challenges have been computed correctlyImplementation
Our abstractions are currently not ideal to implement this. In particular, only cells in the trace can be exposed as publics. So, let me spell out the above list a bit more, using the abstractions we have available today:
alpha_local_col
alpha_local_col = alpha_local
alpha_local_col[0]
as publicalpha
alpha = alpha'
alpha
is a column that is equal to the same value everywhere, this can be used like a scalar. All constraints that need to use the shared challenge should reference it.alpha[0]
as publicCompositeBackend::verify
, verify all machine proofs and also check that the shared challenges have been computed correctlyalpha_local_col
has the correct value (because there is a constraint for it), and thatalpha
was equal to whatever value is in the publics.Note: This needs a slight modification in #1603, which currently overwrites the challenges, so witgen wouldn't have access to the local challenge anymore.
Discussion
This suggested implementation adds significant overhead. For example, for Plonky3, we're currently adding 3 witness columns for each public (this could be changed to just one fixed column though, see #1607). So, this transformation would currently add 8 witness columns per challenge (2 witness and 2 fixed after #1607). For a bus, for example, we would need 2 extension field challenges, so we'd have 4 challenges. A more integrated solution could achieve shared challenges without any extra cost.
I still think it's worth doing though, because the cost still seems manageable and we'd have a backend-agnostic implementation.