Skip to content

Commit 20f8c2d

Browse files
committed
no outputs for mmcs
1 parent 719deea commit 20f8c2d

File tree

3 files changed

+36
-78
lines changed

3 files changed

+36
-78
lines changed

circuit/src/builder/compiler/non_primitive_lowerer.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -90,24 +90,24 @@ impl<'a> NonPrimitiveLowerer<'a> {
9090
"MmcsVerify index input",
9191
)?;
9292

93-
// Map root outputs
93+
// Map root inputs (assert op; no outputs)
9494
let root_widx: Vec<WitnessId> = (ext + 1..expected)
9595
.map(|i| {
9696
get_witness_id(
9797
self.expr_to_widx,
9898
witness_exprs[i],
99-
"MmcsVerify root output",
99+
"MmcsVerify root input",
100100
)
101101
})
102102
.collect::<Result<_, _>>()?;
103103

104-
// Build Op with executor
104+
// Build Op with executor: all in inputs; no outputs
105105
let mut inputs = leaf_widx.clone();
106106
inputs.push(index_widx);
107-
let outputs = root_widx.clone();
107+
inputs.extend(root_widx);
108108
lowered_ops.push(Op::NonPrimitiveOpWithExecutor {
109109
inputs,
110-
outputs,
110+
outputs: Vec::new(),
111111
executor: alloc::boxed::Box::new(MmcsVerifyExecutor::new()),
112112
op_id: *op_id,
113113
});
@@ -239,8 +239,8 @@ mod tests {
239239
..
240240
} => {
241241
assert_eq!(executor.op_type(), &NonPrimitiveOpType::MmcsVerify);
242-
assert_eq!(inputs, &vec![WitnessId(0), WitnessId(1)]);
243-
assert_eq!(outputs, &vec![WitnessId(2)]);
242+
assert_eq!(inputs, &vec![WitnessId(0), WitnessId(1), WitnessId(2)]);
243+
assert!(outputs.is_empty());
244244
}
245245
_ => panic!("Expected NonPrimitiveOpWithExecutor(MmcsVerify)"),
246246
}
@@ -281,17 +281,16 @@ mod tests {
281281
..
282282
} => {
283283
assert_eq!(executor.op_type(), &NonPrimitiveOpType::MmcsVerify);
284-
// Verify leaf witnesses (0..8) + index (8)
285-
assert_eq!(inputs.len(), 9);
284+
// Verify leaf witnesses (0..8) + index (8) + root (9..16)
285+
assert_eq!(inputs.len(), 17);
286286
for (i, &wid) in inputs.iter().enumerate().take(8) {
287287
assert_eq!(wid, WitnessId(i as u32));
288288
}
289289
assert_eq!(inputs[8], WitnessId(8));
290-
// Verify root witnesses (9..16) as outputs
291-
assert_eq!(outputs.len(), 8);
292-
for (i, &wid) in outputs.iter().enumerate() {
293-
assert_eq!(wid, WitnessId((9 + i) as u32));
290+
for (i, &wid) in inputs.iter().enumerate().skip(9) {
291+
assert_eq!(wid, WitnessId(i as u32));
294292
}
293+
assert!(outputs.is_empty());
295294
}
296295
_ => panic!("Expected NonPrimitiveOpWithExecutor(MmcsVerify)"),
297296
}
@@ -341,11 +340,11 @@ mod tests {
341340
} => {
342341
assert_eq!(executor.op_type(), &NonPrimitiveOpType::MmcsVerify);
343342
let base = (i * 3) as u32;
344-
assert_eq!(inputs.len(), 2); // leaf (1) + index (1)
343+
assert_eq!(inputs.len(), 3); // leaf (1) + index (1) + root(1)
345344
assert_eq!(inputs[0], WitnessId(base));
346345
assert_eq!(inputs[1], WitnessId(base + 1));
347-
assert_eq!(outputs.len(), 1);
348-
assert_eq!(outputs[0], WitnessId(base + 2));
346+
assert_eq!(inputs[2], WitnessId(base + 2));
347+
assert!(outputs.is_empty());
349348
assert_eq!(*op_id, NonPrimitiveOpId(i as u32));
350349
}
351350
_ => panic!("Expected NonPrimitiveOpWithExecutor(MmcsVerify)"),

circuit/src/ops/mmcs.rs

Lines changed: 19 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,7 @@ pub trait MmcsOps<F> {
207207
root_expr: &[ExprId],
208208
) -> Result<NonPrimitiveOpId, CircuitBuilderError>;
209209

210-
/// Allocate root outputs as witness hints and add MMCS verify that will set-or-verify them.
211-
fn add_mmcs_verify_allocating_root(
212-
&mut self,
213-
leaf_expr: &[ExprId],
214-
index_expr: &ExprId,
215-
root_len: usize,
216-
) -> Result<(NonPrimitiveOpId, Vec<ExprId>), CircuitBuilderError>;
210+
// Deprecated: MMCS is an assert op and does not write outputs.
217211
}
218212

219213
impl<F> MmcsOps<F> for CircuitBuilder<F>
@@ -237,27 +231,7 @@ where
237231
Ok(self.push_non_primitive_op(NonPrimitiveOpType::MmcsVerify, inputs, "mmcs_verify"))
238232
}
239233

