Public IO #627
Replies: 3 comments 8 replies
-
The program will typically be driven by private inputs, e.g. a rollup block. And it will generate public summaries, e.g. hash digests and counters. Then it can write there as public outputs. If only inputs were available, it would simulate outputs by loading inputs, comparing, and branching. The output style is easier and safer to use. Easier: No need to generate the public IO somehow before tracing, as it is naturally a result of the trace.
Safer: This is an automatic and intuitive feature of the output style. |
Beta Was this translation helpful? Give feedback.
-
Note for the implementation of unhash or Merkle openings: this is best offered as a software library, as opposed to some solution built into the zkVM. First because there can be many variants of these for different contexts, and the applications actually come with their own methods: e.g. the existing formats of blocks and the Merkle trees of a rollup. So we want the flexibility of changing or adding functions in this library. Of course that will use zkVM intrinsics for the actual hashing. |
Beta Was this translation helpful? Give feedback.
-
The public input region is expected to be relatively small, e.g. less than 2^4 field elements as the verifier needs to evaluate the MLE at a random point. Therefore it's should be holding hash digest of the data that a guest program wants to output. The SP1's approach looks good to me. It feed the bytes to a static |
Beta Was this translation helpful? Give feedback.
-
We recently discussed hints (also known as unconstrained private input.
Now it is time to look at public IO.
We have two choices to make:
Simulate input or simulate output?
SP1 makes a curious choice here: For hints, they simulate input via functions like
read
orread_slice
. We do the same. However for public IO, they simulate output via functions likecommit
orcommit_slice
Not that they need a
Serialize
bound, because they are actually serialising inside the VM.Serialising is a rather expensive operation. Deserialising is much cheaper. (But the gap between the two is smaller in SP1, because their deserialisation is literally orders of magnitude less efficient than ours.)
So I suggest to deviate from SP1 here, and simulate public input instead of public output. Both models have the same expressiveness, but simulating input is more efficient thanks to
rkvy
's zero-copy deserialisation.(And we can implement
commit
andcommit_slice
as convenience functions on top ofread_public
andread_public_slice
, without even having to serialise inside the VM.)I suggest we follow the same model as for hints. We already have public IO memory regions in the VM.
As an extra wrinkle, in the code for 'successful exit' we will want to assert that all public input values have been consumed. This is not necessary for hints.
Merkle-ise by default?
The discussion so far assumes that we specify public IO as a list of values. If we have a long collection of inputs and we only need to read some of them, it can make sense to use a Merkle-tree.
In that case, the public input would consists of just the root of the Merkle-tree.
To make that work we need one specific pre-compile that can be wrapped in Rust function:
unhash
takes a digest and returns the corresponding pre-image according to some hash function. This combines reading the pre-image from some private input (not necessarily the same as for our unconstrained hints) and verifying its hash digest.On top of this primitive, we can build functionality that abstracts away from the hashing and presents the guest developer with an API to navigate a tree (or directed acyclic graph) of public input data.
Details depend on the hash functions we want to implement as pre-compiles.
We can also look into eg vector commitments and other schemes.
Beta Was this translation helpful? Give feedback.
All reactions