Skip to content

Commit 58346f1

Browse files
committed
impl io and crypto ops
1 parent e70d219 commit 58346f1

File tree

8 files changed

+164
-250
lines changed

8 files changed

+164
-250
lines changed

processor/src/parallel/basic_block.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use miden_air::trace::{
44
DECODER_TRACE_OFFSET,
55
decoder::{
66
ADDR_COL_IDX, GROUP_COUNT_COL_IDX, HASHER_STATE_OFFSET, IN_SPAN_COL_IDX,
7-
NUM_OP_BATCH_FLAGS, NUM_OP_BITS, NUM_OP_BITS_EXTRA_COLS, OP_BATCH_FLAGS_OFFSET,
8-
OP_BITS_EXTRA_COLS_OFFSET, OP_BITS_OFFSET, OP_INDEX_COL_IDX,
7+
NUM_OP_BATCH_FLAGS, NUM_OP_BITS, NUM_OP_BITS_EXTRA_COLS, NUM_USER_OP_HELPERS,
8+
OP_BATCH_FLAGS_OFFSET, OP_BITS_EXTRA_COLS_OFFSET, OP_BITS_OFFSET, OP_INDEX_COL_IDX,
99
},
1010
};
1111
use vm_core::{
@@ -194,6 +194,7 @@ impl CoreTraceFragmentGenerator {
194194
&mut self,
195195
operation: Operation,
196196
op_idx_in_group: usize,
197+
user_op_helpers: Option<[Felt; NUM_USER_OP_HELPERS]>,
197198
) -> ControlFlow<()> {
198199
let row_idx = self.num_rows_built();
199200

@@ -208,7 +209,7 @@ impl CoreTraceFragmentGenerator {
208209

209210
self.fragment.columns[DECODER_TRACE_OFFSET + ADDR_COL_IDX][row_idx] = block.addr;
210211

211-
// TODO(plafer): copy/pasted from trace_builder.rs; put in some `append_opcode` method
212+
// TODO(plafer): copy/pasted from trace_builder.rs; use `append_opcode` method
212213
{
213214
let opcode = operation.op_code();
214215
for i in 0..NUM_OP_BITS {
@@ -217,17 +218,28 @@ impl CoreTraceFragmentGenerator {
217218
}
218219
}
219220

220-
// hasher trace
221+
// hasher trace: group_ops_left and parent address
221222
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET][row_idx] =
222223
ctx.group_ops_left;
223224
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 1][row_idx] =
224225
block.parent_addr;
225-
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 2][row_idx] = ZERO;
226-
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 3][row_idx] = ZERO;
227-
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 4][row_idx] = ZERO;
228-
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 5][row_idx] = ZERO;
229-
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 6][row_idx] = ZERO;
230-
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 7][row_idx] = ZERO;
226+
227+
// hasher trace: user op helpers
228+
{
229+
let user_op_helpers = user_op_helpers.unwrap_or([ZERO; NUM_USER_OP_HELPERS]);
230+
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 2][row_idx] =
231+
user_op_helpers[0];
232+
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 3][row_idx] =
233+
user_op_helpers[1];
234+
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 4][row_idx] =
235+
user_op_helpers[2];
236+
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 5][row_idx] =
237+
user_op_helpers[3];
238+
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 6][row_idx] =
239+
user_op_helpers[4];
240+
self.fragment.columns[DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + 7][row_idx] =
241+
user_op_helpers[5];
242+
}
231243

232244
self.fragment.columns[DECODER_TRACE_OFFSET + IN_SPAN_COL_IDX][row_idx] = ONE;
233245
self.fragment.columns[DECODER_TRACE_OFFSET + GROUP_COUNT_COL_IDX][row_idx] =

processor/src/parallel/mod.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use core::ops::ControlFlow;
33

