Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/settlement/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ version.workspace = true

[dependencies]
katana-chain-spec.workspace = true
katana-metrics.workspace = true
katana-primitives.workspace = true
katana-provider.workspace = true
katana-provider-api.workspace = true
Expand All @@ -23,6 +24,7 @@ x509-verifier-rust-crypto.workspace = true

alloy-primitives.workspace = true
async-trait.workspace = true
metrics.workspace = true
cainome.workspace = true
hex.workspace = true
starknet.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions crates/settlement/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ pub trait ProvingBackend: Send + Sync {
/// Human-readable backend name, for logs.
fn name(&self) -> &'static str;

/// Short, label-friendly identifier of the proof system (e.g. `sp1`,
/// `mock`), used as a metric label.
fn proof_type(&self) -> &'static str;

/// Builds the `update_state` payload settling the state transition
/// `(prev_block, block]`.
///
Expand Down
7 changes: 7 additions & 0 deletions crates/settlement/src/backend/tee/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ where
}
}

fn proof_type(&self) -> &'static str {
match self.prover {
TeeProver::Mock => "mock",
TeeProver::Sp1 { .. } => "sp1",
}
}

async fn prove(
&self,
prev_block: Option<BlockNumber>,
Expand Down
1 change: 1 addition & 0 deletions crates/settlement/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
pub mod backend;
mod config;
pub mod error;
mod metrics;
mod piltover;
mod service;

Expand Down
52 changes: 52 additions & 0 deletions crates/settlement/src/metrics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! Metrics for the settlement service.
//!
//! Instrumented at the service layer so they are agnostic to the proving
//! backend: `proof_generation_seconds` times the whole [`ProvingBackend::prove`]
//! call (attestation build + proving), regardless of whether it is the TEE/SP1
//! backend or a future validity-proof one.
//!
//! [`ProvingBackend::prove`]: crate::backend::ProvingBackend::prove

use katana_metrics::Metrics;
use metrics::{Counter, Gauge, Histogram};

/// Proof-related settlement metrics.
///
/// Constructed with a `proof_type` label (e.g. `sp1`, `mock`) identifying the
/// proving backend, so proof timings can be broken down and compared across
/// backends.
#[derive(Metrics)]
#[metrics(scope = "settlement")]
pub(crate) struct SettlementProofMetrics {
/// Time spent generating a proof for a batch, in seconds — the backend
/// `prove` call (attestation build + proving). This is the dominant cost of
/// settlement and the primary thing to watch.
pub(crate) proof_generation_seconds: Histogram,

/// End-to-end time to settle a batch (prove + submit), in seconds.
pub(crate) settle_batch_seconds: Histogram,
}

/// Metrics for the settlement service's settle loop.
#[derive(Metrics)]
#[metrics(scope = "settlement")]
pub(crate) struct SettlementMetrics {
/// Time spent submitting the `update_state` transaction to the Piltover core
/// contract and waiting for it to land, in seconds.
pub(crate) state_update_seconds: Histogram,

/// Number of blocks in each settled batch.
pub(crate) blocks_per_batch: Histogram,

/// Total number of batches successfully settled.
pub(crate) batches_settled_total: Counter,

/// Total number of blocks successfully settled.
pub(crate) blocks_settled_total: Counter,

/// Total number of failed settlement attempts.
pub(crate) settlement_failures_total: Counter,

/// The last block number successfully settled to the core contract.
pub(crate) settled_block: Gauge,
}
29 changes: 28 additions & 1 deletion crates/settlement/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use tracing::{error, info, warn};

use crate::backend::ProvingBackend;
use crate::error::SettlementError;
use crate::metrics::{SettlementMetrics, SettlementProofMetrics};
use crate::piltover::PiltoverClient;
use crate::SettlementConfig;

Expand Down Expand Up @@ -90,6 +91,11 @@ where
provider: self.provider.clone(),
batch_size: self.config.batch_size.max(1) as u64,
idle_flush_interval: self.config.idle_flush_interval,
metrics: SettlementMetrics::default(),
proof_metrics: SettlementProofMetrics::new_with_labels(&[(
"proof_type",
self.backend.proof_type(),
)]),
};

let notify_rx = self.block_notify.subscribe();
Expand Down Expand Up @@ -147,6 +153,8 @@ struct Worker<P> {
idle_flush_interval: tokio::time::Duration,
/// Last settled block, from Piltover's `get_state()`. `None` = nothing settled yet.
cursor: Option<BlockNumber>,
metrics: SettlementMetrics,
proof_metrics: SettlementProofMetrics,
}

/// Persists the settled-block cursor to the durable [`tables::SettlementCheckpoints`] index, read
Expand Down Expand Up @@ -231,8 +239,18 @@ where

match next_action(self.cursor, head, self.batch_size, idle_elapsed) {
Action::Settle { first, last } => {
let batch_start = Instant::now();
match self.settle_batch(first, last).await {
Ok(tx_hash) => {
let blocks = last - first + 1;
self.proof_metrics
.settle_batch_seconds
.record(batch_start.elapsed().as_secs_f64());
self.metrics.blocks_per_batch.record(blocks as f64);
self.metrics.batches_settled_total.increment(1);
self.metrics.blocks_settled_total.increment(blocks);
self.metrics.settled_block.set(last as f64);

info!(
first,
last,
Expand All @@ -248,6 +266,7 @@ where
}

Err(error) => {
self.metrics.settlement_failures_total.increment(1);
consecutive_failures += 1;
error!(
first,
Expand Down Expand Up @@ -354,8 +373,16 @@ where
last: BlockNumber,
) -> Result<TxHash, SettlementError> {
let prev_block = if first == 0 { None } else { Some(first - 1) };

let proof_start = Instant::now();
let update = self.backend.prove(prev_block, last).await?;
self.piltover.update_state(update).await.map_err(Into::into)
self.proof_metrics.proof_generation_seconds.record(proof_start.elapsed().as_secs_f64());

let update_start = Instant::now();
let tx_hash = self.piltover.update_state(update).await?;
self.metrics.state_update_seconds.record(update_start.elapsed().as_secs_f64());

Ok(tx_hash)
}
}

Expand Down
Loading
Loading