diff --git a/circuits/proof-builder/src/lib.rs b/circuits/proof-builder/src/lib.rs index f14a7c50..0fd9e2bd 100644 --- a/circuits/proof-builder/src/lib.rs +++ b/circuits/proof-builder/src/lib.rs @@ -70,6 +70,22 @@ pub enum ProofRequest { }, } +/// Latest EL block time in the state-chain batch (max header timestamp), Unix seconds. +/// +/// Used for `total_time_to_proof` as (time when proving completes) − (latest proved block time); +/// see . +pub fn state_chain_el_anchor_unix_secs(ctx: &ProofRequest) -> anyhow::Result { + let ProofRequest::StateChainProofRequest { blocks, .. } = ctx else { + anyhow::bail!("expected state chain proof request"); + }; + let max_ts = blocks + .iter() + .map(|b| b.evm_block.current_block.header.timestamp) + .max() + .ok_or_else(|| anyhow::anyhow!("state chain batch has no blocks"))?; + i64::try_from(max_ts).map_err(|_| anyhow::anyhow!("EL block timestamp out of range for i64")) +} + #[derive(Error, Debug, Clone)] pub enum ProofError { #[error("Retry after {0} seconds")] diff --git a/proof-builder-rpc/src/task/mod.rs b/proof-builder-rpc/src/task/mod.rs index 09eb425a..66f20dce 100644 --- a/proof-builder-rpc/src/task/mod.rs +++ b/proof-builder-rpc/src/task/mod.rs @@ -607,6 +607,8 @@ pub(crate) async fn update_long_running_task( chain_name: String, proving_time: i64, zkm_version: String, + // Unix seconds of the latest EL block in the proved batch (chain time anchor for issue #366). + el_block_anchor_unix_secs: i64, ) -> anyhow::Result { let mut storage_processor = local_db.acquire().await?; let task = storage_processor @@ -617,7 +619,10 @@ pub(crate) async fn update_long_running_task( "Long running task not found for chain: {chain_name}, start_index: {start_index}" ); } - let total_time_to_proof = (current_time_secs() - task.unwrap().created_at) * 1000; + let proving_at = current_time_secs(); + let total_time_to_proof = proving_at + .saturating_sub(el_block_anchor_unix_secs) + .saturating_mul(1000); Ok(storage_processor .update_long_running_task_proof_success( start_index, diff --git a/proof-builder-rpc/src/task/state_chain_proof.rs b/proof-builder-rpc/src/task/state_chain_proof.rs index 5f7302bd..8a62ce55 100644 --- a/proof-builder-rpc/src/task/state_chain_proof.rs +++ b/proof-builder-rpc/src/task/state_chain_proof.rs @@ -2,7 +2,7 @@ use crate::task::ProofState::{Failed, New, Proven, Proving}; use crate::task::fetch_latest_long_running_task_by_state; use crate::task::{create_long_running_task, update_long_running_task}; use crate::{ProofBuilderConfig, task::fetch_latest_long_running_task}; -use proof_builder::{ProofBuilder, ProofRequest}; +use proof_builder::{state_chain_el_anchor_unix_secs, ProofBuilder, ProofRequest}; use state_chain_proof::{StateChainProofBuilder, fetch_state_chain}; use std::time::Duration; use store::localdb::LocalDB; @@ -162,6 +162,14 @@ async fn spawn_state_chain_prover( } }; + let el_anchor = match state_chain_el_anchor_unix_secs(&ctx) { + Ok(s) => s, + Err(e) => { + tracing::error!("EL block anchor for total_time_to_proof: {e:?}"); + continue; + } + }; + let affteced = match update_long_running_task( &local_db, start_index as i64, @@ -174,6 +182,7 @@ async fn spawn_state_chain_prover( StateChainProofBuilder::name(), 0, "".to_string(), + el_anchor, ).await { Ok(affected) => affected, Err(e) => { @@ -213,6 +222,7 @@ async fn spawn_state_chain_prover( StateChainProofBuilder::name(), proving_time as i64, zkm_version, + el_anchor, ).await { Ok(affected) => affected, Err(e) => {