Skip to content

Commit bf4e332

Browse files
committed
[iop-prover] Fix commit_masked for msg_len < packing width
When log_len < P::LOG_WIDTH, the message and mask each fit within a single packed element, so concatenating them at the packed level produces two separate P values rather than the intended log_len + 1 scalars packed into one P. In that case, build the combined value with P::from_scalars over the chained scalar iterators instead. Same fix applied at the call site in basefold_zk_channel where the combined (witness || mask) buffer is constructed for prove_zk.
1 parent 39b4546 commit bf4e332

File tree

2 files changed

+37
-15
lines changed

2 files changed

+37
-15
lines changed

crates/iop-prover/src/basefold_zk_channel.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//! this channel always applies zero-knowledge blinding to all oracles by generating masks
88
//! internally.
99
10+
use std::iter;
11+
1012
use binius_field::{BinaryField, PackedField};
1113
use binius_iop::{channel::OracleSpec, fri::FRIParams, merkle_tree::MerkleTreeScheme};
1214
use binius_ip_prover::channel::IPProverChannel;
@@ -182,23 +184,35 @@ where
182184
buffer.log_len()
183185
);
184186

185-
// Copy the message for later use in prove_zk (commit_masked consumes buffer).
186-
let log_len = buffer.log_len();
187-
let message_values: Box<[P]> = buffer.as_ref().into();
188-
189187
// Generate mask, interleave, and commit via commit_masked.
190188
let CommitMaskedOutput {
191189
commitment,
192190
committed,
193191
codeword,
194192
mask,
195-
} = fri::commit_masked(fri_params, self.ntt, self.merkle_prover, buffer, &mut self.rng)
196-
.expect("FRI commit_masked should succeed with valid params");
193+
} = fri::commit_masked(
194+
fri_params,
195+
self.ntt,
196+
self.merkle_prover,
197+
buffer.to_ref(),
198+
&mut self.rng,
199+
)
200+
.expect("FRI commit_masked should succeed with valid params");
197201

198202
// Build the combined (witness || mask) buffer for later use in prove_zk.
199-
let mut combined_values = Vec::with_capacity(message_values.len() * 2);
200-
combined_values.extend_from_slice(&message_values);
201-
combined_values.extend_from_slice(mask.as_ref());
203+
let log_len = buffer.log_len();
204+
let combined_values = if log_len < P::LOG_WIDTH {
205+
let combined_value =
206+
P::from_scalars(iter::chain(buffer.iter_scalars(), mask.iter_scalars()));
207+
vec![combined_value]
208+
} else {
209+
// TODO: The concatenation here is sequential and a performance issue. Ideally, commit
210+
// should not allocate and copy the memory into a temp buffer.
211+
// TODO: At the very least, make this a parallel copy
212+
iter::chain(buffer.as_ref(), mask.as_ref())
213+
.copied()
214+
.collect::<Vec<_>>()
215+
};
202216
let combined = FieldBuffer::new(log_len + 1, combined_values.into_boxed_slice());
203217

204218
// Send commitment via transcript.

crates/iop-prover/src/fri/commit.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2025 Irreducible Inc.
22
// Copyright 2026 The Binius Developers
33

4+
use std::iter;
5+
46
use binius_field::{BinaryField, PackedField};
57
use binius_iop::{fri::FRIParams, merkle_tree::MerkleTreeScheme};
68
use binius_math::{FieldBuffer, FieldSlice, ntt::AdditiveNTT};
@@ -133,12 +135,18 @@ where
133135
par_rand::<StdRng, _, _>(packed_len, &mut rng, P::random).collect(),
134136
);
135137

136-
// TODO: The concatenation here is sequential and a performance issue. Ideally, commit should
137-
// not allocate and copy the memory into a temp buffer.
138-
let combined_packed_len = packed_len * 2;
139-
let mut combined_values = Vec::with_capacity(combined_packed_len);
140-
combined_values.extend_from_slice(message.as_ref());
141-
combined_values.extend_from_slice(mask.as_ref());
138+
let combined_values = if log_len < P::LOG_WIDTH {
139+
let combined_value =
140+
P::from_scalars(iter::chain(message.iter_scalars(), mask.iter_scalars()));
141+
vec![combined_value]
142+
} else {
143+
// TODO: The concatenation here is sequential and a performance issue. Ideally, commit
144+
// should not allocate and copy the memory into a temp buffer.
145+
// TODO: At the very least, make this a parallel copy
146+
iter::chain(message.as_ref(), mask.as_ref())
147+
.copied()
148+
.collect::<Vec<_>>()
149+
};
142150
let combined = FieldBuffer::new(log_len + 1, combined_values.into_boxed_slice());
143151

144152
let CommitOutput {

0 commit comments

Comments
 (0)