Skip to content

Commit bc486f3

Browse files
committed
[frontend] Combine message and chain tweaks
1 parent 6e7d272 commit bc486f3

File tree

7 files changed

+950
-603
lines changed

7 files changed

+950
-603
lines changed

crates/frontend/src/circuits/hash_based_sig/chain.rs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use binius_core::Word;
22

3-
use super::tweak::ChainTweak;
3+
use super::tweak::verify_chain_tweak;
44
use crate::{
5-
circuits::multiplexer::multi_wire_multiplex,
5+
circuits::{keccak::Keccak, multiplexer::multi_wire_multiplex},
66
compiler::{CircuitBuilder, Wire},
77
};
88

@@ -41,7 +41,7 @@ use crate::{
4141
///
4242
/// # Returns
4343
///
44-
/// A vector of `ChainTweak` hashers that need to be populated with witness values.
44+
/// A vector of `Keccak` hashers that need to be populated with witness values.
4545
/// The number of hashers equals the maximum chain length supported.
4646
#[allow(clippy::too_many_arguments)]
4747
pub fn verify_chain(
@@ -53,7 +53,7 @@ pub fn verify_chain(
5353
coordinate: Wire,
5454
max_chain_len: u64,
5555
end_hash: [Wire; 4],
56-
) -> Vec<ChainTweak> {
56+
) -> Vec<Keccak> {
5757
assert!(
5858
param_len <= param.len() * 8,
5959
"param_len {} exceeds maximum capacity {} of param wires",
@@ -74,7 +74,7 @@ pub fn verify_chain(
7474
let (position_plus_one, _) = builder.iadd_cin_cout(position, one, zero);
7575

7676
let next_hash = std::array::from_fn(|_| builder.add_witness());
77-
let hasher = ChainTweak::new(
77+
let keccak = verify_chain_tweak(
7878
builder,
7979
param.to_vec(),
8080
param_len,
@@ -84,7 +84,7 @@ pub fn verify_chain(
8484
next_hash,
8585
);
8686

87-
hashers.push(hasher);
87+
hashers.push(keccak);
8888

8989
// Conditionally select the hash based on whether position + 1 < max_chain_len
9090
// If position + 1 < max_chain_len, use next_hash, otherwise keep current_hash
@@ -106,7 +106,7 @@ mod tests {
106106
use proptest::{prelude::*, strategy::Just};
107107
use sha3::{Digest, Keccak256};
108108

109-
use super::*;
109+
use super::{super::tweak::build_chain_tweak, *};
110110
use crate::{constraint_verifier::verify_constraints, util::pack_bytes_into_wires_le};
111111

112112
proptest! {
@@ -147,38 +147,41 @@ mod tests {
147147
w[chain_index] = Word::from_u64(chain_index_val);
148148
w[coordinate] = Word::from_u64(coordinate_val);
149149

150+
// Populate param wires (they're reused for all hashers)
151+
pack_bytes_into_wires_le(&mut w, &param, &param_bytes);
152+
153+
// Track current hash through the chain
150154
let mut current_hash: [u8; 32] = signature_chunk_bytes;
151-
for (step, hasher) in hashers.iter().enumerate() {
152-
let hash_position = step as u64 + coordinate_val + 1;
153155

154-
hasher.populate_param(&mut w, &param_bytes);
155-
hasher.populate_hash(&mut w, &current_hash);
156-
hasher.populate_chain_index(&mut w, chain_index_val);
157-
hasher.populate_position(&mut w, hash_position);
156+
for (step, keccak) in hashers.iter().enumerate() {
157+
// Calculate position for this step
158+
let position = step as u64 + coordinate_val;
159+
let position_plus_one = position + 1;
158160

159-
let message = ChainTweak::build_message(
161+
// Build the message for this hash using current_hash
162+
let message = build_chain_tweak(
160163
&param_bytes,
161164
&current_hash,
162165
chain_index_val,
163-
hash_position,
166+
position_plus_one,
164167
);
165-
hasher.populate_message(&mut w, &message);
166168

167-
// The circuit always computes the hash, even if it won't be used in the final result
168-
// This is because the constraint system verifies all hash computations
169+
// Populate the Keccak circuit
170+
keccak.populate_message(&mut w, &message);
171+
172+
// Compute the hash
169173
let digest: [u8; 32] = Keccak256::digest(&message).into();
170-
hasher.populate_digest(&mut w, digest);
174+
keccak.populate_digest(&mut w, digest);
171175

172-
// Only update current_hash if this hash is actually selected by the multiplexer
173-
// (when hash_position < max_chain_len)
174-
if hash_position < max_chain_len {
176+
// Update current_hash for next iteration if this hash is selected
177+
// The multiplexer in the circuit selects next_hash when position_plus_one < max_chain_len
178+
if position_plus_one < max_chain_len {
175179
current_hash = digest;
176180
}
177181
}
178182

179183
pack_bytes_into_wires_le(&mut w, &end_hash, &current_hash);
180184
pack_bytes_into_wires_le(&mut w, &signature_chunk, &signature_chunk_bytes);
181-
pack_bytes_into_wires_le(&mut w, &param, &param_bytes);
182185
circuit.populate_wire_witness(&mut w).unwrap();
183186

184187
let cs = circuit.constraint_system();

0 commit comments

Comments
 (0)