Skip to main content

proof_stream/
events.rs

1//! `ProofEvent` — the central event type streamed from stwo-ml proving sessions.
2//!
3//! All variants are `#[non_exhaustive]` so that future additions don't break
4//! downstream event consumers (e.g. sinks compiled against an older version).
5
6use serde::{Deserialize, Serialize};
7
8// ─── Mirror types (no dependency on stwo/nightly toolchain) ─────────────────
9
10/// Mirror of QM31 / SecureField — four M31 limbs stored as bare u32.
11/// The `a` field is the "real" M31 component; use it for scalar visualization.
12#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
13pub struct SecureFieldMirror {
14    pub a: u32,
15    pub b: u32,
16    pub c: u32,
17    pub d: u32,
18}
19
20impl SecureFieldMirror {
21    /// Normalize `a` to [0,1] for plotting.
22    pub fn as_f32(&self) -> f32 {
23        self.a as f32 / (0x7fff_ffff_u32 as f32)
24    }
25}
26
27/// Degree-2 round polynomial [c0, c1, c2] from a MatMul sumcheck round.
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct RoundPolyViz {
30    pub c0: SecureFieldMirror,
31    pub c1: SecureFieldMirror,
32    pub c2: SecureFieldMirror,
33}
34
35/// Degree-3 round polynomial [c0, c1, c2, c3] (MulLayer / higher-degree oracle).
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct RoundPolyDeg3Viz {
38    pub c0: SecureFieldMirror,
39    pub c1: SecureFieldMirror,
40    pub c2: SecureFieldMirror,
41    pub c3: SecureFieldMirror,
42}
43
44// ─── Metadata types ───────────────────────────────────────────────────────────
45
46/// Classification of a circuit layer used for coloring and filtering.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
48pub enum LayerKind {
49    MatMul,
50    Activation,
51    LayerNorm,
52    RMSNorm,
53    Add,
54    Mul,
55    Attention,
56    Embedding,
57    Dequantize,
58    Quantize,
59    Input,
60    Unknown,
61}
62
63impl LayerKind {
64    /// RGB color (0–255) used to tint this layer in the 3D circuit view.
65    pub fn color_rgb(&self) -> [u8; 3] {
66        match self {
67            LayerKind::MatMul => [0x42, 0x9b, 0xf5],    // blue
68            LayerKind::Activation => [0xf5, 0xa5, 0x42], // orange
69            LayerKind::LayerNorm => [0x4c, 0xc6, 0x71],  // green
70            LayerKind::RMSNorm => [0x38, 0xb2, 0xac],    // teal
71            LayerKind::Add => [0xa0, 0xa0, 0xa0],        // gray
72            LayerKind::Mul => [0xa8, 0x55, 0xd4],        // purple
73            LayerKind::Attention => [0xf5, 0xd0, 0x42],  // yellow
74            LayerKind::Embedding => [0xec, 0x6e, 0xad],  // pink
75            LayerKind::Dequantize => [0xff, 0x8c, 0x00], // dark orange
76            LayerKind::Quantize => [0xff, 0x4c, 0x4c],   // red
77            LayerKind::Input => [0x80, 0x80, 0xff],      // light blue
78            LayerKind::Unknown => [0x60, 0x60, 0x60],    // dark gray
79        }
80    }
81}
82
83/// Classification of the proof artifact produced by a layer.
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
85pub enum LayerProofKind {
86    Sumcheck,
87    LogUp,
88    Linear,
89    Skipped,
90    Deferred,
91}
92
93/// A single node in the circuit DAG (static metadata emitted in `CircuitCompiled`).
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct CircuitNodeMeta {
96    pub layer_idx: usize,
97    pub node_id: usize,
98    pub kind: LayerKind,
99    pub input_shape: (usize, usize),
100    pub output_shape: (usize, usize),
101    /// Estimated number of trace cells (used as node radius in 3D view).
102    pub trace_cost: usize,
103    /// Predecessor layer indices in the `LayeredCircuit`.
104    pub input_layers: Vec<usize>,
105}
106
107/// Snapshot of a single GPU device.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct GpuSnapshot {
110    pub device_id: usize,
111    pub device_name: String,
112    /// Utilization in [0.0, 1.0].
113    pub utilization: f32,
114    /// Free memory in bytes (None if unknown).
115    pub free_memory_bytes: Option<usize>,
116}
117
118/// Basic descriptive statistics for a layer activation tensor.
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct ActivationStats {
121    pub mean: f32,
122    pub std_dev: f32,
123    pub min: f32,
124    pub max: f32,
125    pub sparsity: f32,
126}
127
128/// Severity level for log events.
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
130pub enum LogLevel {
131    Trace,
132    Debug,
133    Info,
134    Warn,
135    Error,
136}
137
138// ─── ProofEvent ──────────────────────────────────────────────────────────────
139
140/// All events that can be emitted during a stwo-ml proof session.
141///
142/// Consumers (e.g. `RerunSink`) pattern-match this enum to route events to
143/// the appropriate Rerun entity paths.
144#[derive(Debug, Clone, Serialize, Deserialize)]
145#[non_exhaustive]
146pub enum ProofEvent {
147    // ── Circuit (once, static) ──────────────────────────────────────────────
148    /// Emitted once after the `LayeredCircuit` is compiled from the `ComputationGraph`.
149    CircuitCompiled {
150        total_layers: usize,
151        input_shape: (usize, usize),
152        output_shape: (usize, usize),
153        nodes: Vec<CircuitNodeMeta>,
154        has_simd: bool,
155        simd_num_blocks: usize,
156    },
157
158    // ── Forward pass intermediates (viz #2 Inference DVR, #3 Robotics) ──────
159    /// Raw layer activation output sampled for visualization.
160    LayerActivation {
161        layer_idx: usize,
162        node_id: usize,
163        kind: LayerKind,
164        output_shape: (usize, usize),
165        /// Up to `max_sample` elements from the output tensor (M31 raw values).
166        output_sample: Vec<u32>,
167        stats: ActivationStats,
168    },
169    /// Attention score matrix for one head (sampled to ≤64×64).
170    AttentionHeatmap {
171        layer_idx: usize,
172        head_idx: usize,
173        num_heads: usize,
174        seq_len: usize,
175        /// Row-major, length = min(seq_len,64)².
176        scores: Vec<f32>,
177    },
178
179    // ── GKR walk (viz #1 ZK Debugger, #5 Circuit Layout) ───────────────────
180    /// Start of the entire proof session.
181    ProofStart {
182        model_name: Option<String>,
183        backend: String,
184        num_layers: usize,
185        input_shape: (usize, usize),
186        output_shape: (usize, usize),
187    },
188    /// Beginning of a single layer's reduction.
189    LayerStart {
190        layer_idx: usize,
191        kind: LayerKind,
192        input_shape: (usize, usize),
193        output_shape: (usize, usize),
194        /// Estimated trace cost for this layer.
195        trace_cost: usize,
196        /// Initial claim value (QM31.a normalized to f32).
197        claim_value_approx: f32,
198        gpu_device: Option<usize>,
199    },
200    /// One round of sumcheck within a layer.
201    SumcheckRound {
202        layer_idx: usize,
203        round: usize,
204        total_rounds: usize,
205        /// Degree-2 polynomial (MatMul / LogUp rounds).
206        poly_deg2: Option<RoundPolyViz>,
207        /// Degree-3 polynomial (Mul layer rounds).
208        poly_deg3: Option<RoundPolyDeg3Viz>,
209        /// Reduced claim after this round.
210        claim_value_approx: f32,
211    },
212    /// End of a single layer's reduction.
213    LayerEnd {
214        layer_idx: usize,
215        kind: LayerProofKind,
216        final_claim_value_approx: f32,
217        duration_ms: u64,
218        rounds_completed: usize,
219    },
220    /// The entire proof session completed.
221    ProofComplete {
222        duration_ms: u64,
223        num_layer_proofs: usize,
224        num_weight_openings: usize,
225        weight_binding_mode: String,
226    },
227
228    // ── Weight openings (viz #5: highlighted edges) ──────────────────────────
229    WeightOpeningStart {
230        weight_node_id: usize,
231        eval_point_len: usize,
232    },
233    WeightOpeningEnd {
234        weight_node_id: usize,
235        duration_ms: u64,
236        /// Hex-encoded commitment (first 8 bytes).
237        commitment_hex: String,
238    },
239
240    // ── Aggregated oracle sumcheck ───────────────────────────────────────────
241    AggregatedBindingStart {
242        num_claims: usize,
243        num_matrices: usize,
244    },
245    AggregatedBindingEnd {
246        duration_ms: u64,
247        estimated_calldata_felts: usize,
248    },
249
250    // ── GPU cluster (viz #4 ProofTV) ─────────────────────────────────────────
251    GpuStatus {
252        devices: Vec<GpuSnapshot>,
253        matmul_done: usize,
254        matmul_total: usize,
255        layers_done: usize,
256        layers_total: usize,
257    },
258
259    // ── Unified STARK (aggregation.rs) ───────────────────────────────────────
260    StarkProofStart {
261        num_activation_layers: usize,
262        num_add_layers: usize,
263        num_layernorm_layers: usize,
264    },
265    StarkProofEnd {
266        duration_ms: u64,
267    },
268
269    /// Free-form log entry.
270    Log {
271        level: LogLevel,
272        message: String,
273    },
274}