mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-22 23:44:48 +02:00
refactor(verify-era-proof-attestation): modularize and restructure proof verification logic
- Split `verify-era-proof-attestation` into modular subcomponents for maintainability. - Moved client, proof handling, and core types into dedicated modules.
This commit is contained in:
parent
1e853f653a
commit
2605e2ae3a
34 changed files with 2918 additions and 2304 deletions
139
bin/verify-era-proof-attestation/src/proof/fetcher.rs
Normal file
139
bin/verify-era-proof-attestation/src/proof/fetcher.rs
Normal file
|
@ -0,0 +1,139 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (c) 2023-2025 Matter Labs
|
||||
|
||||
use crate::{
|
||||
client::{HttpClient, RetryConfig, RetryHelper},
|
||||
error::{Error, Result},
|
||||
proof::{
|
||||
parsing::ProofResponseParser,
|
||||
types::{GetProofsRequest, GetProofsResponse, Proof},
|
||||
},
|
||||
};
|
||||
use std::time::Duration;
|
||||
use tokio::sync::watch;
|
||||
use url::Url;
|
||||
use zksync_basic_types::{tee_types::TeeType, L1BatchNumber};
|
||||
|
||||
/// Handles fetching proofs from the server with retry logic
|
||||
pub struct ProofFetcher {
|
||||
http_client: HttpClient,
|
||||
rpc_url: Url,
|
||||
retry_config: RetryConfig,
|
||||
}
|
||||
|
||||
impl ProofFetcher {
|
||||
/// Create a new proof fetcher
|
||||
pub fn new(http_client: HttpClient, rpc_url: Url, retry_config: RetryConfig) -> Self {
|
||||
Self {
|
||||
http_client,
|
||||
rpc_url,
|
||||
retry_config,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get proofs for a batch number with retry logic
|
||||
pub async fn get_proofs(
|
||||
&self,
|
||||
stop_receiver: &mut watch::Receiver<bool>,
|
||||
batch_number: L1BatchNumber,
|
||||
tee_type: &TeeType,
|
||||
) -> Result<Vec<Proof>> {
|
||||
let mut proofs_request = GetProofsRequest::new(batch_number, tee_type);
|
||||
let mut backoff = Duration::from_secs(1);
|
||||
let max_backoff = Duration::from_secs(128);
|
||||
let retry_backoff_multiplier: f32 = 2.0;
|
||||
|
||||
while !*stop_receiver.borrow() {
|
||||
match self.send_request(&proofs_request, stop_receiver).await {
|
||||
Ok(response) => {
|
||||
// Parse the response using the ProofResponseParser
|
||||
match ProofResponseParser::parse_response(response) {
|
||||
Ok(proofs) => {
|
||||
// Filter valid proofs
|
||||
let valid_proofs = ProofResponseParser::filter_valid_proofs(&proofs);
|
||||
|
||||
if !valid_proofs.is_empty() {
|
||||
return Ok(valid_proofs);
|
||||
}
|
||||
|
||||
// No valid proofs found, retry
|
||||
let error_msg = format!(
|
||||
"No valid TEE proofs found for batch #{}. They may not be ready yet. Retrying in {} milliseconds.",
|
||||
batch_number.0,
|
||||
backoff.as_millis()
|
||||
);
|
||||
tracing::warn!(batch_no = batch_number.0, "{}", error_msg);
|
||||
// Here we could use the ProofFetching error if we needed to return immediately
|
||||
// return Err(Error::ProofFetching(error_msg));
|
||||
}
|
||||
Err(e) => {
|
||||
// Handle specific error for Sgx variant
|
||||
if let Error::JsonRpc(msg) = &e {
|
||||
if msg.contains("RPC requires 'Sgx' variant") {
|
||||
tracing::debug!("Switching to 'Sgx' variant for RPC");
|
||||
proofs_request.params.1 = "Sgx".to_string();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
|
||||
tokio::time::timeout(backoff, stop_receiver.changed())
|
||||
.await
|
||||
.ok();
|
||||
|
||||
backoff = std::cmp::min(
|
||||
Duration::from_millis(
|
||||
(backoff.as_millis() as f32 * retry_backoff_multiplier) as u64,
|
||||
),
|
||||
max_backoff,
|
||||
);
|
||||
|
||||
if *stop_receiver.borrow() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we've reached this point, we've either been stopped or exhausted retries
|
||||
if *stop_receiver.borrow() {
|
||||
// Return empty vector if stopped
|
||||
Ok(vec![])
|
||||
} else {
|
||||
// Use the ProofFetching error variant if we've exhausted retries
|
||||
Err(Error::proof_fetch(batch_number, "exhausted retries"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a request to the server with retry logic
|
||||
async fn send_request(
|
||||
&self,
|
||||
request: &GetProofsRequest,
|
||||
stop_receiver: &mut watch::Receiver<bool>,
|
||||
) -> Result<GetProofsResponse> {
|
||||
let retry_helper = RetryHelper::new(self.retry_config.clone());
|
||||
let request_clone = request.clone();
|
||||
let http_client = self.http_client.clone();
|
||||
let rpc_url = self.rpc_url.clone();
|
||||
|
||||
retry_helper
|
||||
.execute(&format!("get_proofs_{}", request.params.0), || async {
|
||||
let result = http_client
|
||||
.send_json::<_, GetProofsResponse>(&rpc_url, &request_clone)
|
||||
.await;
|
||||
|
||||
// Check if we need to abort due to stop signal
|
||||
if *stop_receiver.borrow() {
|
||||
return Err(Error::Interrupted);
|
||||
}
|
||||
|
||||
result
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue