11use p3_field:: PrimeField64 ;
2+ use p3_symmetric:: Permutation ;
23
34use crate :: {
45 bytecode:: {
@@ -11,13 +12,17 @@ use crate::{
1112 memory:: { address:: MemoryAddress , manager:: MemoryManager , val:: MemoryValue } ,
1213} ;
1314
15+ const DIMENSION : usize = 8 ;
16+
1417#[ derive( Debug , Default ) ]
15- pub struct VirtualMachine {
18+ pub struct VirtualMachine < PERM16 , PERM24 > {
1619 pub ( crate ) run_context : RunContext ,
1720 pub memory_manager : MemoryManager ,
21+ pub poseidon2_16 : PERM16 ,
22+ pub poseidon2_24 : PERM24 ,
1823}
1924
20- impl VirtualMachine {
25+ impl < PERM16 , PERM24 > VirtualMachine < PERM16 , PERM24 > {
2126 /// Advances the program counter (`pc`) to the next instruction.
2227 ///
2328 /// This function embodies the control flow logic of the zkVM. For most instructions,
@@ -146,6 +151,7 @@ impl VirtualMachine {
146151 ) -> Result < ( ) , VirtualMachineError < F > >
147152 where
148153 F : PrimeField64 ,
154+ PERM16 : Permutation < [ F ; DIMENSION * 2 ] > ,
149155 {
150156 // Dispatch to the appropriate execution logic based on the instruction type.
151157 match instruction {
@@ -316,11 +322,63 @@ impl VirtualMachine {
316322 Ok ( ( ) )
317323 }
318324
319- fn execute_poseidon2_16 < F > ( & self , _shift : usize ) -> Result < ( ) , VirtualMachineError < F > >
325+ /// Executes the `Poseidon2_16` precompile instruction.
326+ ///
327+ /// This function orchestrates a Poseidon2 permutation over 16 field elements,
328+ /// as defined by the zkVM's ISA. It reads two 8-element input vectors and
329+ /// writes two 8-element output vectors using pointers stored relative to the
330+ /// frame pointer (`fp`).
331+ ///
332+ /// The operation is: `Poseidon2(m_vec[ptr_0], m_vec[ptr_1]) -> (m_vec[ptr_2], m_vec[ptr_3])`
333+ fn execute_poseidon2_16 < F > ( & mut self , shift : usize ) -> Result < ( ) , VirtualMachineError < F > >
320334 where
321335 F : PrimeField64 ,
336+ PERM16 : Permutation < [ F ; 2 * DIMENSION ] > ,
322337 {
323- // TODO: implement this instruction.
338+ // Read Pointers from Memory
339+ //
340+ // The instruction specifies 4 consecutive pointers starting at `fp + shift`.
341+ let base_ptr_addr = self . run_context . fp . add_usize ( shift) ?;
342+ let ptrs: [ MemoryValue < F > ; 4 ] = self . memory_manager . get_array ( base_ptr_addr) ?;
343+
344+ // Convert the `MemoryValue` pointers to `MemoryAddress`.
345+ let ptr_arg_0: MemoryAddress = ptrs[ 0 ] . try_into ( ) ?;
346+ let ptr_arg_1: MemoryAddress = ptrs[ 1 ] . try_into ( ) ?;
347+ let ptr_res_0: MemoryAddress = ptrs[ 2 ] . try_into ( ) ?;
348+ let ptr_res_1: MemoryAddress = ptrs[ 3 ] . try_into ( ) ?;
349+
350+ // Read Input Vectors
351+ //
352+ // Read the 8-element vectors from the locations pointed to by `ptr_arg_0` and `ptr_arg_1`.
353+ let arg0: [ MemoryValue < F > ; DIMENSION ] = self . memory_manager . get_array ( ptr_arg_0) ?;
354+ let arg1: [ MemoryValue < F > ; DIMENSION ] = self . memory_manager . get_array ( ptr_arg_1) ?;
355+
356+ // Perform Hashing
357+ //
358+ // Concatenate the two input vectors into a single 16-element array for the permutation.
359+ let mut state = [ MemoryValue :: default ( ) ; DIMENSION * 2 ] ;
360+ state[ ..DIMENSION ] . copy_from_slice ( & arg0) ;
361+ state[ DIMENSION ..] . copy_from_slice ( & arg1) ;
362+
363+ // Convert the state to an array of field
364+ let mut state_f: [ F ; DIMENSION * 2 ] = [ F :: ZERO ; DIMENSION * 2 ] ;
365+ for i in 0 ..DIMENSION {
366+ state_f[ i] = state[ i] . to_f ( ) ?;
367+ }
368+
369+ // Apply the Poseidon2 permutation to the state.
370+ self . poseidon2_16 . permute_mut ( & mut state_f) ;
371+
372+ // Write Output Vectors
373+ //
374+ // Split the permuted state back into two 8-element output vectors.
375+ let res0: [ F ; DIMENSION ] = state_f[ ..DIMENSION ] . try_into ( ) . unwrap ( ) ;
376+ let res1: [ F ; DIMENSION ] = state_f[ DIMENSION ..] . try_into ( ) . unwrap ( ) ;
377+
378+ // Write the output vectors to the memory locations pointed to by `ptr_res_0` and `ptr_res_1`.
379+ self . memory_manager . load_data ( ptr_res_0, & res0) ?;
380+ self . memory_manager . load_data ( ptr_res_1, & res1) ?;
381+
324382 Ok ( ( ) )
325383 }
326384
0 commit comments