Skip to content

Commit 72ab579

Browse files
authored
instruction: generate witness for multilinear eval (#12)
* instructions: update the precompiles * instruction: generate witness for multilinear eval * some fixes
1 parent 5dd2a71 commit 72ab579

File tree

6 files changed

+104
-6
lines changed

6 files changed

+104
-6
lines changed

crates/leanVm/src/bytecode/instruction/dot_product.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
bytecode::operand::{MemOrConstant, MemOrFp},
55
constant::{DIMENSION, EF, F},
66
context::run_context::RunContext,
7-
errors::vm::VirtualMachineError,
7+
errors::{memory::MemoryError, vm::VirtualMachineError},
88
memory::{address::MemoryAddress, manager::MemoryManager},
99
};
1010

@@ -51,7 +51,7 @@ impl DotProductInstruction {
5151
let addr = (ptr_arg_0 + i)?;
5252
let vector_coeffs = memory_manager.memory.get_array_as::<F, DIMENSION>(addr)?;
5353
EF::from_basis_coefficients_slice(&vector_coeffs)
54-
.ok_or(VirtualMachineError::InvalidExtensionField)
54+
.ok_or(MemoryError::InvalidExtensionFieldConversion)
5555
})
5656
.collect::<Result<_, _>>()?;
5757

@@ -61,7 +61,7 @@ impl DotProductInstruction {
6161
let addr = (ptr_arg_1 + i)?;
6262
let vector_coeffs = memory_manager.memory.get_array_as::<F, DIMENSION>(addr)?;
6363
EF::from_basis_coefficients_slice(&vector_coeffs)
64-
.ok_or(VirtualMachineError::InvalidExtensionField)
64+
.ok_or(MemoryError::InvalidExtensionFieldConversion)
6565
})
6666
.collect::<Result<_, _>>()?;
6767

crates/leanVm/src/bytecode/instruction/multilinear_eval.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use crate::{
55
bytecode::operand::{MemOrConstant, MemOrFp},
66
constant::{DIMENSION, EF, F},
77
context::run_context::RunContext,
8-
errors::vm::VirtualMachineError,
8+
errors::{memory::MemoryError, vm::VirtualMachineError},
99
memory::{address::MemoryAddress, manager::MemoryManager},
10+
witness::multilinear_eval::WitnessMultilinearEval,
1011
};
1112

1213
/// An instruction to evaluate a multilinear polynomial at a point in the extension field.
@@ -64,7 +65,7 @@ impl MultilinearEvalInstruction {
6465
let addr = (ptr_point + i)?;
6566
let vector_coeffs = memory_manager.memory.get_array_as::<F, DIMENSION>(addr)?;
6667
EF::from_basis_coefficients_slice(&vector_coeffs)
67-
.ok_or(VirtualMachineError::InvalidExtensionField)
68+
.ok_or(MemoryError::InvalidExtensionFieldConversion)
6869
})
6970
.collect::<Result<_, _>>()?;
7071

@@ -76,4 +77,46 @@ impl MultilinearEvalInstruction {
7677

7778
Ok(())
7879
}
80+
81+
/// Generates the witness for a `MultilinearEval` instruction execution.
82+
///
83+
/// This function reads the necessary data from memory (operands and result)
84+
/// to construct a `WitnessMultilinearEval` struct, which captures the complete
85+
/// state of the operation at a specific cycle.
86+
pub fn generate_witness(
87+
&self,
88+
cycle: usize,
89+
run_context: &RunContext,
90+
memory_manager: &MemoryManager,
91+
) -> Result<WitnessMultilinearEval, VirtualMachineError> {
92+
// Resolve the memory addresses for the coefficients, point, and result.
93+
let addr_coeffs = run_context
94+
.value_from_mem_or_constant(&self.coeffs, memory_manager)?
95+
.try_into()?;
96+
let addr_point = run_context
97+
.value_from_mem_or_constant(&self.point, memory_manager)?
98+
.try_into()?;
99+
let addr_res = run_context
100+
.value_from_mem_or_fp(&self.res, memory_manager)?
101+
.try_into()?;
102+
103+
// Read the evaluation point from memory using the helper function.
104+
let point = memory_manager
105+
.memory
106+
.get_vectorized_slice_extension(addr_point, self.n_vars)?;
107+
108+
// Read the result of the evaluation from memory.
109+
let res = memory_manager.memory.get_extension(addr_res)?;
110+
111+
// Construct and return the witness struct.
112+
Ok(WitnessMultilinearEval {
113+
cycle,
114+
addr_coeffs,
115+
addr_point,
116+
addr_res,
117+
n_vars: self.n_vars,
118+
point,
119+
res,
120+
})
121+
}
79122
}

