Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2c56e2e
Enable distributed proving in the L2 proof coordinator and multi-batch
avilagaston9 Feb 9, 2026
8158381
Remove verifyBatch() from OnChainProposer contracts, interfaces, and …
avilagaston9 Feb 9, 2026
c693938
Move BatchVerified event emission into _verifyBatchInternal so it fires
avilagaston9 Feb 9, 2026
6df4400
Reword comment about DB-behind-on-chain sync to be self-contained
avilagaston9 Feb 9, 2026
88419bd
Extract invalid_proof_type() and try_delete_invalid_proof() helpers i…
avilagaston9 Feb 9, 2026
849bec4
Extract send_single_batch_proof() to encapsulate the logic for sending a
avilagaston9 Feb 9, 2026
76f4179
Consolidate the invalid proof error handling into a single if-block that
avilagaston9 Feb 9, 2026
66f5d18
Merge request_timestamp and assignments maps in the proof coordinator…
avilagaston9 Feb 9, 2026
1fab83a
Move all_proofs_exist check into next_batch_to_assign so the proof co…
avilagaston9 Feb 9, 2026
94a7b92
Return prover input directly from next_batch_to_assign to avoid a red…
avilagaston9 Feb 9, 2026
2f6108e
Track proof coordinator assignments per (batch_number, prover_type) i…
avilagaston9 Feb 9, 2026
d09103d
Align prover_type changes with PR #6157 to avoid merge conflicts: use…
avilagaston9 Feb 9, 2026
9779c05
Add missing prover_type field to BatchRequest in the TDX quote-gen se…
avilagaston9 Feb 9, 2026
6ab37ca
Collapse nested if-let into a single chain in proof_coordinator to sa…
avilagaston9 Feb 10, 2026
7ae742f
Add distributed proving documentation covering architecture, local te…
avilagaston9 Feb 10, 2026
df807d2
Add comment explaining the #[allow(dead_code)] on needed_proof_types in
avilagaston9 Feb 10, 2026
9a6b2eb
Remove redundant require from verifyBatches, re-add batch verificatio…
avilagaston9 Feb 10, 2026
7426d6d
Record per-batch verification gas in the Grafana metric and bound the
avilagaston9 Feb 10, 2026
3c9cd5c
Add tx_hash label to batch_verification_gas metric and update the Gra…
avilagaston9 Feb 10, 2026
ab6e51f
Add missing override keyword to verifyBatches in the standard OnChain…
avilagaston9 Feb 10, 2026
444285f
Restore NoBatchForVersion response in proof_coordinator when a prover's
avilagaston9 Feb 10, 2026
ddba8a5
Add Verification Gas by Batch xychart panel to the Grafana L2 dashboard,
avilagaston9 Feb 10, 2026
9ae1be6
Remove the Batch Verification Gas table panel from the Grafana dashboard
avilagaston9 Feb 10, 2026
a79321c
Fall back to single-batch verification on any multi-batch error, not …
avilagaston9 Feb 10, 2026
fb160e6
Refactor proof sender so that all post-success work (metrics, verify tx
avilagaston9 Feb 10, 2026
c6291e4
Address review feedback: align OpenVM/ZisK with PR #6157 (todo! → uni…
avilagaston9 Feb 11, 2026
0873cdb
Use calldata instead of memory for verifyBatches proof array parameters
avilagaston9 Feb 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions cmd/ethrex/l2/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ impl TryFrom<SequencerOptions> for SequencerConfig {
.proof_coordinator_tdx_private_key,
qpl_tool_path: opts.proof_coordinator_opts.proof_coordinator_qpl_tool_path,
validium: opts.validium,
prover_timeout_ms: opts.proof_coordinator_opts.prover_timeout_ms,
},
based: BasedConfig {
enabled: opts.based,
Expand Down Expand Up @@ -775,6 +776,15 @@ pub struct ProofCoordinatorOptions {
help_heading = "Proof coordinator options"
)]
pub proof_send_interval_ms: u64,
#[arg(
long = "proof-coordinator.prover-timeout",
default_value = "600000",
value_name = "UINT64",
env = "ETHREX_PROOF_COORDINATOR_PROVER_TIMEOUT",
help = "Timeout in milliseconds before a batch assignment to a prover is considered stale.",
help_heading = "Proof coordinator options"
)]
pub prover_timeout_ms: u64,
}

