1use alloc::vec::Vec;
4use core::iter::{repeat, repeat_with};
5use core::marker::PhantomData;
6
7use p3_challenger::{
8 CanObserve, CanSample, CanSampleBits, CanSampleUniformBits, FieldChallenger,
9 GrindingChallenger, HashChallenger, ResamplingError,
10};
11use p3_field::BasedVectorSpace;
12use p3_maybe_rayon::prelude::*;
13use p3_symmetric::{CryptographicHasher, Hash, MerkleCap};
14use tracing::instrument;
15
16use crate::tower::TowerLevel;
17
18const BITS_SAMPLE_BYTES: usize = 8;
22
23const GRIND_MARGIN_BITS: usize = 8;
33
34#[derive(Clone, Debug)]
63pub struct BinaryChallenger<F, Inner> {
64 inner: Inner,
65 _marker: PhantomData<F>,
66}
67
68impl<F, Inner> BinaryChallenger<F, Inner> {
69 pub const fn new(inner: Inner) -> Self {
71 Self {
72 inner,
73 _marker: PhantomData,
74 }
75 }
76}
77
78impl<F, H> BinaryChallenger<F, HashChallenger<u8, H, 32>>
79where
80 H: CryptographicHasher<u8, [u8; 32]>,
81{
82 pub const fn from_hasher(initial_state: Vec<u8>, hasher: H) -> Self {
84 Self::new(HashChallenger::new(initial_state, hasher))
85 }
86}
87
88impl<F: TowerLevel, Inner: CanObserve<u8>> CanObserve<F> for BinaryChallenger<F, Inner> {
89 fn observe(&mut self, value: F) {
90 for byte in value.into_bytes() {
91 self.inner.observe(byte);
92 }
93 }
94}
95
96impl<F, const N: usize, Inner: CanObserve<u8>> CanObserve<Hash<F, u8, N>>
97 for BinaryChallenger<F, Inner>
98{
99 fn observe(&mut self, values: Hash<F, u8, N>) {
100 for value in values {
101 self.inner.observe(value);
102 }
103 }
104}
105
106impl<F, const N: usize, Inner: CanObserve<u8>> CanObserve<&MerkleCap<F, [u8; N]>>
107 for BinaryChallenger<F, Inner>
108{
109 fn observe(&mut self, cap: &MerkleCap<F, [u8; N]>) {
110 for digest in cap.roots() {
111 for value in digest {
112 self.inner.observe(*value);
113 }
114 }
115 }
116}
117
118impl<F, const N: usize, Inner: CanObserve<u8>> CanObserve<MerkleCap<F, [u8; N]>>
119 for BinaryChallenger<F, Inner>
120{
121 fn observe(&mut self, cap: MerkleCap<F, [u8; N]>) {
122 self.observe(&cap);
123 }
124}
125
126impl<F, EF, Inner> CanSample<EF> for BinaryChallenger<F, Inner>
127where
128 F: TowerLevel,
129 EF: BasedVectorSpace<F>,
130 Inner: CanSample<u8>,
131{
132 fn sample(&mut self) -> EF {
133 let inner = &mut self.inner;
134 EF::from_basis_coefficients_fn(|_| F::from_le_byte_iter(repeat_with(|| inner.sample())))
137 }
138}
139
140impl<F, Inner> CanSampleBits<usize> for BinaryChallenger<F, Inner>
141where
142 F: TowerLevel,
143 Inner: CanSample<u8>,
144{
145 fn sample_bits(&mut self, bits: usize) -> usize {
156 assert!(
157 bits < (usize::BITS as usize),
158 "requested bit count must fit within a usize"
159 );
160 let bytes: [u8; BITS_SAMPLE_BYTES] = self.inner.sample_array();
161 let rand_u64 = u64::from_le_bytes(bytes);
162 (rand_u64 & ((1u64 << bits) - 1)) as usize
163 }
164}
165
166impl<F, Inner> CanSampleUniformBits<F> for BinaryChallenger<F, Inner>
167where
168 F: TowerLevel,
169 Inner: CanSample<u8>,
170{
171 fn sample_uniform_bits<const RESAMPLE: bool>(
183 &mut self,
184 bits: usize,
185 ) -> Result<usize, ResamplingError> {
186 Ok(self.sample_bits(bits))
189 }
190}
191
192#[inline]
197fn candidate<F: TowerLevel>(index: u64) -> F {
198 F::from_le_byte_iter(index.to_le_bytes().into_iter().chain(repeat(0)))
199}
200
201impl<F, Inner> GrindingChallenger for BinaryChallenger<F, Inner>
202where
203 F: TowerLevel,
204 Inner: CanSample<u8> + CanObserve<u8> + Clone + Send + Sync,
205{
206 type Witness = F;
207
208 #[instrument(name = "grind for proof-of-work witness", skip_all)]
212 fn grind(&mut self, bits: usize) -> Self::Witness {
213 if bits == 0 {
215 return F::ZERO;
216 }
217
218 assert!(bits < (usize::BITS as usize));
219 assert!(
220 bits + GRIND_MARGIN_BITS <= F::bits().min(u64::BITS as usize),
221 "requested bit count leaves too small a margin against the witness field's size"
222 );
223
224 let num_candidates = if F::bits() >= u64::BITS as usize {
227 u64::MAX
228 } else {
229 1u64 << F::bits()
230 };
231
232 let witness = (0..num_candidates)
233 .into_par_iter()
234 .map(candidate)
235 .find_any(|witness| self.clone().check_witness(bits, *witness))
236 .expect("failed to find witness");
237 assert!(self.check_witness(bits, witness));
238 witness
239 }
240}
241
242impl<F, Inner> FieldChallenger<F> for BinaryChallenger<F, Inner>
243where
244 F: TowerLevel,
245 Inner: CanSample<u8> + CanObserve<u8> + Clone + Send + Sync,
246{
247}
248
249#[cfg(test)]
250mod tests {
251 use alloc::vec;
252 use alloc::vec::Vec;
253
254 use p3_challenger::{
255 CanObserve, CanSample, CanSampleBits, CanSampleUniformBits, FieldChallenger,
256 GrindingChallenger, HashChallenger,
257 };
258 use p3_field::{BasedVectorSpace, Field, PrimeCharacteristicRing, RawDataSerializable};
259 use p3_keccak::Keccak256Hash;
260 use p3_symmetric::{Hash, MerkleCap};
261
262 use crate::challenger::{BITS_SAMPLE_BYTES, BinaryChallenger};
263 use crate::{BinaryField8, BinaryField32, BinaryField128, Gf2};
264
265 type Inner = HashChallenger<u8, Keccak256Hash, 32>;
266
267 fn mk<F>() -> BinaryChallenger<F, Inner> {
269 BinaryChallenger::from_hasher(vec![], Keccak256Hash)
270 }
271
272 fn mk_inner() -> Inner {
274 HashChallenger::new(vec![], Keccak256Hash)
275 }
276
277 fn a128() -> BinaryField128 {
279 BinaryField128::from_le_bytes([
280 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed, 0x0f, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
281 0x34, 0x12,
282 ])
283 }
284
285 #[test]
286 fn sampling_is_deterministic_and_observation_dependent() {
287 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
289 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
290 assert_eq!(x, y);
291
292 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
294 a.observe(a128());
295 b.observe(a128());
296 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
297 assert_eq!(x, y);
298
299 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
301 a.observe(BinaryField128::ONE);
302 b.observe(BinaryField128::ZERO);
303 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
304 assert_ne!(x, y);
305
306 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
308 b.observe(BinaryField128::ZERO);
309 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
310 assert_ne!(x, y);
311
312 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
315 let xs: [BinaryField128; 4] = a.sample_array();
316 let ys: [BinaryField128; 4] = b.sample_array();
317 assert_eq!(xs, ys);
318 assert_ne!(xs[0], xs[1]);
319 assert_ne!(xs[1], xs[2]);
320 assert_ne!(xs[2], xs[3]);
321 }
322
323 #[test]
324 fn observing_an_element_absorbs_its_little_endian_bytes() {
325 let a = a128();
326
327 let mut challenger = mk::<BinaryField128>();
328 challenger.observe(a);
329
330 let mut inner = mk_inner();
331 inner.observe_slice(&a.into_bytes().into_iter().collect::<Vec<_>>());
332
333 for _ in 0..32 {
335 let observed: u8 = challenger.inner.sample();
336 let expected: u8 = inner.sample();
337 assert_eq!(observed, expected);
338 }
339 }
340
341 #[test]
342 fn a_sampled_element_is_read_from_the_little_endian_byte_stream() {
343 let mut challenger = mk::<BinaryField128>();
344 let sampled: BinaryField128 = challenger.sample();
345
346 let mut inner = mk_inner();
347 let bytes: [u8; 16] = core::array::from_fn(|_| inner.sample());
348
349 assert_eq!(sampled, BinaryField128::from_le_bytes(bytes));
350 }
351
352 #[test]
353 fn a_sampled_element_of_a_narrow_level_reads_only_its_own_bytes() {
354 let mut challenger = mk::<BinaryField32>();
355 let sampled: BinaryField32 = challenger.sample();
356
357 let mut inner = mk_inner();
358 let bytes: [u8; 4] = core::array::from_fn(|_| inner.sample());
359
360 assert_eq!(sampled, BinaryField32::from_le_bytes(bytes));
361 }
362
363 #[test]
364 fn sampling_an_extension_element_reads_its_basis_coefficients_in_order() {
365 let mut challenger = mk::<BinaryField8>();
366 let sampled: BinaryField128 = challenger.sample();
367
368 let mut coefficients = mk::<BinaryField8>();
369 let coeffs: [BinaryField8; 16] = core::array::from_fn(|_| coefficients.sample());
370
371 assert_eq!(
372 <BinaryField128 as BasedVectorSpace<BinaryField8>>::from_basis_coefficients_fn(|i| {
373 coeffs[i]
374 }),
375 sampled
376 );
377 }
378
379 #[test]
380 fn observing_digests_matches_observing_their_bytes() {
381 let digest = [1_u8, 2, 3, 4];
382
383 let mut from_hash = mk::<BinaryField128>();
384 from_hash.observe(Hash::<BinaryField128, u8, 4>::from(digest));
385
386 let cap = MerkleCap::<BinaryField128, [u8; 4]>::new(vec![digest, [5, 6, 7, 8]]);
387 let mut from_cap_ref = mk::<BinaryField128>();
388 from_cap_ref.observe(&cap);
389 let mut from_cap = mk::<BinaryField128>();
390 from_cap.observe(cap);
391
392 let mut hash_bytes = mk_inner();
393 hash_bytes.observe_slice(&digest);
394 let mut cap_bytes = mk_inner();
395 cap_bytes.observe_slice(&[1, 2, 3, 4, 5, 6, 7, 8]);
396
397 for _ in 0..32 {
398 let expected: u8 = hash_bytes.sample();
399 assert_eq!(from_hash.inner.sample(), expected);
400
401 let expected: u8 = cap_bytes.sample();
402 assert_eq!(from_cap_ref.inner.sample(), expected);
403 assert_eq!(from_cap.inner.sample(), expected);
404 }
405 }
406
407 #[test]
408 fn sampled_bits_fit_the_requested_width_and_are_reproducible() {
409 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
410 for bits in 0..32 {
411 let value = a.sample_bits(bits);
412 assert!(value < (1 << bits), "{value} does not fit in {bits} bits");
413 assert_eq!(value, b.sample_bits(bits));
414 }
415
416 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
418 a.observe(BinaryField128::ONE);
419 assert_ne!(a.sample_bits(31), b.sample_bits(31));
420 }
421
422 #[test]
423 fn uniform_bits_agree_with_plain_bits_and_never_reject() {
424 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
425 for bits in [0, 1, 7, 8, 16, 31] {
426 assert_eq!(
427 a.sample_uniform_bits::<true>(bits).unwrap(),
428 b.sample_bits(bits)
429 );
430 }
431
432 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
433 for bits in [0, 1, 7, 8, 16, 31] {
434 assert_eq!(
435 a.sample_uniform_bits::<false>(bits).unwrap(),
436 b.sample_bits(bits)
437 );
438 }
439 }
440
441 #[test]
444 fn sample_bits_is_not_limited_by_the_width_of_the_field() {
445 assert_eq!(<BinaryField8 as Field>::bits(), 8);
448 let mut challenger = mk::<BinaryField8>();
449 let sampled = challenger.sample_bits(24);
450 assert!(sampled < (1 << 24));
451
452 let mut inner = mk_inner();
453 let bytes: [u8; BITS_SAMPLE_BYTES] = core::array::from_fn(|_| inner.sample());
454 assert_eq!(sampled, (u64::from_le_bytes(bytes) & 0xff_ffff) as usize);
455
456 let mut challenger = mk::<BinaryField8>();
458 assert_eq!(challenger.sample_uniform_bits::<true>(24).unwrap(), sampled);
459 let mut challenger = mk::<BinaryField8>();
460 assert_eq!(
461 challenger.sample_uniform_bits::<false>(24).unwrap(),
462 sampled
463 );
464
465 let widest = usize::BITS as usize - 1;
467 let mut challenger = mk::<BinaryField8>();
468 assert!(challenger.sample_bits(widest) < (1 << widest));
469 }
470
471 #[test]
472 #[should_panic = "requested bit count must fit within a usize"]
473 fn sample_bits_rejects_a_request_wider_than_a_usize() {
474 let mut challenger = mk::<BinaryField128>();
475 let _ = challenger.sample_bits(usize::BITS as usize);
476 }
477
478 #[test]
479 #[should_panic = "requested bit count leaves too small a margin"]
480 fn grind_rejects_a_request_wider_than_the_field() {
481 let mut challenger = mk::<BinaryField32>();
482 let _ = challenger.grind(32);
483 }
484
485 #[test]
486 #[should_panic = "requested bit count leaves too small a margin"]
487 fn grind_rejects_a_request_inside_the_margin() {
488 let mut challenger = mk::<BinaryField32>();
490 let _ = challenger.grind(25);
491 }
492
493 #[derive(Clone)]
497 struct AlwaysZeroInner;
498
499 impl CanObserve<u8> for AlwaysZeroInner {
500 fn observe(&mut self, _value: u8) {}
501 }
502
503 impl CanSample<u8> for AlwaysZeroInner {
504 fn sample(&mut self) -> u8 {
505 0
506 }
507 }
508
509 #[test]
510 #[should_panic = "requested bit count leaves too small a margin"]
511 fn grind_rejects_a_request_the_u64_cap_no_longer_allows() {
512 let mut challenger = mk::<BinaryField128>();
517 let _ = challenger.grind(63);
518 }
519
520 #[test]
521 fn grind_accepts_the_widest_request_the_u64_cap_allows() {
522 let mut challenger: BinaryChallenger<BinaryField128, AlwaysZeroInner> =
528 BinaryChallenger::new(AlwaysZeroInner);
529 let witness = challenger.grind(56);
530 assert!(challenger.check_witness(56, witness));
531 }
532
533 #[test]
534 fn a_bitstring_sample_reads_a_fixed_number_of_bytes() {
535 let mut challenger = mk::<BinaryField128>();
538 let sampled = challenger.sample_bits(31);
539
540 let mut inner = mk_inner();
541 let bytes: [u8; BITS_SAMPLE_BYTES] = core::array::from_fn(|_| inner.sample());
542
543 assert_eq!(BITS_SAMPLE_BYTES, 8);
544 assert_eq!(
545 sampled,
546 (u64::from_le_bytes(bytes) & ((1 << 31) - 1)) as usize
547 );
548
549 let next = challenger.sample_bits(8);
551 let bytes: [u8; BITS_SAMPLE_BYTES] = core::array::from_fn(|_| inner.sample());
552 assert_eq!(next, (u64::from_le_bytes(bytes) & 0xff) as usize);
553 }
554
555 #[test]
556 fn grind_satisfies_check() {
557 let mut challenger = mk::<BinaryField128>();
558 let witness = challenger.clone().grind(8);
559 assert!(challenger.check_witness(8, witness));
560 }
561
562 #[test]
563 fn grind_over_a_narrow_level_satisfies_check() {
564 let mut challenger = mk::<BinaryField32>();
565 let witness = challenger.clone().grind(8);
566 assert!(challenger.check_witness(8, witness));
567 }
568
569 #[test]
570 fn grind_of_zero_bits_is_free() {
571 let mut challenger = mk::<BinaryField128>();
572 let mut shadow = challenger.clone();
573
574 let witness = challenger.grind(0);
575 assert_eq!(witness, BinaryField128::ZERO);
576
577 for _ in 0..32 {
579 let expected: u8 = shadow.inner.sample();
580 assert_eq!(challenger.inner.sample(), expected);
581 }
582 }
583
584 #[test]
585 fn grind_of_zero_bits_is_free_on_a_level_narrower_than_the_margin() {
586 let mut challenger = mk::<Gf2>();
589 let mut shadow = challenger.clone();
590
591 let witness = challenger.grind(0);
592 assert_eq!(witness, Gf2::ZERO);
593
594 for _ in 0..32 {
596 let expected: u8 = shadow.inner.sample();
597 assert_eq!(challenger.inner.sample(), expected);
598 }
599 }
600
601 #[test]
602 fn a_wrong_witness_fails_the_check() {
603 let mut challenger = mk::<BinaryField128>();
604 let witness = challenger.clone().grind(8);
605
606 let mut wrong = challenger.clone();
609 assert!(!wrong.check_witness(8, witness + BinaryField128::ONE));
610 assert!(challenger.check_witness(8, witness));
611 }
612
613 #[test]
615 fn field_challenger_algebra_helpers_round_trip() {
616 let mut challenger = mk::<BinaryField8>();
617 challenger.observe_algebra_element(a128());
618 let sampled: BinaryField128 = challenger.sample_algebra_element();
619
620 let mut expected = mk::<BinaryField8>();
621 expected
622 .observe_slice(BasedVectorSpace::<BinaryField8>::as_basis_coefficients_slice(&a128()));
623 let expected: BinaryField128 = expected.sample();
624
625 assert_eq!(sampled, expected);
626 }
627}