crates/leanVm/src/errors/memory.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,7 @@ pub enum MemoryError {
5252

5353
#[error("Operation failed: {} * {}, can't multiply these two values", 0.0, 0.1)]
5454
InvalidMul(Box<(MemoryValue, MemoryValue)>),
55+
56+
#[error("Invalid extensionn field conversion.")]
57+
InvalidExtensionFieldConversion,
5558
}

crates/leanVm/src/memory/mem.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
use std::mem::MaybeUninit;
22

3+
use p3_field::BasedVectorSpace;
4+
35
use super::{address::MemoryAddress, cell::MemoryCell, val::MemoryValue};
4-
use crate::errors::memory::MemoryError;
6+
use crate::{
7+
constant::{DIMENSION, EF, F},
8+
errors::memory::MemoryError,
9+
};
510

611
#[derive(Debug, Default, Clone)]
712
pub struct Memory {
@@ -202,6 +207,40 @@ impl Memory {
202207
// SAFETY: All elements have been initialized above in the loop
203208
Ok(unsafe { std::mem::transmute_copy::<_, [V; DIM]>(&out) })
204209
}
210+
211+
/// Retrieves a slice of extension field elements starting from a given vectorized address.
212+
///
213+
/// This function reads `len` consecutive vectors of size `DIMENSION` and converts each
214+
/// into an extension field element.
215+
pub(crate) fn get_vectorized_slice_extension(
216+
&self,
217+
start_address: MemoryAddress,
218+
len: usize,
219+
) -> Result<Vec<EF>, MemoryError> {
220+
(0..len)
221+
.map(|i| {
222+
// Calculate the address for the i-th vector.
223+
let current_addr = (start_address + i).map_err(MemoryError::Math)?;
224+
225+
// Read the DIMENSION base field elements for the i-th vector.
226+
let vector_coeffs = self.get_array_as::<F, DIMENSION>(current_addr)?;
227+
228+
// Convert the base field elements into an extension field element.
229+
EF::from_basis_coefficients_slice(&vector_coeffs)
230+
.ok_or(MemoryError::InvalidExtensionFieldConversion)
231+
})
232+
.collect()
233+
}
234+
235+
/// Retrieves a single extension field element from a vectorized address.
236+
pub(crate) fn get_extension(&self, address: MemoryAddress) -> Result<EF, MemoryError> {
237+
// Read the DIMENSION base field elements for the vector.
238+
let vector_coeffs = self.get_array_as::<F, DIMENSION>(address)?;
239+
240+
// Convert the base field elements into an extension field element.
241+
EF::from_basis_coefficients_slice(&vector_coeffs)
242+
.ok_or(MemoryError::InvalidExtensionFieldConversion)
243+
}
205244
}
206245

207246
#[cfg(test)]

crates/leanVm/src/witness/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod dot_product;
2+
pub mod multilinear_eval;
23
pub mod poseidon;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use crate::{constant::EF, memory::address::MemoryAddress};
2+
3+
#[derive(Debug)]
4+
pub struct WitnessMultilinearEval {
5+
pub cycle: usize,
6+
pub addr_coeffs: MemoryAddress, // vectorized pointer, of size 8.2^size
7+
pub addr_point: MemoryAddress, // vectorized pointer, of size `size`
8+
pub addr_res: MemoryAddress, // vectorized pointer
9+
pub n_vars: usize,
10+
pub point: Vec<EF>,
11+
pub res: EF,
12+
}

0 commit comments

Comments
 (0)