44
use miden_air::{
55
RowIndex,
6-
trace::{DECODER_TRACE_WIDTH, STACK_TRACE_WIDTH, SYS_TRACE_WIDTH, decoder::NUM_OP_BITS},
6+
trace::{
7+
DECODER_TRACE_WIDTH, STACK_TRACE_WIDTH, SYS_TRACE_WIDTH,
8+
decoder::{NUM_OP_BITS, NUM_USER_OP_HELPERS},
9+
},
710
};
811
use tokio::{sync::mpsc::Receiver, task::JoinHandle};
912
use traversal::ExecutionTraversal;
@@ -717,16 +720,18 @@ impl CoreTraceFragmentGenerator {
717720
/// any memory or advice provider operations for parallel trace generation.
718721
fn execute_op(&mut self, op: Operation, op_idx_in_group: usize) -> ControlFlow<()> {
719722
// Execute the operation by dispatching to appropriate operation methods
720-
self.dispatch_operation(&op);
723+
let user_op_helpers = self.dispatch_operation(&op);
721724

722725
// write the operation to the trace
723-
self.add_operation_trace_row(op, op_idx_in_group)
726+
self.add_operation_trace_row(op, op_idx_in_group, user_op_helpers)
724727
}
725728

726729
/// Dispatches the operation to the appropriate execution method.
727-
fn dispatch_operation(&mut self, op: &Operation) {
730+
fn dispatch_operation(&mut self, op: &Operation) -> Option<[Felt; NUM_USER_OP_HELPERS]> {
728731
use vm_core::Operation;
729732

733+
let mut user_op_helpers = None;
734+
730735
match op {
731736
// ----- system operations ------------------------------------------------------------
732737
Operation::Noop => {
@@ -827,24 +832,32 @@ impl CoreTraceFragmentGenerator {
827832

828833
// ----- input / output ---------------------------------------------------------------
829834
Operation::Push(value) => self.op_push(*value),
830-
Operation::AdvPop => self.advpop(),
831-
Operation::AdvPopW => self.advpopw(),
832-
Operation::MLoadW => self.mloadw(),
833-
Operation::MStoreW => self.mstorew(),
834-
Operation::MLoad => self.mload(),
835-
Operation::MStore => self.mstore(),
836-
Operation::MStream => self.mstream(),
837-
Operation::Pipe => self.pipe(),
835+
Operation::AdvPop => self.op_advpop(),
836+
Operation::AdvPopW => self.op_advpopw(),
837+
Operation::MLoadW => self.op_mloadw(),
838+
Operation::MStoreW => self.op_mstorew(),
839+
Operation::MLoad => self.op_mload(),
840+
Operation::MStore => self.op_mstore(),
841+
Operation::MStream => self.op_mstream(),
842+
Operation::Pipe => self.op_pipe(),
838843

839844
// ----- cryptographic operations -----------------------------------------------------
840-
Operation::HPerm => self.hperm(),
841-
Operation::MpVerify(_err_code) => self.mpverify(),
842-
Operation::MrUpdate => self.mrupdate(),
843-
Operation::FriE2F4 => self.fri_ext2fold4(),
844-
Operation::HornerBase => self.horner_eval_base(),
845-
Operation::HornerExt => self.horner_eval_ext(),
846-
Operation::ArithmeticCircuitEval => self.arithmetic_circuit_eval(),
845+
Operation::HPerm => {
846+
let hperm_helpers = self.op_hperm();
847+
user_op_helpers = Some(hperm_helpers);
848+
},
849+
Operation::MpVerify(_err_code) => {
850+
let mpverify_helpers = self.op_mpverify();
851+
user_op_helpers = Some(mpverify_helpers);
852+
},
853+
Operation::MrUpdate => self.op_mrupdate(),
854+
Operation::FriE2F4 => self.op_fri_ext2fold4(),
855+
Operation::HornerBase => self.op_horner_eval_base(),
856+
Operation::HornerExt => self.op_horner_eval_ext(),
857+
Operation::ArithmeticCircuitEval => self.op_arithmetic_circuit_eval(),
847858
}
859+
860+
user_op_helpers
848861
}
849862

850863
fn finalize_fragment(mut self) -> CoreTraceFragment {
Lines changed: 30 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,62 @@
1-
use vm_core::{ZERO, chiplets::hasher::apply_permutation};
1+
use miden_air::trace::decoder::NUM_USER_OP_HELPERS;
2+
use vm_core::{Felt, ZERO};
23

34
use super::CoreTraceFragmentGenerator;
5+
use crate::processor::Processor;
46

57
impl CoreTraceFragmentGenerator {
68
/// Performs a hash permutation operation.
79
/// Applies Rescue Prime Optimized permutation to the top 12 elements of the stack.
8-
pub(crate) fn hperm(&mut self) {
9-
// Get the top 12 elements from the stack (in reverse order for hasher state)
10-
let mut hasher_state = [
11-
self.stack_get(11),
12-
self.stack_get(10),
13-
self.stack_get(9),
14-
self.stack_get(8),
15-
self.stack_get(7),
16-
self.stack_get(6),
17-
self.stack_get(5),
18-
self.stack_get(4),
19-
self.stack_get(3),
20-
self.stack_get(2),
21-
self.stack_get(1),
22-
self.stack_get(0),
23-
];
24-
25-
// TODO(plafer): use hasher state replay (and in other crypto ops)
26-
// Apply the RPO permutation
27-
apply_permutation(&mut hasher_state);
10+
pub(crate) fn op_hperm(&mut self) -> [Felt; NUM_USER_OP_HELPERS] {
11+
let (addr, computed_hash) = self.state.hasher.replay_permutation();
2812

2913
// Put the result back on the stack (in reverse order)
30-
for (i, &value) in hasher_state.iter().rev().enumerate() {
31-
self.stack_set(i, value);
14+
for (i, &value) in computed_hash.iter().rev().enumerate() {
15+
self.stack_write(i, value);
3216
}
17+
18+
[addr, ZERO, ZERO, ZERO, ZERO, ZERO]
3319
}
3420

3521
/// Verifies a Merkle path.
36-
pub(crate) fn mpverify(&mut self) {
37-
// For parallel trace generation, we assume the Merkle path verification is already done
38-
// This would involve complex cryptographic verification in the actual implementation
39-
40-
// The operation pops the node value (4 elements), depth, index, and root (4 elements)
41-
// and verifies the path. In parallel mode, we assume verification succeeds.
22+
///
23+
/// In this implementation, we don't actually verify the path.
24+
pub(crate) fn op_mpverify(&mut self) -> [Felt; NUM_USER_OP_HELPERS] {
25+
let depth = self.stack_get(4);
26+
let index = self.stack_get(5);
27+
let root = self.stack_get_word(6);
4228

43-
// Stack layout: [node_value(4), depth, index, root(4), ...]
44-
// After verification: [root(4), ...]
29+
// Replay the Merkle path retrieval from the advice provider
30+
let _path = self.state.advice.replay_merkle_path(root, depth, index);
31+
let (addr, computed_root) = self.state.hasher.replay_build_merkle_root();
4532

46-
// Move root to top and remove other elements
47-
let root = [
48-
self.stack_get(9), // root[0]
49-
self.stack_get(8), // root[1]
50-
self.stack_get(7), // root[2]
51-
self.stack_get(6), // root[3]
52-
];
53-
54-
// Set root at top of stack
55-
for (i, &value) in root.iter().enumerate() {
56-
self.stack_set(i, value);
57-
}
33+
debug_assert_eq!(root, computed_root, "Merkle root mismatch");
5834

59-
// Remove the consumed elements (node_value + depth + index = 6 elements)
60-
self.stack_shift_left(6);
35+
[addr, ZERO, ZERO, ZERO, ZERO, ZERO]
6136
}
6237

6338
/// Updates the Merkle root.
64-
pub(crate) fn mrupdate(&mut self) {
65-
// For parallel trace generation, we assume the Merkle root update is already computed
66-
// This would involve complex cryptographic computations in the actual implementation
67-
68-
// In a real implementation, this would:
69-
// 1. Pop the old leaf value, new leaf value, and Merkle path
70-
// 2. Compute the new root by updating the path with the new leaf
71-
// 3. Push the new root onto the stack
72-
73-
// For now, we'll assume the operation succeeds and produces a placeholder root
74-
let new_root = [ZERO; 4]; // Placeholder for computed new root
75-
76-
// Remove consumed elements and place new root
77-
// This is a simplified implementation - actual stack manipulation would depend
78-
// on the specific input format
79-
for (i, &value) in new_root.iter().enumerate() {
80-
self.stack_set(i, value);
81-
}
39+
pub(crate) fn op_mrupdate(&mut self) {
40+
todo!()
8241
}
8342

8443
/// Performs FRI extension fold operation.
85-
pub(crate) fn fri_ext2fold4(&mut self) {
86-
// For parallel trace generation, we assume the FRI fold operation is already computed
87-
// This is a complex cryptographic operation used in polynomial commitments
88-
89-
// In actual implementation, this would perform FRI (Fast Reed-Solomon Interactive Oracle
90-
// Proofs) extension field folding operations
91-
92-
// For now, we'll assume the operation succeeds with a placeholder result
44+
pub(crate) fn op_fri_ext2fold4(&mut self) {
45+
todo!()
9346
}
9447

9548
/// Evaluates a polynomial using Horner's method (base field).
96-
pub(crate) fn horner_eval_base(&mut self) {
97-
// For parallel trace generation, we assume the polynomial evaluation is already computed
98-
// This would evaluate a polynomial at a given point using Horner's method in the base field
99-
100-
// In actual implementation, this would:
101-
// 1. Pop polynomial coefficients and evaluation point from stack
102-
// 2. Compute polynomial value using Horner's method: p(x) = a_n + x(a_{n-1} + x(a_{n-2} +
103-
// ...))
104-
// 3. Push result onto stack
105-
106-
let result = ZERO; // Placeholder for computed result
107-
self.stack_set(0, result);
49+
pub(crate) fn op_horner_eval_base(&mut self) {
50+
todo!()
10851
}
10952

11053
/// Evaluates a polynomial using Horner's method (extension field).
111-
pub(crate) fn horner_eval_ext(&mut self) {
112-
// For parallel trace generation, we assume the polynomial evaluation is already computed
113-
// This would evaluate a polynomial at a given point using Horner's method in the extension
114-
// field
115-
116-
// Similar to base field version but operates in quadratic extension field
117-
let result = [ZERO, ZERO]; // Placeholder for extension field result
118-
119-
self.stack_set(0, result[0]);
120-
self.stack_set(1, result[1]);
54+
pub(crate) fn op_horner_eval_ext(&mut self) {
55+
todo!()
12156
}
12257

12358
/// Evaluates an arithmetic circuit.
124-
pub(crate) fn arithmetic_circuit_eval(&mut self) {
125-
// For parallel trace generation, we assume the circuit evaluation is already computed
126-
// This would evaluate an arithmetic circuit with given inputs
127-
128-
// In actual implementation, this would:
129-
// 1. Pop circuit description and inputs from stack
130-
// 2. Evaluate the arithmetic circuit
131-
// 3. Push results onto stack
132-
133-
let result = ZERO; // Placeholder for computed result
134-
self.stack_set(0, result);
59+
pub(crate) fn op_arithmetic_circuit_eval(&mut self) {
60+
todo!()
13561
}
13662
}

processor/src/parallel/operations/helpers.rs

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)