-
Notifications
You must be signed in to change notification settings - Fork 130
refactor(l2): decouple guest program IO #5314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Lines of code reportTotal lines added: Detailed view |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR decouples the guest program input/output structures for L1 and L2 proving by creating separate type definitions based on feature flags. This improves modularity and user experience for developers who only need L1 block proving capabilities.
Key Changes:
- Separated
ProgramInputinto L1 (single block) and L2 (multiple blocks with additional fields) variants - Separated
ProgramOutputinto L1 (basic fields) and L2 (with additional L2-specific fields) variants - Refactored
execution_program()function to have distinct implementations for L1 and L2
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| crates/l2/prover/src/guest_program/src/input.rs | Defines separate ProgramInput structures for L1 (with single block field) and L2 (with blocks vector and additional L2-specific fields like elasticity_multiplier, blob_commitment, etc.) |
| crates/l2/prover/src/guest_program/src/output.rs | Creates distinct ProgramOutput structures for L1 (with basic fields) and L2 (with additional L2-specific fields like l1messages_merkle_root, privileged_transactions_hash, and blob_versioned_hash) along with separate encode() implementations |
| crates/l2/prover/src/guest_program/src/execution.rs | Separates execution_program() into L1 and L2 variants with appropriate parameter handling; L1 version now uses the constant ELASTICITY_MULTIPLIER and converts single block to slice |
| crates/l2/prover/src/prover.rs | Updates ProgramInput construction to conditionally extract single block for L1 or use full blocks vector for L2 based on feature flags |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| serde::Serialize, serde::Deserialize, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, | ||
| )] | ||
| pub struct ProgramInput { | ||
| /// blocks to execute |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment starts with a lowercase letter "blocks to execute" while the corresponding L1 comment starts with an uppercase "Block to execute". For consistency, consider capitalizing this to "Blocks to execute".
| /// blocks to execute | |
| /// Blocks to execute |
|
|
||
| /// Public output variables exposed by the zkVM execution program. Some of these are part of | ||
| /// the program input. | ||
| #[cfg(not(feature = "l2"))] | ||
| #[derive(Serialize, Deserialize)] | ||
| pub struct ProgramOutput { | ||
| /// initial state trie root hash | ||
| pub initial_state_hash: H256, | ||
| /// final state trie root hash | ||
| pub final_state_hash: H256, | ||
| /// hash of the last block in a batch | ||
| pub last_block_hash: H256, | ||
| /// chain_id of the network | ||
| pub chain_id: U256, | ||
| /// amount of non-privileged transactions | ||
| pub non_privileged_count: U256, | ||
| } | ||
|
|
||
| #[cfg(not(feature = "l2"))] | ||
| impl ProgramOutput { | ||
| pub fn encode(&self) -> Vec<u8> { | ||
| [ | ||
| self.initial_state_hash.to_fixed_bytes(), | ||
| self.final_state_hash.to_fixed_bytes(), | ||
| self.last_block_hash.to_fixed_bytes(), | ||
| self.chain_id.to_big_endian(), | ||
| self.non_privileged_count.to_big_endian(), | ||
| ] | ||
| .concat() | ||
| } | ||
| } |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The L1 ProgramOutput struct and its encode() implementation are duplicated from the L2 version. Consider using a macro or shared implementation to reduce code duplication and make maintenance easier. For example, you could define common fields in a macro and compose the different variants.
| pub initial_state_hash: H256, | ||
| /// final state trie root hash | ||
| pub final_state_hash: H256, | ||
| /// hash of the last block in a batch |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says "hash of the last block in a batch", but in the L1 context (non-l2 feature), only a single block is processed, not a batch. Consider updating the comment to reflect this, e.g., "hash of the block" or "hash of the last block".
| /// hash of the last block in a batch | |
| /// hash of the block |
Motivation
Our guest program library is used for both L1 and L2 block proving, and the logic for it is very coupled. A first step towards decoupling this is separating the guest program inputs for L1 and L2. This also improves the UX for users that only care about proving L1 blocks.
Description
Guest program inputs for L1
Guest program inputs for L2