Conversation
How to use the Graphite Merge QueueAdd the label merge-ready to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
d0cca1a to
31d1a20
Compare
31d1a20 to
af2771c
Compare
| for val in a { | ||
| let reg = self.read_reg(); | ||
| self.store(ctx, reg, val); | ||
| } |
There was a problem hiding this comment.
Critical Bug: Incorrect State Writeback in Keccak-f[1600] Implementation
There's a significant issue with the state writeback logic in the exec_keccakf1600 function. Currently, the writeback loop (lines 507-510) is inside the round loop, causing state values to be written back after each round:
for &round_constant in &CONSTS[..24] {
// θ, ρ, π, χ, ι steps...
// writeback - THIS IS THE PROBLEM
for val in a {
let reg = self.read_reg();
self.store(ctx, reg, val);
}
}This is incorrect because:
- It overwrites intermediate state values 24 times
- It expects 24×25 output registers when the gate only provides 25
- It produces incorrect permutation results
The writeback loop should be moved outside and after the round loop, so it executes only once after all 24 rounds are complete:
for &round_constant in &CONSTS[..24] {
// θ, ρ, π, χ, ι steps...
}
// writeback (only once, after all rounds)
for val in a {
let reg = self.read_reg();
self.store(ctx, reg, val);
}This change will ensure the correct final state is written to the output registers.
| for val in a { | |
| let reg = self.read_reg(); | |
| self.store(ctx, reg, val); | |
| } | |
| } | |
| // Writeback (only once, after all rounds) | |
| for val in a { | |
| let reg = self.read_reg(); | |
| self.store(ctx, reg, val); | |
| } |
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
|
|
||
| use super::gate::keccakf1600::{CONSTS, R}; | ||
|
|
||
| fn idx(x: usize, y: usize) -> usize { |
There was a problem hiding this comment.
minor: Is there a reason not to reuse the public idx function from keccakf1600?
|
suggestion: Add a test in keccakf1600 that builds a circuit using the |
| // θ | ||
| let c: [Vec<RotWire>; 5] = | ||
| array::from_fn(|i| (0..5).map(|j| plain(pre[idx(i, j)])).collect()); | ||
| let d: [Vec<RotWire>; 5] = |
There was a problem hiding this comment.
I'm pretty sure committing the d wires would make the shift reduction more efficient. The main cost in shift reduction is the total number of different ShiftedWireIndices referenced (regardless of how many different constraints/operands reference them). When d is not committed, each rotation in the ρ steps applies to 5x as many wires.
|
This is superseded by gate fusion. Closing down. |

Introducing an intrinsic
Keccakf1600opcode, which instantiates an optimal 600 AND constraint circuit.The
keccakexample has a--no-intrinsicflag to facilitate comparison with the gate fusion approach.