Brainstorming doc: https://hackmd.io/FAXOf-PUTAOP–2_kuNb-A
WORKER: L1 mode and L2 mode
For L1 mode
offChainSubmissionMarkers
flagsThis design covers:
- Changes to the UpaVerifier
contract.
- Design of off-chain RPC endpoint and worker
- L2 considerations (can we re-use off-chain design?)
It does not cover:
- How or when are fees charged?
- Incorporating blobs/DA layers
- Bundling off-chain submissions
- Batch filling
- Multi-worker
One verifier contract that can handle both on-chain and off-chain submissions
Off-chain RPC endpoint and worker
We must aggregate on-chain submissions in order, but we have some flexibility in how we interleave off-chain submissions. To simplify the Verifier contract logic, we will maintain:
Invariant: Aggregated batches have all on-chain submissions at the front followed by all off-chain submissions at the back.
Other details:
Currently we have
with
This SubmissionProof
is needed for on-chain submissions to ensure that the proofIds in an interval belong to the a submissionId that matches the one stored in proofReceiver. For off-chain submissions we no longer need to do this consistency check- we can just store the current submission's proofIds and then, once we get to the end of the submission, compute which submissionId to mark verified from within the Verifier contract.
VerifyAggregatedProof
We add one more argument offChainSubmissionMarkers
that is a bool[]
packed into a uint256[]
. It marks each off-chain proofId with a bool. A 1 indicates the end of a submission. (Could make this a fixed size array based on aggregation batch size. Right now offChainSubmissionMarkers
will only contain one entry since our agg batch size is 32.) The gas cost impact is very low (2 x 32 bytes of calldata x 10 gas / byte 700 gas).
VerifyAggregatedProof
will process the (on-chain) proofIds using submissionProofs
first. Once there are no more submissionProofs
we know the rest of the proofIds are for off-chain submissions, and at that point we start using offChainSubmissionMarkers
to determine submission boundaries.
Storage: We will add a storage array currentOffChainSubmissionProofIds
that stores the proofIds so far for the current partially verified off-chain submission.
verifiedAtBlock
to hold off-chain submission statusFor on-chain submissions we needed to keep track of numVerifiedInSubmission
to track partial progress towards verifying the current submission. For off-chain submissions, currentOffChainSubmissionProofIds
tracks partial progress instead. So we only need to store whether the submissionId was verified, not the number of proofs verified. To facilitate the payment note system, we will do a bit more and store the block when a submission was verified.
SubmissionId
and isSubmissionVerified
We don't have ideal options for checking the verification status of a proof/submission:
isOnChainSubmissionVerified
, isOffChainSubmissionVerified
isSubmissionVerified
that checks both on-chain and off-chain submission statuses.
verifiedAtBlock
before numVerifiedInSubmission
.Out of these, I'd choose option 2 and pay for an extra SLOAD when checking the status of on-chain submissions (since the 2k gas is less impactful there). Also in some sense this SLOAD is offset by the packing of numVerifiedInSubmission
.
Aggregators commit to aggregating off-chain subsmission by some deadline (whereas they have no such time constraints for on-chain submission), they may be incentivised to focus on off-chain submission if they have a large backlog.
We need to give on-chain submitters some kind of guarantee of liveness, namely that aggregation of on-chain proofs will not be stalled due to an aggregator promising to aggregate off-chain submissions by some deadline.
num_all_off_chain
that increments if: !(on-chain queue empty) && !(agg. batch has on-chain submission)
and is reset if agg. batch has on-chain submission
N
called delayedLastSubmissionIdx
delayedLastSubmissionIdx.tail()
is then always the nextSubmissionIdx
as of N
aggregated batches ago.Note: what if there is a single invalid on-chain submission? Aggregator cannot make progress.
Challenge system? We already record submissionBlockNumber
of on-chain submissions. For aggregated off-chain submissions, we populate a map of the form:
If challenger (restrict to be the submitter?) supplies:
then we have waited too long to service the on-chain queue, so we are penalized/they get a refund. We can store the on-chain submission referenced in the challenge to avoid repeats.
NOTE, this measures submissions rather than blocks
We can re-use the above design on L2. If we simply remove all the on-chain codepaths, the design becomes the same as our previous L2 design.