impl Default for ProofCoordinatorOptions {
Expand All @@ -794,6 +804,7 @@ impl Default for ProofCoordinatorOptions {
proof_coordinator_qpl_tool_path: Some(
DEFAULT_PROOF_COORDINATOR_QPL_TOOL_PATH.to_string(),
),
prover_timeout_ms: 600_000,
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions crates/blockchain/metrics/l2/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ impl Metrics {
batch_verification_gas: IntGaugeVec::new(
Opts::new(
"batch_verification_gas",
"Batch verification gas cost in L1, labeled by batch number",
"Batch verification gas cost in L1, labeled by batch number and tx hash",
),
&["batch_number"],
&["batch_number", "tx_hash"],
)
.unwrap(),
batch_commitment_gas: IntGaugeVec::new(
Expand Down Expand Up @@ -193,10 +193,11 @@ impl Metrics {
&self,
batch_number: u64,
verification_gas: i64,
tx_hash: &str,
) -> Result<(), MetricsError> {
let builder = self
.batch_verification_gas
.get_metric_with_label_values(&[&batch_number.to_string()])
.get_metric_with_label_values(&[&batch_number.to_string(), tx_hash])
.map_err(|e| MetricsError::PrometheusErr(e.to_string()))?;
builder.set(verification_gas);
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/l2/based/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
- is **elected through a Round-Robin** election in L1,
- **produces** L2 blocks,
- **posts** L2 batches to L1 during their allowed period.
- `OnChainProposer`s `verifyBatch` method is **callable by anyone**. **Only one valid proof is needed** to advance the network.
- `OnChainProposer`'s `verifyBatches` method is **callable by anyone**. **Only one valid proof is needed** to advance the network.
- `OnChainProposer`’s `commitBatch` method is **callable by the lead Sequencer**.

### Milestone 2: P2P
Expand Down
13 changes: 10 additions & 3 deletions crates/l2/common/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,11 @@ pub enum ProofData {
/// The Client initiates the connection with a BatchRequest.
/// Asking for the ProverInputData the prover_server considers/needs.
/// The commit hash is used to ensure the client and server are compatible.
BatchRequest { commit_hash: String },
/// The prover type indicates what kind of proof this prover produces.
BatchRequest {
commit_hash: String,
prover_type: ProverType,
},

/// 4.
/// The Server responds with a NoBatchForVersion if the code version is not the same as the one
Expand Down Expand Up @@ -224,8 +228,11 @@ impl ProofData {
}

/// Builder function for creating a BatchRequest
pub fn batch_request(commit_hash: String) -> Self {
ProofData::BatchRequest { commit_hash }
pub fn batch_request(commit_hash: String, prover_type: ProverType) -> Self {
ProofData::BatchRequest {
commit_hash,
prover_type,
}
}

/// Builder function for creating a NoBatchForVersion
Expand Down
50 changes: 33 additions & 17 deletions crates/l2/contracts/src/l1/OnChainProposer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -354,26 +354,13 @@ contract OnChainProposer is
lastCommittedBatch = batchNumber;
}

/// @inheritdoc IOnChainProposer
/// @notice The first `require` checks that the batch number is the subsequent block.
/// @notice The second `require` checks if the batch has been committed.
/// @notice The order of these `require` statements is important.
/// Ordering Reason: After the verification process, we delete the `batchCommitments` for `batchNumber - 1`. This means that when checking the batch,
/// we might get an error indicating that the batch hasn’t been committed, even though it was committed but deleted. Therefore, it has already been verified.
function verifyBatch(
/// @notice Internal batch verification logic used by verifyBatches.
function _verifyBatchInternal(
uint256 batchNumber,
//risc0
bytes memory risc0BlockProof,
//sp1
bytes memory sp1ProofBytes,
//tdx
bytes memory tdxSignature
) external override onlyOwner whenNotPaused {
require(
!ALIGNED_MODE,
"008" // Batch verification should be done via Aligned Layer. Call verifyBatchesAligned() instead.
);

) internal {
require(
batchNumber == lastVerifiedBatch + 1,
"009" // OnChainProposer: batch already verified
Expand Down Expand Up @@ -417,6 +404,7 @@ contract OnChainProposer is
}

// Reconstruct public inputs from commitments
// MUST be BEFORE updating lastVerifiedBatch
bytes memory publicInputs = _getPublicInputsFromCommitment(batchNumber);

if (REQUIRE_RISC0_PROOF) {
Expand Down Expand Up @@ -471,6 +459,7 @@ contract OnChainProposer is
batchCommitments[batchNumber].balanceDiffs
);

// MUST be AFTER _getPublicInputsFromCommitment
lastVerifiedBatch = batchNumber;

// Remove previous batch commitment as it is no longer needed.
Expand All @@ -479,6 +468,33 @@ contract OnChainProposer is
emit BatchVerified(lastVerifiedBatch);
}

/// @inheritdoc IOnChainProposer
function verifyBatches(
uint256 firstBatchNumber,
bytes[] calldata risc0BlockProofs,
bytes[] calldata sp1ProofsBytes,
bytes[] calldata tdxSignatures
) external override onlyOwner whenNotPaused {
require(
!ALIGNED_MODE,
"008" // Batch verification should be done via Aligned Layer. Call verifyBatchesAligned() instead.
);
uint256 batchCount = risc0BlockProofs.length;
require(batchCount > 0, "OnChainProposer: empty batch array");
require(
sp1ProofsBytes.length == batchCount && tdxSignatures.length == batchCount,
"OnChainProposer: array length mismatch"
);
for (uint256 i = 0; i < batchCount; i++) {
_verifyBatchInternal(
firstBatchNumber + i,
risc0BlockProofs[i],
sp1ProofsBytes[i],
tdxSignatures[i]
);
}
}

/// @inheritdoc IOnChainProposer
function verifyBatchesAligned(
uint256 firstBatchNumber,
Expand All @@ -488,7 +504,7 @@ contract OnChainProposer is
) external override onlyOwner whenNotPaused {
require(
ALIGNED_MODE,
"00h" // Batch verification should be done via smart contract verifiers. Call verifyBatch() instead.
"00h" // Batch verification should be done via smart contract verifiers. Call verifyBatches() instead.
);
require(
firstBatchNumber == lastVerifiedBatch + 1,
Expand Down
20 changes: 10 additions & 10 deletions crates/l2/contracts/src/l1/Timelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,17 @@ contract Timelock is TimelockControllerUpgradeable, UUPSUpgradeable, ITimelock {
}

/// @custom:access Restricted to accounts with the `SEQUENCER` role.
function verifyBatch(
uint256 batchNumber,
bytes memory risc0BlockProof,
bytes memory sp1ProofBytes,
bytes memory tdxSignature
function verifyBatches(
uint256 firstBatchNumber,
bytes[] calldata risc0BlockProofs,
bytes[] calldata sp1ProofsBytes,
bytes[] calldata tdxSignatures
) external onlyRole(SEQUENCER) {
onChainProposer.verifyBatch(
batchNumber,
risc0BlockProof,
sp1ProofBytes,
tdxSignature
onChainProposer.verifyBatches(
firstBatchNumber,
risc0BlockProofs,
sp1ProofsBytes,
tdxSignatures
);
}

Expand Down
52 changes: 37 additions & 15 deletions crates/l2/contracts/src/l1/based/OnChainProposer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -332,26 +332,17 @@ contract OnChainProposer is
);
}

/// @inheritdoc IOnChainProposer
/// @notice The first `require` checks that the batch number is the subsequent block.
/// @notice The second `require` checks if the batch has been committed.
/// @notice The order of these `require` statements is important.
/// Ordering Reason: After the verification process, we delete the `batchCommitments` for `batchNumber - 1`. This means that when checking the batch,
/// we might get an error indicating that the batch hasn’t been committed, even though it was committed but deleted. Therefore, it has already been verified.
function verifyBatch(
/// @notice Internal batch verification logic used by verifyBatches.
function _verifyBatchInternal(
uint256 batchNumber,
//risc0
bytes memory risc0BlockProof,
//sp1
bytes memory sp1ProofBytes,
//tdx
bytes memory tdxSignature
) external {
) internal {
require(
!ALIGNED_MODE,
"Batch verification should be done via Aligned Layer. Call verifyBatchesAligned() instead."
batchNumber == lastVerifiedBatch + 1,
"OnChainProposer: batch already verified"
);

require(
batchCommitments[batchNumber].newStateRoot != bytes32(0),
"OnChainProposer: cannot verify an uncommitted batch"
Expand Down Expand Up @@ -380,6 +371,7 @@ contract OnChainProposer is
}

// Reconstruct public inputs from commitments
// MUST be BEFORE updating lastVerifiedBatch
bytes memory publicInputs = _getPublicInputsFromCommitment(batchNumber);

if (REQUIRE_RISC0_PROOF) {
Expand Down Expand Up @@ -429,6 +421,7 @@ contract OnChainProposer is
}
}

// MUST be AFTER _getPublicInputsFromCommitment
lastVerifiedBatch = batchNumber;

// Remove previous batch commitment as it is no longer needed.
Expand All @@ -437,6 +430,35 @@ contract OnChainProposer is
emit BatchVerified(lastVerifiedBatch);
}

/// @inheritdoc IOnChainProposer
/// @notice Callable by anyone (no access control) so that any party can
/// advance verification once proofs are available.
function verifyBatches(
uint256 firstBatchNumber,
bytes[] calldata risc0BlockProofs,
bytes[] calldata sp1ProofsBytes,
bytes[] calldata tdxSignatures
) external {
require(
!ALIGNED_MODE,
"Batch verification should be done via Aligned Layer. Call verifyBatchesAligned() instead."
);
uint256 batchCount = risc0BlockProofs.length;
require(batchCount > 0, "OnChainProposer: empty batch array");
require(
sp1ProofsBytes.length == batchCount && tdxSignatures.length == batchCount,
"OnChainProposer: array length mismatch"
);
for (uint256 i = 0; i < batchCount; i++) {
_verifyBatchInternal(
firstBatchNumber + i,
risc0BlockProofs[i],
sp1ProofsBytes[i],
tdxSignatures[i]
);
}
}

/// @inheritdoc IOnChainProposer
function verifyBatchesAligned(
uint256 firstBatchNumber,
Expand All @@ -446,7 +468,7 @@ contract OnChainProposer is
) external override {
require(
ALIGNED_MODE,
"Batch verification should be done via smart contract verifiers. Call verifyBatch() instead."
"Batch verification should be done via smart contract verifiers. Call verifyBatches() instead."
);
require(
firstBatchNumber == lastVerifiedBatch + 1,
Expand Down
28 changes: 10 additions & 18 deletions crates/l2/contracts/src/l1/based/interfaces/IOnChainProposer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,16 @@ interface IOnChainProposer {
bytes[] calldata _rlpEncodedBlocks
) external;

/// @notice Method used to verify a batch of L2 blocks.
/// @dev This method is used by the operator when a batch is ready to be
/// verified (this is after proved).
/// @param batchNumber is the number of the batch to be verified.
/// ----------------------------------------------------------------------
/// @param risc0BlockProof is the proof of the batch to be verified.
/// ----------------------------------------------------------------------
/// @param sp1ProofBytes Groth16 proof
/// ----------------------------------------------------------------------
/// @param tdxSignature TDX signature
function verifyBatch(
uint256 batchNumber,
//risc0
bytes memory risc0BlockProof,
//sp1
bytes memory sp1ProofBytes,
//tdx
bytes memory tdxSignature
/// @notice Method used to verify one or more consecutive L2 batches in a single transaction.
/// @param firstBatchNumber The batch number of the first batch to verify. Must be `lastVerifiedBatch + 1`.
/// @param risc0BlockProofs An array of RISC0 proofs, one per batch.
/// @param sp1ProofsBytes An array of SP1 proofs, one per batch.
/// @param tdxSignatures An array of TDX signatures, one per batch.
function verifyBatches(
uint256 firstBatchNumber,
bytes[] memory risc0BlockProofs,
bytes[] memory sp1ProofsBytes,
bytes[] memory tdxSignatures
) external;

// TODO: imageid, programvkey and riscvvkey should be constants
Expand Down
28 changes: 10 additions & 18 deletions crates/l2/contracts/src/l1/interfaces/IOnChainProposer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,24 +82,16 @@ interface IOnChainProposer {
ICommonBridge.L2MessageRollingHash[] calldata l2MessageRollingHashes
) external;

/// @notice Method used to verify a batch of L2 blocks.
/// @dev This method is used by the operator when a batch is ready to be
/// verified (this is after proved).
/// @param batchNumber is the number of the batch to be verified.
/// ----------------------------------------------------------------------
/// @param risc0BlockProof is the proof of the batch to be verified.
/// ----------------------------------------------------------------------
/// @param sp1ProofBytes Groth16 proof
/// ----------------------------------------------------------------------
/// @param tdxSignature TDX signature
function verifyBatch(
uint256 batchNumber,
//risc0
bytes memory risc0BlockProof,
//sp1
bytes memory sp1ProofBytes,
//tdx
bytes memory tdxSignature
/// @notice Method used to verify one or more consecutive L2 batches in a single transaction.
/// @param firstBatchNumber The batch number of the first batch to verify. Must be `lastVerifiedBatch + 1`.
/// @param risc0BlockProofs An array of RISC0 proofs, one per batch.
/// @param sp1ProofsBytes An array of SP1 proofs, one per batch.
/// @param tdxSignatures An array of TDX signatures, one per batch.
function verifyBatches(
uint256 firstBatchNumber,
bytes[] calldata risc0BlockProofs,
bytes[] calldata sp1ProofsBytes,
bytes[] calldata tdxSignatures
) external;

// TODO: imageid, programvkey and riscvvkey should be constants
Expand Down
12 changes: 6 additions & 6 deletions crates/l2/contracts/src/l1/interfaces/ITimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ interface ITimelock {
ICommonBridge.L2MessageRollingHash[] calldata l2MessageRollingHashes
) external;

/// @notice Verifies a single batch through the timelock.
function verifyBatch(
uint256 batchNumber,
bytes memory risc0BlockProof,
bytes memory sp1ProofBytes,
bytes memory tdxSignature
/// @notice Verifies one or more consecutive batches through the timelock.
function verifyBatches(
uint256 firstBatchNumber,
bytes[] calldata risc0BlockProofs,
bytes[] calldata sp1ProofsBytes,
bytes[] calldata tdxSignatures
) external;

/// @notice Verifies multiple batches through the timelock using aligned proofs.
Expand Down
Loading