Skip to content

Commit 9dc3ebc

Browse files
author
Leo
authored
Merge pull request #1097 from powdr-labs/poseidon-regs
Use state registers directly in Poseidon
2 parents 490b301 + 961c5f8 commit 9dc3ebc

File tree

3 files changed

+19
-28
lines changed

3 files changed

+19
-28
lines changed

riscv-executor/src/lib.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ impl<'a, 'b, F: FieldElement> Executor<'a, 'b, F> {
714714
"shl" => vec![(args[0].u() << args[1].u()).into()],
715715
"shr" => vec![(args[0].u() >> args[1].u()).into()],
716716
"split_gl" => {
717-
let value = args[0].fe().to_integer();
717+
let value = args[0].into_fe().to_integer();
718718
// This instruction is only for Goldilocks, so the value must
719719
// fit into a u64.
720720
let value = value.try_into_u64().unwrap();
@@ -724,13 +724,16 @@ impl<'a, 'b, F: FieldElement> Executor<'a, 'b, F> {
724724
vec![lo.into(), hi.into()]
725725
}
726726
"poseidon_gl" => {
727-
let inputs = args
728-
.iter()
729-
.take(12)
730-
.map(|arg| arg.into_fe())
727+
assert!(args.is_empty());
728+
let inputs = (0..12)
729+
.map(|i| self.proc.get_reg(format!("P{}", i).as_str()).into_fe())
731730
.collect::<Vec<_>>();
732731
let result = poseidon_gl::poseidon_gl(&inputs);
733-
result.into_iter().map(Elem::Field).collect()
732+
(0..4).for_each(|i| {
733+
self.proc
734+
.set_reg(format!("P{}", i).as_str(), Elem::Field(result[i]))
735+
});
736+
vec![]
734737
}
735738
instr => {
736739
panic!("unknown instruction: {instr}");

riscv/src/continuations/bootloader.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,7 @@ mstore_bootloader x3 * {PAGE_SIZE_BYTES} + {i} * {BYTES_PER_WORD}, P{reg_index};
228228

229229
// Hash if buffer is full
230230
if i % 4 == 3 {
231-
bootloader.push_str(
232-
r#"
233-
P0, P1, P2, P3 <== poseidon_gl(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11);
234-
"#,
235-
);
231+
bootloader.push_str("poseidon_gl;");
236232
}
237233
}
238234

@@ -294,7 +290,7 @@ P1 <== load_bootloader_input(x2 * {BOOTLOADER_INPUTS_PER_PAGE} + {PAGE_INPUTS_OF
294290
P2 <== load_bootloader_input(x2 * {BOOTLOADER_INPUTS_PER_PAGE} + {PAGE_INPUTS_OFFSET} + 1 + {WORDS_PER_PAGE} + 4 + {i} * 4 + 2);
295291
P3 <== load_bootloader_input(x2 * {BOOTLOADER_INPUTS_PER_PAGE} + {PAGE_INPUTS_OFFSET} + 1 + {WORDS_PER_PAGE} + 4 + {i} * 4 + 3);
296292
bootloader_level_{i}_end:
297-
P0, P1, P2, P3 <== poseidon_gl(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11);
293+
poseidon_gl;
298294
"#
299295
));
300296
}
@@ -455,9 +451,7 @@ P11 <=X= 0;
455451

456452
// Hash if buffer is full
457453
if i % 4 == 3 {
458-
bootloader.push_str(
459-
"P0, P1, P2, P3 <== poseidon_gl(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11);\n",
460-
);
454+
bootloader.push_str("poseidon_gl;\n");
461455
}
462456
}
463457

riscv/src/coprocessors.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static POSEIDON_GL_COPROCESSOR: CoProcessor = CoProcessor {
5959
import: "use std::hash::poseidon_gl::PoseidonGL;",
6060
instructions: r#"
6161
// ================== hashing instructions ==============
62-
instr poseidon_gl A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11 -> X, Y, Z, W = poseidon_gl.poseidon_permutation;
62+
instr poseidon_gl = poseidon_gl.poseidon_permutation P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11 -> P0, P1, P2, P3;
6363
6464
"#,
6565
runtime_function_impl: Some(("poseidon_gl_coprocessor", poseidon_gl_call)),
@@ -199,18 +199,16 @@ impl CoProcessors {
199199
pub fn registers(&self) -> String {
200200
// Poseidon has 12 inputs and 4 outputs.
201201
// The base RISCV machine has 4 assignment registers.
202-
// Therefore we need to add 12 assignment registers when using Poseidon.
203-
// Moreover, we also need 12 extra general purpose registers to store the
204-
// input values.
202+
// We need 12 extra general purpose registers to store the
203+
// input and values directly.
205204

206205
if !self.coprocessors.contains_key(POSEIDON_GL_COPROCESSOR.name) {
207206
return String::new();
208207
}
209208

210-
let a_regs: Vec<String> = (0..12).map(|i| format!("reg A{}[<=];", i)).collect();
211209
let p_regs: Vec<String> = (0..12).map(|i| format!("reg P{};", i)).collect();
212210

213-
[a_regs, p_regs].concat().join("\n")
211+
p_regs.join("\n")
214212
}
215213
}
216214

@@ -244,7 +242,7 @@ fn poseidon_gl_call() -> String {
244242
)
245243
};
246244

247-
let call = "P0, P1, P2, P3 <== poseidon_gl(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11);";
245+
let call = "poseidon_gl;";
248246

249247
(0..12)
250248
.map(decoding)
@@ -273,18 +271,14 @@ pub fn call_every_submachine(coprocessors: &CoProcessors) -> Vec<String> {
273271
}
274272
if coprocessors.has(POSEIDON_GL_COPROCESSOR.name) {
275273
calls.extend(vec![
276-
"P0, P1, P2, x10 <== poseidon_gl(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11);"
277-
.to_string(),
274+
"poseidon_gl;".to_string(),
278275
"P0 <=X= 0;".to_string(),
279276
"P1 <=X= 0;".to_string(),
280277
"P2 <=X= 0;".to_string(),
278+
"P3 <=X= 0;".to_string(),
281279
]);
282280
}
283281
if coprocessors.has(SPLIT_GL_COPROCESSOR.name) {
284-
// SplitGL only makes sense when used with PoseidonGL, because there is
285-
// no other way to get a value in the full range of Goldilocks into a
286-
// register of the RISC-V zkVM.
287-
assert!(coprocessors.has(POSEIDON_GL_COPROCESSOR.name));
288282
calls.push("x10, x11 <== split_gl(x10);".to_string());
289283
}
290284

0 commit comments

Comments
 (0)