diff --git a/plonky3/src/params/poseidon2/goldilocks/powdr_accel_impl.rs b/plonky3/src/params/poseidon2/goldilocks/powdr_accel_impl.rs index d0b7419ba1..3fa3d35a49 100644 --- a/plonky3/src/params/poseidon2/goldilocks/powdr_accel_impl.rs +++ b/plonky3/src/params/poseidon2/goldilocks/powdr_accel_impl.rs @@ -3,8 +3,8 @@ use p3_field::AbstractField; use p3_goldilocks::Goldilocks; use p3_symmetric::CryptographicPermutation; use powdr_riscv_runtime::{ - goldilocks::{extract_opaque_vec8, Goldilocks as PowdrGoldilocks, OpaqueGoldilocks}, - hash::{poseidon2_gl, poseidon2_gl_inplace}, + goldilocks::{extract_opaque_vec, Goldilocks as PowdrGoldilocks, OpaqueGoldilocks}, + hash::poseidon2_gl_inplace, }; #[derive(Clone, Copy, Debug)] @@ -21,10 +21,10 @@ impl p3_symmetric::Permutation<[Goldilocks; 8]> for Permutation { // canonical representation internally, so it is safe to cast between their // array's pointers. let input = unsafe { &*(&input as *const _ as *const [PowdrGoldilocks; 8]) }; - let input = input.map(|x| OpaqueGoldilocks::from(x)); - let output = poseidon2_gl(&input); + let mut state = input.map(|x| OpaqueGoldilocks::from(x)); + poseidon2_gl_inplace(&mut state); - extract_opaque_vec8(&output).map(|x| Goldilocks::from_canonical_u64(x)) + extract_opaque_vec::<8>(&state).map(|x| Goldilocks::from_canonical_u64(x)) } fn permute_mut(&self, data: &mut [Goldilocks; 8]) { diff --git a/riscv-executor/src/lib.rs b/riscv-executor/src/lib.rs index bd11109758..d7322bb4e1 100644 --- a/riscv-executor/src/lib.rs +++ b/riscv-executor/src/lib.rs @@ -2438,7 +2438,16 @@ impl Executor<'_, '_, F> { .try_into() .unwrap(); + let output_half = self.proc.get_reg_mem(args[2].u()).u(); + let result = poseidon2_gl::poseidon2_gl(&inputs); + let result = match output_half { + 0 => &result[0..0], + 1 => &result[0..4], + 2 => &result[4..8], + 3 => &result[0..8], + _ => unreachable!(), + }; let output_ptr = self.proc.get_reg_mem(args[1].u()).u(); assert!(is_multiple_of_4(output_ptr)); @@ -2668,7 +2677,7 @@ impl Executor<'_, '_, F> { let output_ptr = self.proc.get_reg_mem(args[1].u()).u(); assert!(is_multiple_of_4(output_ptr)); - let result = (0..8) + let result = (0..4) .flat_map(|i| { let v = self.proc.get_mem(input_ptr + i * 4, 0, 0).into_fe(); let v = v.to_integer().try_into_u64().unwrap(); diff --git a/riscv-runtime/Cargo.toml b/riscv-runtime/Cargo.toml index 7437bc07cb..51fcfa1990 100644 --- a/riscv-runtime/Cargo.toml +++ b/riscv-runtime/Cargo.toml @@ -8,8 +8,14 @@ homepage = "https://powdr.org" repository = "https://github.com/powdr-labs/powdr" [dependencies] -serde = { version = "1.0", default-features = false, features = ["alloc", "derive", "rc"] } -serde_cbor = { version = "0.11.2", default-features = false, features = ["alloc"] } +serde = { version = "1.0", default-features = false, features = [ + "alloc", + "derive", + "rc", +] } +serde_cbor = { version = "0.11.2", default-features = false, features = [ + "alloc", +] } powdr-riscv-syscalls = { path = "../riscv-syscalls", version = "0.1.4" } getrandom = { version = "0.2", features = ["custom"], optional = true } spin = "0.9" diff --git a/riscv-runtime/src/goldilocks.rs b/riscv-runtime/src/goldilocks.rs index bf132cd3ce..55689b1f80 100644 --- a/riscv-runtime/src/goldilocks.rs +++ b/riscv-runtime/src/goldilocks.rs @@ -44,10 +44,24 @@ impl From for OpaqueGoldilocks { } /// Extract the Goldilocks values from the OpaqueGoldilocks values. -pub fn extract_opaque_vec8(vec: &[OpaqueGoldilocks; 8]) -> [u64; 8] { +/// +/// The array size must be a multiple of 4. +pub fn extract_opaque_vec(vec: &[OpaqueGoldilocks; N]) -> [u64; N] { + assert_eq!(N % 4, 0); unsafe { - let mut output: MaybeUninit<[u64; 8]> = MaybeUninit::uninit(); - ecall!(Syscall::SplitGLVec, in("a0") vec, in("a1") output.as_mut_ptr()); + let mut output: MaybeUninit<[u64; N]> = MaybeUninit::uninit(); + + let input_ptr = vec.as_ptr(); + let output_ptr = (*output.as_mut_ptr()).as_mut_ptr(); + + for i in 0..(N / 4) { + ecall!( + Syscall::SplitGLVec, + in("a0") input_ptr.add(i * 4), + in("a1") output_ptr.add(i * 4) + ); + } + output.assume_init() } } diff --git a/riscv-runtime/src/hash.rs b/riscv-runtime/src/hash.rs index 38beb70c9b..5b7636987b 100644 --- a/riscv-runtime/src/hash.rs +++ b/riscv-runtime/src/hash.rs @@ -27,15 +27,26 @@ pub fn poseidon_gl(data: &mut [Goldilocks; 12]) -> &[Goldilocks; 4] { /// Perform one Poseidon2 permutation with 8 Goldilocks field elements in-place. pub fn poseidon2_gl_inplace(data: &mut [OpaqueGoldilocks; 8]) { unsafe { - ecall!(Syscall::Poseidon2GL, in("a0") data, in("a1") data); + ecall!(Syscall::Poseidon2GL, in("a0") data, in("a1") data, in("a2") 3); } } -/// Perform one Poseidon2 permutation with 8 Goldilocks field elements. -pub fn poseidon2_gl(data: &[OpaqueGoldilocks; 8]) -> [OpaqueGoldilocks; 8] { +#[repr(u32)] +pub enum Poseidon2OutputHalf { + //None = 0, + FirstHalf = 1, + SecondHalf = 2, + //Full = 3, +} + +/// Perform one Poseidon2 compression with 8 Goldilocks field elements. +pub fn poseidon2_gl_compression( + data: &[OpaqueGoldilocks; 8], + output_half: Poseidon2OutputHalf, +) -> [OpaqueGoldilocks; 4] { unsafe { - let mut output: MaybeUninit<[OpaqueGoldilocks; 8]> = MaybeUninit::uninit(); - ecall!(Syscall::Poseidon2GL, in("a0") data, in("a1") output.as_mut_ptr()); + let mut output: MaybeUninit<[OpaqueGoldilocks; 4]> = MaybeUninit::uninit(); + ecall!(Syscall::Poseidon2GL, in("a0") data, in("a1") output.as_mut_ptr(), in("a2") output_half as u32); output.assume_init() } } diff --git a/riscv/src/large_field/runtime.rs b/riscv/src/large_field/runtime.rs index 1d503f30cf..4a22b829f3 100644 --- a/riscv/src/large_field/runtime.rs +++ b/riscv/src/large_field/runtime.rs @@ -277,10 +277,11 @@ impl Runtime { None, "poseidon2_gl", vec!["memory", "MIN_DEGREE", "LARGE_SUBMACHINES_MAX_DEGREE"], - [r#"instr poseidon2_gl X, Y + [r#"instr poseidon2_gl X, Y, Z link ~> tmp1_col = regs.mload(X, STEP) link ~> tmp2_col = regs.mload(Y, STEP + 1) - link ~> poseidon2_gl.poseidon2_permutation(tmp1_col, tmp2_col, STEP) + link ~> tmp3_col = regs.mload(Z, STEP + 2) + link ~> poseidon2_gl.permute(tmp1_col, STEP, tmp2_col, STEP + 1, tmp3_col) { // make sure tmp1_col and tmp2_col are 4-byte aligned memory addresses tmp1_col = 4 * (X_b1 + X_b2 * 0x100 + X_b3 * 0x10000 + X_b4 * 0x1000000), @@ -290,7 +291,7 @@ impl Runtime { ); self.add_submachine( - "std::machines::split::split_gl_vec::SplitGLVec8", + "std::machines::split::split_gl_vec::SplitGLVec4", None, "split_gl_vec", vec!["memory", "split_gl", "MIN_DEGREE", "MAIN_MAX_DEGREE"], @@ -298,7 +299,7 @@ impl Runtime { r#"instr split_gl_vec X, Y link ~> tmp1_col = regs.mload(X, STEP) link ~> tmp2_col = regs.mload(Y, STEP + 1) - link ~> split_gl_vec.split(tmp1_col, tmp2_col, STEP + 2) + link ~> split_gl_vec.split(tmp1_col, tmp2_col, STEP) { // make sure tmp1_col and tmp2_col are 4-byte aligned memory addresses tmp1_col = 4 * (X_b1 + X_b2 * 0x100 + X_b3 * 0x10000 + X_b4 * 0x1000000), @@ -331,7 +332,7 @@ impl Runtime { // they can overlap. self.add_syscall( Syscall::Poseidon2GL, - std::iter::once("poseidon2_gl 10, 11;".to_string()), + std::iter::once(format!("{} 10, 11, 12;", Syscall::Poseidon2GL.name())), ); self.add_syscall( diff --git a/riscv/tests/riscv_data/poseidon2_gl_via_coprocessor/src/main.rs b/riscv/tests/riscv_data/poseidon2_gl_via_coprocessor/src/main.rs index 1e47e9270b..8d6580c8f9 100644 --- a/riscv/tests/riscv_data/poseidon2_gl_via_coprocessor/src/main.rs +++ b/riscv/tests/riscv_data/poseidon2_gl_via_coprocessor/src/main.rs @@ -2,46 +2,44 @@ #![no_std] use powdr_riscv_runtime::{ - goldilocks::{extract_opaque_vec8, Goldilocks, OpaqueGoldilocks, PRIME}, - hash::{poseidon2_gl, poseidon2_gl_inplace}, + goldilocks::{extract_opaque_vec, Goldilocks, OpaqueGoldilocks, PRIME}, + hash::{poseidon2_gl_compression, poseidon2_gl_inplace, Poseidon2OutputHalf}, }; #[no_mangle] fn main() { let i = [OpaqueGoldilocks::from(0); 8]; - let h = extract_opaque_vec8(&poseidon2_gl(&i)); + let h = extract_opaque_vec::<4>(&poseidon2_gl_compression( + &i, + Poseidon2OutputHalf::FirstHalf, + )); assert_eq!(h[0], 14905565590733827480); assert_eq!(h[1], 640905753703258831); assert_eq!(h[2], 4579128623722792381); assert_eq!(h[3], 158153743058056413); - assert_eq!(h[4], 5905145432652609062); - assert_eq!(h[5], 9814446752588696081); - assert_eq!(h[6], 13759450385053274731); - assert_eq!(h[7], 2402148582355896469); let i = [OpaqueGoldilocks::from(1); 8]; - let h = extract_opaque_vec8(&poseidon2_gl(&i)); - assert_eq!(h[0], 18201552556563266798); - assert_eq!(h[1], 6814935789744812745); - assert_eq!(h[2], 5947349602629011250); - assert_eq!(h[3], 15482468195247053191); - assert_eq!(h[4], 2971437633000883992); - assert_eq!(h[5], 9752341516515962403); - assert_eq!(h[6], 15477293561177957600); - assert_eq!(h[7], 13574628582471329853); + let h = extract_opaque_vec::<4>(&poseidon2_gl_compression( + &i, + Poseidon2OutputHalf::SecondHalf, + )); + assert_eq!(h[0], 2971437633000883992); + assert_eq!(h[1], 9752341516515962403); + assert_eq!(h[2], 15477293561177957600); + assert_eq!(h[3], 13574628582471329853); let minus_one = PRIME - 1; let i = [OpaqueGoldilocks::from(Goldilocks::new(minus_one)); 8]; - let h = extract_opaque_vec8(&poseidon2_gl(&i)); + let h = extract_opaque_vec::<4>(&poseidon2_gl_compression( + &i, + Poseidon2OutputHalf::FirstHalf, + )); assert_eq!(h[0], 13601391594672984423); assert_eq!(h[1], 7799837486760213030); assert_eq!(h[2], 4721195013230721931); assert_eq!(h[3], 6190752424007146655); - assert_eq!(h[4], 5006958669091947377); - assert_eq!(h[5], 716937639216173272); - assert_eq!(h[6], 10656923966581845557); - assert_eq!(h[7], 6633446230068695780); + // Also test the inplace version let mut i = [ 923978, 235763497586, @@ -53,7 +51,9 @@ fn main() { 2087, ] .map(|x| OpaqueGoldilocks::from(Goldilocks::new(x))); - let h = extract_opaque_vec8(&poseidon2_gl(&i)); + poseidon2_gl_inplace(&mut i); + + let h = extract_opaque_vec::<8>(&i); assert_eq!(h[0], 14498150941209346562); assert_eq!(h[1], 8038616707062714447); assert_eq!(h[2], 17242548914990530484); @@ -62,9 +62,4 @@ fn main() { assert_eq!(h[5], 12505236434419724338); assert_eq!(h[6], 3134668969942435695); assert_eq!(h[7], 1912726109528180442); - - // Also test the inplace version - poseidon2_gl_inplace(&mut i); - let h_inplace = extract_opaque_vec8(&i); - assert_eq!(h, h_inplace); } diff --git a/std/machines/hash/poseidon2_gl.asm b/std/machines/hash/poseidon2_gl.asm index f61ea49f62..8bc5bd45d2 100644 --- a/std/machines/hash/poseidon2_gl.asm +++ b/std/machines/hash/poseidon2_gl.asm @@ -1,6 +1,7 @@ use std::array; use std::check::assert; use std::utils::unchanged_until; +use std::utils::new_bool; use std::utils::force_bool; use std::utils::sum; use std::convert::expr; @@ -19,8 +20,8 @@ use super::poseidon2_common::poseidon2; // state size of 8 field elements instead of 12, matching Plonky3's implementation. // // This machine assumes each memory word contains a full field element, and it -// writes one field element per memory word. Use SplitGLVec8 to split the output -// into 32-bit words. +// writes one field element per memory word. Use SplitGLVec4 to split the output +// into 32-bit words. machine Poseidon2GL(mem: Memory) with latch: latch, // Allow this machine to be connected via a permutation @@ -33,19 +34,32 @@ machine Poseidon2GL(mem: Memory) with // The input data is passed via a memory pointer: the machine will read STATE_SIZE // field elements from memory. // - // Similarly, the output data is written to memory at the provided pointer. + // Similarly, the output data is written to memory at the provided pointer. We don't + // have any use for writing the full state as output, so depending on the operation, + // it will either write the first half of the state (used in sponge squeeze) or the + // second half (used in sponge absorb and on merkle tree compression). // - // Reads happen at the provided time step; writes happen at the next time step. + // Memory reads happen at input_time_step and memory writes happens at output_time_step. // // The addresses must be multiple of 4. - operation poseidon2_permutation + // + // This operation can output any combination of the first and second half of the final + // state, depending on the value of output_halves: + // 0: no output + // 1: first half + // 2: second half + // 3: the entire state + operation permute input_addr, + input_time_step, output_addr, - time_step ->; + output_time_step, + output_halves ->; let latch = 1; - let time_step; + let input_time_step; + let output_time_step; // Poseidon2 parameters, compatible with our powdr-plonky3 implementation. // @@ -120,14 +134,14 @@ machine Poseidon2GL(mem: Memory) with let input: col[STATE_SIZE]; // TODO: when link is available inside functions, we can turn this into array operations. - link if is_used ~> input[0] = mem.mload(input_addr + 0, time_step); - link if is_used ~> input[1] = mem.mload(input_addr + 4, time_step); - link if is_used ~> input[2] = mem.mload(input_addr + 8, time_step); - link if is_used ~> input[3] = mem.mload(input_addr + 12, time_step); - link if is_used ~> input[4] = mem.mload(input_addr + 16, time_step); - link if is_used ~> input[5] = mem.mload(input_addr + 20, time_step); - link if is_used ~> input[6] = mem.mload(input_addr + 24, time_step); - link if is_used ~> input[7] = mem.mload(input_addr + 28, time_step); + link if is_used ~> input[0] = mem.mload(input_addr + 0, input_time_step); + link if is_used ~> input[1] = mem.mload(input_addr + 4, input_time_step); + link if is_used ~> input[2] = mem.mload(input_addr + 8, input_time_step); + link if is_used ~> input[3] = mem.mload(input_addr + 12, input_time_step); + link if is_used ~> input[4] = mem.mload(input_addr + 16, input_time_step); + link if is_used ~> input[5] = mem.mload(input_addr + 20, input_time_step); + link if is_used ~> input[6] = mem.mload(input_addr + 24, input_time_step); + link if is_used ~> input[7] = mem.mload(input_addr + 28, input_time_step); // Generate the Poseidon2 permutation let output = poseidon2( @@ -143,16 +157,25 @@ machine Poseidon2GL(mem: Memory) with input, ); - // Write the output to memory at the next time step - let output_addr; + // Decide which halves to output: + let output_halves; + let output_first_half = new_bool(); + let output_second_half = new_bool(); + output_halves = output_first_half + 2 * output_second_half; - // TODO: turn this into array operations - link if is_used ~> mem.mstore(output_addr + 0, time_step + 1, output[0]); - link if is_used ~> mem.mstore(output_addr + 4, time_step + 1, output[1]); - link if is_used ~> mem.mstore(output_addr + 8, time_step + 1, output[2]); - link if is_used ~> mem.mstore(output_addr + 12, time_step + 1, output[3]); - link if is_used ~> mem.mstore(output_addr + 16, time_step + 1, output[4]); - link if is_used ~> mem.mstore(output_addr + 20, time_step + 1, output[5]); - link if is_used ~> mem.mstore(output_addr + 24, time_step + 1, output[6]); - link if is_used ~> mem.mstore(output_addr + 28, time_step + 1, output[7]); + // TODO: turn these into array operations: + + // Write the first half of the output + let output_addr; + link if is_used * output_first_half ~> mem.mstore(output_addr + 0, output_time_step, output[0]); + link if is_used * output_first_half ~> mem.mstore(output_addr + 4, output_time_step, output[1]); + link if is_used * output_first_half ~> mem.mstore(output_addr + 8, output_time_step, output[2]); + link if is_used * output_first_half ~> mem.mstore(output_addr + 12, output_time_step, output[3]); + + // Write the second half of the output + let second_half_addr = output_addr + 16 * output_first_half; + link if is_used * output_second_half ~> mem.mstore(second_half_addr + 0, output_time_step, output[4]); + link if is_used * output_second_half ~> mem.mstore(second_half_addr + 4, output_time_step, output[5]); + link if is_used * output_second_half ~> mem.mstore(second_half_addr + 8, output_time_step, output[6]); + link if is_used * output_second_half ~> mem.mstore(second_half_addr + 12, output_time_step, output[7]); } diff --git a/std/machines/hash/poseidon_bb.asm b/std/machines/hash/poseidon_bb.asm index 296a7a08c1..467ea7e34e 100644 --- a/std/machines/hash/poseidon_bb.asm +++ b/std/machines/hash/poseidon_bb.asm @@ -2,7 +2,6 @@ use std::array; use std::check::assert; use std::utils::unchanged_until; use std::utils::force_bool; -use std::utils::new_bool; use std::utils::sum; use std::convert::expr; use std::machines::small_field::memory::Memory; diff --git a/std/machines/split/split_gl_vec.asm b/std/machines/split/split_gl_vec.asm index 01b2ad431e..011a29da09 100644 --- a/std/machines/split/split_gl_vec.asm +++ b/std/machines/split/split_gl_vec.asm @@ -2,7 +2,7 @@ use std::array; use std::machines::large_field::memory::Memory; use super::split_gl::SplitGL; -machine SplitGLVec8(mem: Memory, split_gl: SplitGL) with +machine SplitGLVec4(mem: Memory, split_gl: SplitGL) with latch: latch, call_selectors: sel, { @@ -12,8 +12,8 @@ machine SplitGLVec8(mem: Memory, split_gl: SplitGL) with // Is this a used row? let is_used = array::sum(sel); - // Reads 8 memory words from input_addr as field elements at time_step - // and writes 16 memory words to output_addr with u32s representing + // Reads 4 memory words from input_addr as field elements at time_step + // and writes 8 memory words to output_addr with u32s representing // the decomposed field elements, in little-endian (i.e., the // lower word address is the least significant limb), in time_step + 1. // @@ -24,31 +24,23 @@ machine SplitGLVec8(mem: Memory, split_gl: SplitGL) with let output_addr; let time_step; - let input: col[8]; + let input: col[4]; // TODO: when link is available inside functions, we can turn this into array operations. link if is_used ~> input[0] = mem.mload(input_addr + 0, time_step); link if is_used ~> input[1] = mem.mload(input_addr + 4, time_step); link if is_used ~> input[2] = mem.mload(input_addr + 8, time_step); link if is_used ~> input[3] = mem.mload(input_addr + 12, time_step); - link if is_used ~> input[4] = mem.mload(input_addr + 16, time_step); - link if is_used ~> input[5] = mem.mload(input_addr + 20, time_step); - link if is_used ~> input[6] = mem.mload(input_addr + 24, time_step); - link if is_used ~> input[7] = mem.mload(input_addr + 28, time_step); // Split the output into high and low limbs - let output_low: col[8]; - let output_high: col[8]; + let output_low: col[4]; + let output_high: col[4]; // TODO: turn this into array operations link if is_used ~> (output_low[0], output_high[0]) = split_gl.split(input[0]); link if is_used ~> (output_low[1], output_high[1]) = split_gl.split(input[1]); link if is_used ~> (output_low[2], output_high[2]) = split_gl.split(input[2]); link if is_used ~> (output_low[3], output_high[3]) = split_gl.split(input[3]); - link if is_used ~> (output_low[4], output_high[4]) = split_gl.split(input[4]); - link if is_used ~> (output_low[5], output_high[5]) = split_gl.split(input[5]); - link if is_used ~> (output_low[6], output_high[6]) = split_gl.split(input[6]); - link if is_used ~> (output_low[7], output_high[7]) = split_gl.split(input[7]); // TODO: turn this into array operations link if is_used ~> mem.mstore(output_addr + 0, time_step + 1, output_low[0]); @@ -62,17 +54,4 @@ machine SplitGLVec8(mem: Memory, split_gl: SplitGL) with link if is_used ~> mem.mstore(output_addr + 24, time_step + 1, output_low[3]); link if is_used ~> mem.mstore(output_addr + 28, time_step + 1, output_high[3]); - - link if is_used ~> mem.mstore(output_addr + 32, time_step + 1, output_low[4]); - link if is_used ~> mem.mstore(output_addr + 36, time_step + 1, output_high[4]); - - link if is_used ~> mem.mstore(output_addr + 40, time_step + 1, output_low[5]); - link if is_used ~> mem.mstore(output_addr + 44, time_step + 1, output_high[5]); - - link if is_used ~> mem.mstore(output_addr + 48, time_step + 1, output_low[6]); - link if is_used ~> mem.mstore(output_addr + 52, time_step + 1, output_high[6]); - - link if is_used ~> mem.mstore(output_addr + 56, time_step + 1, output_low[7]); - link if is_used ~> mem.mstore(output_addr + 60, time_step + 1, output_high[7]); - } diff --git a/test_data/std/poseidon2_gl_test.asm b/test_data/std/poseidon2_gl_test.asm index 75fff89146..d48ca843e2 100644 --- a/test_data/std/poseidon2_gl_test.asm +++ b/test_data/std/poseidon2_gl_test.asm @@ -26,7 +26,8 @@ machine Main with degree: main_degree { link ~> memory.mstore(ADDR1, STEP, X1); Poseidon2GL poseidon2(memory, poseidon2_degree, poseidon2_degree); - instr poseidon2 ADDR1, ADDR2 -> link ~> poseidon2.poseidon2_permutation(ADDR1, ADDR2, STEP); + instr poseidon2 ADDR1, ADDR2, X1 -> + link ~> poseidon2.permute(ADDR1, STEP, ADDR2, STEP + 1, X1); col witness val; instr assert_eq ADDR1, X1 -> @@ -50,7 +51,24 @@ machine Main with degree: main_degree { mstore 24, 0; mstore 28, 0; - poseidon2 0, 0; + // Test only second half output + poseidon2 0, 100, 2; + + assert_eq 100, 5905145432652609062; + assert_eq 104, 9814446752588696081; + assert_eq 108, 13759450385053274731; + assert_eq 112, 2402148582355896469; + + // Test only first half output + poseidon2 0, 100, 1; + + assert_eq 100, 14905565590733827480; + assert_eq 104, 640905753703258831; + assert_eq 108, 4579128623722792381; + assert_eq 112, 158153743058056413; + + // Test full state output + poseidon2 0, 0, 3; assert_eq 0, 14905565590733827480; assert_eq 4, 640905753703258831; @@ -72,7 +90,7 @@ machine Main with degree: main_degree { mstore 24, 1; mstore 28, 1; - poseidon2 0, 0; + poseidon2 0, 0, 3; assert_eq 0, 18201552556563266798; assert_eq 4, 6814935789744812745; @@ -94,7 +112,7 @@ machine Main with degree: main_degree { mstore 24, 0xffffffff00000000; mstore 28, 0xffffffff00000000; - poseidon2 0, 0; + poseidon2 0, 0, 3; assert_eq 0, 13601391594672984423; assert_eq 4, 7799837486760213030; @@ -116,7 +134,7 @@ machine Main with degree: main_degree { mstore 24, 1456 * 2**32 + 1394942011; mstore 28, 2087; - poseidon2 0, 0; + poseidon2 0, 0, 3; assert_eq 0, 14498150941209346562; assert_eq 4, 8038616707062714447; @@ -138,7 +156,7 @@ machine Main with degree: main_degree { mstore 124, 0; mstore 128, 0; - poseidon2 100, 104; + poseidon2 100, 104, 3; assert_eq 104, 14905565590733827480; assert_eq 108, 640905753703258831; diff --git a/test_data/std/split_gl_vec_test.asm b/test_data/std/split_gl_vec_test.asm index 5aece007fd..2a97e73918 100644 --- a/test_data/std/split_gl_vec_test.asm +++ b/test_data/std/split_gl_vec_test.asm @@ -1,6 +1,6 @@ use std::machines::split::ByteCompare; use std::machines::split::split_gl::SplitGL; -use std::machines::split::split_gl_vec::SplitGLVec8; +use std::machines::split::split_gl_vec::SplitGLVec4; use std::machines::large_field::memory::Memory; use std::machines::range::Byte2; @@ -20,7 +20,7 @@ machine Main with degree: main_degree { ByteCompare byte_compare; SplitGL split_machine(byte_compare, split_degree, split_degree); - SplitGLVec8 split_vec_machine(memory, split_machine, split_vec_degree, split_vec_degree); + SplitGLVec4 split_vec_machine(memory, split_machine, split_vec_degree, split_vec_degree); col fixed STEP(i) { 2 * i }; @@ -39,20 +39,16 @@ machine Main with degree: main_degree { function main { // Store 8 field elements sequentially in memory - mstore 100, 0; + mstore 100, 1; mstore 104, 0xffffffff00000000; mstore 108, 0xfffffffeffffffff; mstore 112, 0xabcdef0123456789; - mstore 116, 0x0000000100000002; - mstore 120, 0x0000000300000004; - mstore 124, 0x0000000500000006; - mstore 128, 0x0000000700000008; // Split the previously stored field elements split 100, 200; // Assert the field elements are what was written - assert_eq 200, 0; + assert_eq 200, 1; assert_eq 204, 0; assert_eq 208, 0; @@ -64,23 +60,11 @@ machine Main with degree: main_degree { assert_eq 224, 0x23456789; assert_eq 228, 0xabcdef01; - assert_eq 232, 0x00000002; - assert_eq 236, 0x00000001; - - assert_eq 240, 0x00000004; - assert_eq 244, 0x00000003; - - assert_eq 248, 0x00000006; - assert_eq 252, 0x00000005; - - assert_eq 256, 0x00000008; - assert_eq 260, 0x00000007; - // Same split, but now overlaping the input and output split 100, 104; // Assert the field elements are what was written - assert_eq 104, 0; + assert_eq 104, 1; assert_eq 108, 0; assert_eq 112, 0; @@ -92,18 +76,6 @@ machine Main with degree: main_degree { assert_eq 128, 0x23456789; assert_eq 132, 0xabcdef01; - assert_eq 136, 0x00000002; - assert_eq 140, 0x00000001; - - assert_eq 144, 0x00000004; - assert_eq 148, 0x00000003; - - assert_eq 152, 0x00000006; - assert_eq 156, 0x00000005; - - assert_eq 160, 0x00000008; - assert_eq 164, 0x00000007; - return; } }