240-
fn add_mmcs_verify_allocating_root(
241-
&mut self,
242-
leaf_expr: &[ExprId],
243-
index_expr: &ExprId,
244-
root_len: usize,
245-
) -> Result<(NonPrimitiveOpId, Vec<ExprId>), CircuitBuilderError> {
246-
self.ensure_op_enabled(NonPrimitiveOpType::MmcsVerify)?;
247-
248-
let root_expr: Vec<ExprId> = self.alloc_witness_hints(root_len, "mmcs_root");
249-
250-
// Push op with inputs including root exprs (they are outputs conceptually, but part of op spec)
251-
let mut inputs = vec![];
252-
inputs.extend(leaf_expr);
253-
inputs.push(*index_expr);
254-
inputs.extend(&root_expr);
255-
256-
let op_id =
257-
self.push_non_primitive_op(NonPrimitiveOpType::MmcsVerify, inputs, "mmcs_verify");
258-
259-
Ok((op_id, root_expr))
260-
}
234+
// Deprecated: MMCS is an assert op and does not write outputs.
261235
}
262236

263237
/// Executor for MMCS verification operations
@@ -288,7 +262,7 @@ impl<F: Field> NonPrimitiveExecutor<F> for MmcsVerifyExecutor {
288262
fn execute(
289263
&self,
290264
inputs: &[WitnessId],
291-
outputs: &[WitnessId],
265+
_outputs: &[WitnessId],
292266
ctx: &mut ExecutionContext<F>,
293267
) -> Result<(), CircuitError> {
294268
// Get the configuration
@@ -304,30 +278,21 @@ impl<F: Field> NonPrimitiveExecutor<F> for MmcsVerifyExecutor {
304278
// Get private data
305279
let NonPrimitiveOpPrivateData::MmcsVerify(private_data) = ctx.get_private_data()?;
306280

307-
// Validate input size matches configuration
308-
let expected_input_size = config.input_size();
309-
if inputs.len() != expected_input_size {
281+
// Validate input size: leaf(ext) + index(1) + root(ext)
282+
let ext_digest_elems = config.ext_field_digest_elems;
283+
let min_inputs = ext_digest_elems + 1 + ext_digest_elems;
284+
if inputs.len() < min_inputs {
310285
return Err(CircuitError::IncorrectNonPrimitiveOpPrivateDataSize {
311286
op: self.op_type.clone(),
312-
expected: expected_input_size,
287+
expected: min_inputs,
313288
got: inputs.len(),
314289
});
315290
}
316291

317-
// Extract leaf, index from inputs; root from outputs
318-
let ext_digest_elems = config.ext_field_digest_elems;
292+
// Extract leaf, index, and root from inputs
319293
let leaf_wids = &inputs[..ext_digest_elems];
320294
let index_wid = inputs[ext_digest_elems];
321-
322-
// Root comes from outputs (the value we're verifying against)
323-
if outputs.len() < ext_digest_elems {
324-
return Err(CircuitError::IncorrectNonPrimitiveOpPrivateDataSize {
325-
op: self.op_type.clone(),
326-
expected: ext_digest_elems,
327-
got: outputs.len(),
328-
});
329-
}
330-
let root_wids = &outputs[..ext_digest_elems];
295+
let root_wids = &inputs[ext_digest_elems + 1..ext_digest_elems + 1 + ext_digest_elems];
331296

332297
// Validate leaf values match private data
333298
let witness_leaf: Vec<F> = leaf_wids
@@ -365,7 +330,7 @@ impl<F: Field> NonPrimitiveExecutor<F> for MmcsVerifyExecutor {
365330
});
366331
}
367332

368-
// Set-or-verify for roots: if unset, set; if set, verify equality.
333+
// Verify roots match exactly (assert op; do not write)
369334
let private_data_root = private_data
370335
.path_states
371336
.last()
@@ -384,20 +349,14 @@ impl<F: Field> NonPrimitiveExecutor<F> for MmcsVerifyExecutor {
384349
}
385350

386351
for (i, &wid) in root_wids.iter().enumerate() {
387-
match ctx.get_witness(wid) {
388-
Ok(existing) => {
389-
if existing != private_data_root[i] {
390-
return Err(CircuitError::IncorrectNonPrimitiveOpPrivateData {
391-
op: self.op_type.clone(),
392-
operation_index: ctx.operation_id(),
393-
expected: alloc::format!("root: {private_data_root:?}"),
394-
got: alloc::format!("root: existing witness value at {wid:?}"),
395-
});
396-
}
397-
}
398-
Err(_) => {
399-
ctx.set_witness(wid, private_data_root[i])?;
400-
}
352+
let existing = ctx.get_witness(wid)?;
353+
if existing != private_data_root[i] {
354+
return Err(CircuitError::IncorrectNonPrimitiveOpPrivateData {
355+
op: self.op_type.clone(),
356+
operation_index: ctx.operation_id(),
357+
expected: alloc::format!("root: {:?}", private_data_root),
358+
got: alloc::format!("root witness at {:?}", wid),
359+
});
401360
}
402361
}
403362

circuit/src/tables/mmcs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ impl<'a, F: CircuitField> MmcsTraceBuilder<'a, F> {
275275
for op in &self.circuit.non_primitive_ops {
276276
let Op::NonPrimitiveOpWithExecutor {
277277
inputs,
278-
outputs,
278+
_outputs,
279279
executor,
280280
op_id,
281281
} = op
@@ -288,7 +288,7 @@ impl<'a, F: CircuitField> MmcsTraceBuilder<'a, F> {
288288

289289
let ext = config.ext_field_digest_elems;
290290
let leaf = &inputs[..ext];
291-
let root = &outputs[..ext];
291+
let root = &inputs[ext + 1..ext + 1 + ext];
292292

293293
let private_data = self
294294
.non_primitive_op_private_data

0 commit comments

Comments
 (0)