1use alloc::vec::Vec;
4use core::iter::repeat;
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)]
64pub struct BinaryChallenger<F, Inner> {
65 inner: Inner,
66 _marker: PhantomData<F>,
67}
68
69impl<F, Inner> BinaryChallenger<F, Inner> {
70 pub const fn new(inner: Inner) -> Self {
72 Self {
73 inner,
74 _marker: PhantomData,
75 }
76 }
77}
78
79impl<F, H> BinaryChallenger<F, HashChallenger<u8, H, 32>>
80where
81 H: CryptographicHasher<u8, [u8; 32]>,
82{
83 pub const fn from_hasher(initial_state: Vec<u8>, hasher: H) -> Self {
85 Self::new(HashChallenger::new(initial_state, hasher))
86 }
87}
88
89impl<F: TowerLevel, Inner: CanObserve<u8>> CanObserve<F> for BinaryChallenger<F, Inner> {
90 fn observe(&mut self, value: F) {
91 let mut bytes = [0; 16];
92 for (slot, byte) in bytes.iter_mut().zip(value.into_bytes()) {
93 *slot = byte;
94 }
95 self.inner.observe_slice(&bytes[..F::NUM_BYTES]);
96 }
97}
98
99impl<F, G, const N: usize, Inner: CanObserve<u8>> CanObserve<Hash<G, u8, N>>
100 for BinaryChallenger<F, Inner>
101{
102 fn observe(&mut self, values: Hash<G, u8, N>) {
103 self.inner.observe_slice(values.as_ref());
104 }
105}
106
107impl<F, G, const N: usize, Inner: CanObserve<u8>> CanObserve<&MerkleCap<G, [u8; N]>>
108 for BinaryChallenger<F, Inner>
109{
110 fn observe(&mut self, cap: &MerkleCap<G, [u8; N]>) {
111 for digest in cap.roots() {
112 self.inner.observe_slice(digest);
113 }
114 }
115}
116
117impl<F, G, const N: usize, Inner: CanObserve<u8>> CanObserve<MerkleCap<G, [u8; N]>>
118 for BinaryChallenger<F, Inner>
119{
120 fn observe(&mut self, cap: MerkleCap<G, [u8; N]>) {
121 self.observe(&cap);
122 }
123}
124
125impl<F, G, const N: usize, Inner: CanObserve<u8>> CanObserve<Hash<G, u64, N>>
130 for BinaryChallenger<F, Inner>
131{
132 fn observe(&mut self, values: Hash<G, u64, N>) {
133 for value in values {
134 self.inner.observe_slice(&value.to_le_bytes());
135 }
136 }
137}
138
139impl<F, G, const N: usize, Inner: CanObserve<u8>> CanObserve<&MerkleCap<G, [u64; N]>>
140 for BinaryChallenger<F, Inner>
141{
142 fn observe(&mut self, cap: &MerkleCap<G, [u64; N]>) {
143 for digest in cap.roots() {
144 for value in digest {
145 self.inner.observe_slice(&value.to_le_bytes());
146 }
147 }
148 }
149}
150
151impl<F, G, const N: usize, Inner: CanObserve<u8>> CanObserve<MerkleCap<G, [u64; N]>>
152 for BinaryChallenger<F, Inner>
153{
154 fn observe(&mut self, cap: MerkleCap<G, [u64; N]>) {
155 self.observe(&cap);
156 }
157}
158
159impl<F, EF, Inner> CanSample<EF> for BinaryChallenger<F, Inner>
160where
161 F: TowerLevel,
162 EF: BasedVectorSpace<F>,
163 Inner: CanSample<u8>,
164{
165 fn sample(&mut self) -> EF {
166 let inner = &mut self.inner;
167 EF::from_basis_coefficients_fn(|_| {
170 let mut bytes = [0; 16];
171 inner.sample_into_slice(&mut bytes[..F::NUM_BYTES]);
172 F::from_le_byte_iter(bytes.into_iter())
173 })
174 }
175}
176
177impl<F, Inner> CanSampleBits<usize> for BinaryChallenger<F, Inner>
178where
179 F: TowerLevel,
180 Inner: CanSample<u8>,
181{
182 fn sample_bits(&mut self, bits: usize) -> usize {
193 assert!(
194 bits < (usize::BITS as usize),
195 "requested bit count must fit within a usize"
196 );
197 let mut bytes = [0; BITS_SAMPLE_BYTES];
198 self.inner.sample_into_slice(&mut bytes);
199 let rand_u64 = u64::from_le_bytes(bytes);
200 (rand_u64 & ((1u64 << bits) - 1)) as usize
201 }
202}
203
204impl<F, Inner> CanSampleUniformBits<F> for BinaryChallenger<F, Inner>
205where
206 F: TowerLevel,
207 Inner: CanSample<u8>,
208{
209 fn sample_uniform_bits<const RESAMPLE: bool>(
221 &mut self,
222 bits: usize,
223 ) -> Result<usize, ResamplingError> {
224 Ok(self.sample_bits(bits))
227 }
228}
229
230#[inline]
235fn candidate<F: TowerLevel>(index: u64) -> F {
236 F::from_le_byte_iter(index.to_le_bytes().into_iter().chain(repeat(0)))
237}
238
239impl<F, Inner> GrindingChallenger for BinaryChallenger<F, Inner>
240where
241 F: TowerLevel,
242 Inner: CanSample<u8> + CanObserve<u8> + Clone + Send + Sync,
243{
244 type Witness = F;
245
246 #[instrument(name = "grind for proof-of-work witness", skip_all)]
250 fn grind(&mut self, bits: usize) -> Self::Witness {
251 if bits == 0 {
253 return F::ZERO;
254 }
255
256 assert!(bits < (usize::BITS as usize));
257 assert!(
258 bits + GRIND_MARGIN_BITS <= F::bits().min(u64::BITS as usize),
259 "requested bit count leaves too small a margin against the witness field's size"
260 );
261
262 let num_candidates = if F::bits() >= u64::BITS as usize {
265 u64::MAX
266 } else {
267 1u64 << F::bits()
268 };
269
270 let witness = (0..num_candidates)
271 .into_par_iter()
272 .map_init(
273 || self.clone(),
274 |worker, index| {
275 worker.inner.clone_from(&self.inner);
276 let witness = candidate(index);
277 worker.check_witness(bits, witness).then_some(witness)
278 },
279 )
280 .find_map_any(core::convert::identity)
281 .expect("failed to find witness");
282 assert!(self.check_witness(bits, witness));
283 witness
284 }
285}
286
287impl<F, Inner> FieldChallenger<F> for BinaryChallenger<F, Inner>
288where
289 F: TowerLevel,
290 Inner: CanSample<u8> + CanObserve<u8> + Clone + Send + Sync,
291{
292}
293
294#[cfg(test)]
295mod tests {
296 use alloc::vec;
297 use alloc::vec::Vec;
298
299 use p3_challenger::{
300 CanObserve, CanSample, CanSampleBits, CanSampleUniformBits, FieldChallenger,
301 GrindingChallenger, HashChallenger,
302 };
303 use p3_field::{BasedVectorSpace, Field, PrimeCharacteristicRing, RawDataSerializable};
304 use p3_keccak::Keccak256Hash;
305 use p3_symmetric::{Hash, MerkleCap};
306
307 use crate::challenger::{BITS_SAMPLE_BYTES, BinaryChallenger};
308 use crate::tower::TowerLevel;
309 use crate::{BinaryField8, BinaryField32, BinaryField128, Gf2, Ghash128};
310
311 type Inner = HashChallenger<u8, Keccak256Hash, 32>;
312
313 fn mk<F>() -> BinaryChallenger<F, Inner> {
315 BinaryChallenger::from_hasher(vec![], Keccak256Hash)
316 }
317
318 fn mk_inner() -> Inner {
320 HashChallenger::new(vec![], Keccak256Hash)
321 }
322
323 fn a128() -> BinaryField128 {
325 BinaryField128::from_le_bytes([
326 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed, 0x0f, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
327 0x34, 0x12,
328 ])
329 }
330
331 #[test]
332 fn the_polynomial_basis_field_shares_the_transcript_with_the_tower() {
333 let element = a128();
340
341 let mut tower = mk::<BinaryField128>();
342 tower.observe(element);
343 let drawn: BinaryField128 = tower.sample();
344
345 let mut ghash = mk::<Ghash128>();
346 ghash.observe(Ghash128::from_le_byte_iter(
347 element.into_bytes().into_iter(),
348 ));
349 let mirrored: Ghash128 = ghash.sample();
350
351 assert_eq!(
352 drawn.into_bytes().into_iter().collect::<Vec<_>>(),
353 mirrored.into_bytes().into_iter().collect::<Vec<_>>()
354 );
355 }
356
357 #[test]
358 fn sampling_is_deterministic_and_observation_dependent() {
359 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
361 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
362 assert_eq!(x, y);
363
364 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
366 a.observe(a128());
367 b.observe(a128());
368 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
369 assert_eq!(x, y);
370
371 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
373 a.observe(BinaryField128::ONE);
374 b.observe(BinaryField128::ZERO);
375 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
376 assert_ne!(x, y);
377
378 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
380 b.observe(BinaryField128::ZERO);
381 let (x, y): (BinaryField128, BinaryField128) = (a.sample(), b.sample());
382 assert_ne!(x, y);
383
384 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
387 let xs: [BinaryField128; 4] = a.sample_array();
388 let ys: [BinaryField128; 4] = b.sample_array();
389 assert_eq!(xs, ys);
390 assert_ne!(xs[0], xs[1]);
391 assert_ne!(xs[1], xs[2]);
392 assert_ne!(xs[2], xs[3]);
393 }
394
395 #[test]
396 fn observing_an_element_absorbs_its_little_endian_bytes() {
397 let a = a128();
398
399 let mut challenger = mk::<BinaryField128>();
400 challenger.observe(a);
401
402 let mut inner = mk_inner();
403 inner.observe_slice(&a.into_bytes().into_iter().collect::<Vec<_>>());
404
405 for _ in 0..32 {
407 let observed: u8 = challenger.inner.sample();
408 let expected: u8 = inner.sample();
409 assert_eq!(observed, expected);
410 }
411 }
412
413 #[test]
414 fn a_sampled_element_is_read_from_the_little_endian_byte_stream() {
415 let mut challenger = mk::<BinaryField128>();
416 let sampled: BinaryField128 = challenger.sample();
417
418 let mut inner = mk_inner();
419 let bytes: [u8; 16] = core::array::from_fn(|_| inner.sample());
420
421 assert_eq!(sampled, BinaryField128::from_le_bytes(bytes));
422 }
423
424 #[test]
425 fn a_sampled_element_of_a_narrow_level_reads_only_its_own_bytes() {
426 let mut challenger = mk::<BinaryField32>();
427 let sampled: BinaryField32 = challenger.sample();
428
429 let mut inner = mk_inner();
430 let bytes: [u8; 4] = core::array::from_fn(|_| inner.sample());
431
432 assert_eq!(sampled, BinaryField32::from_le_bytes(bytes));
433 }
434
435 #[test]
436 fn sampling_an_extension_element_reads_its_basis_coefficients_in_order() {
437 let mut challenger = mk::<BinaryField8>();
438 let sampled: BinaryField128 = challenger.sample();
439
440 let mut coefficients = mk::<BinaryField8>();
441 let coeffs: [BinaryField8; 16] = core::array::from_fn(|_| coefficients.sample());
442
443 assert_eq!(
444 <BinaryField128 as BasedVectorSpace<BinaryField8>>::from_basis_coefficients_fn(|i| {
445 coeffs[i]
446 }),
447 sampled
448 );
449 }
450
451 #[test]
452 fn observing_digests_matches_observing_their_bytes() {
453 let digest = [1_u8, 2, 3, 4];
454
455 let mut from_hash = mk::<BinaryField128>();
456 from_hash.observe(Hash::<BinaryField128, u8, 4>::from(digest));
457
458 let cap = MerkleCap::<BinaryField128, [u8; 4]>::new(vec![digest, [5, 6, 7, 8]]);
459 let mut from_cap_ref = mk::<BinaryField128>();
460 from_cap_ref.observe(&cap);
461 let mut from_cap = mk::<BinaryField128>();
462 from_cap.observe(cap);
463
464 let mut hash_bytes = mk_inner();
465 hash_bytes.observe_slice(&digest);
466 let mut cap_bytes = mk_inner();
467 cap_bytes.observe_slice(&[1, 2, 3, 4, 5, 6, 7, 8]);
468
469 for _ in 0..32 {
470 let expected: u8 = hash_bytes.sample();
471 assert_eq!(from_hash.inner.sample(), expected);
472
473 let expected: u8 = cap_bytes.sample();
474 assert_eq!(from_cap_ref.inner.sample(), expected);
475 assert_eq!(from_cap.inner.sample(), expected);
476 }
477 }
478
479 #[test]
480 fn observing_word_digests_matches_observing_their_little_endian_bytes() {
481 let digest = [0x0807_0605_0403_0201_u64, 0x100f_0e0d_0c0b_0a09];
482 let second = [0x1817_1615_1413_1211_u64, 0x201f_1e1d_1c1b_1a19];
483
484 let mut from_hash = mk::<BinaryField128>();
485 from_hash.observe(Hash::<BinaryField128, u64, 2>::from(digest));
486
487 let cap = MerkleCap::<BinaryField128, [u64; 2]>::new(vec![digest, second]);
488 let mut from_cap_ref = mk::<BinaryField128>();
489 from_cap_ref.observe(&cap);
490 let mut from_cap = mk::<BinaryField128>();
491 from_cap.observe(cap);
492
493 let mut hash_bytes = mk_inner();
494 hash_bytes.observe_slice(&core::array::from_fn::<u8, 16, _>(|i| i as u8 + 1));
495 let mut cap_bytes = mk_inner();
496 cap_bytes.observe_slice(&core::array::from_fn::<u8, 32, _>(|i| i as u8 + 1));
497
498 for _ in 0..32 {
499 let expected: u8 = hash_bytes.sample();
500 assert_eq!(from_hash.inner.sample(), expected);
501
502 let expected: u8 = cap_bytes.sample();
503 assert_eq!(from_cap_ref.inner.sample(), expected);
504 assert_eq!(from_cap.inner.sample(), expected);
505 }
506 }
507
508 #[test]
509 fn sampled_bits_fit_the_requested_width_and_are_reproducible() {
510 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
511 for bits in 0..32 {
512 let value = a.sample_bits(bits);
513 assert!(value < (1 << bits), "{value} does not fit in {bits} bits");
514 assert_eq!(value, b.sample_bits(bits));
515 }
516
517 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
519 a.observe(BinaryField128::ONE);
520 assert_ne!(a.sample_bits(31), b.sample_bits(31));
521 }
522
523 #[test]
524 fn uniform_bits_agree_with_plain_bits_and_never_reject() {
525 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
526 for bits in [0, 1, 7, 8, 16, 31] {
527 assert_eq!(
528 a.sample_uniform_bits::<true>(bits).unwrap(),
529 b.sample_bits(bits)
530 );
531 }
532
533 let (mut a, mut b) = (mk::<BinaryField128>(), mk::<BinaryField128>());
534 for bits in [0, 1, 7, 8, 16, 31] {
535 assert_eq!(
536 a.sample_uniform_bits::<false>(bits).unwrap(),
537 b.sample_bits(bits)
538 );
539 }
540 }
541
542 #[test]
545 fn sample_bits_is_not_limited_by_the_width_of_the_field() {
546 assert_eq!(<BinaryField8 as Field>::bits(), 8);
549 let mut challenger = mk::<BinaryField8>();
550 let sampled = challenger.sample_bits(24);
551 assert!(sampled < (1 << 24));
552
553 let mut inner = mk_inner();
554 let bytes: [u8; BITS_SAMPLE_BYTES] = core::array::from_fn(|_| inner.sample());
555 assert_eq!(sampled, (u64::from_le_bytes(bytes) & 0xff_ffff) as usize);
556
557 let mut challenger = mk::<BinaryField8>();
559 assert_eq!(challenger.sample_uniform_bits::<true>(24).unwrap(), sampled);
560 let mut challenger = mk::<BinaryField8>();
561 assert_eq!(
562 challenger.sample_uniform_bits::<false>(24).unwrap(),
563 sampled
564 );
565
566 let widest = usize::BITS as usize - 1;
568 let mut challenger = mk::<BinaryField8>();
569 assert!(challenger.sample_bits(widest) < (1 << widest));
570 }
571
572 #[test]
573 #[should_panic = "requested bit count must fit within a usize"]
574 fn sample_bits_rejects_a_request_wider_than_a_usize() {
575 let mut challenger = mk::<BinaryField128>();
576 let _ = challenger.sample_bits(usize::BITS as usize);
577 }
578
579 #[test]
580 #[should_panic = "requested bit count leaves too small a margin"]
581 fn grind_rejects_a_request_wider_than_the_field() {
582 let mut challenger = mk::<BinaryField32>();
583 let _ = challenger.grind(32);
584 }
585
586 #[test]
587 #[should_panic = "requested bit count leaves too small a margin"]
588 fn grind_rejects_a_request_inside_the_margin() {
589 let mut challenger = mk::<BinaryField32>();
591 let _ = challenger.grind(25);
592 }
593
594 #[derive(Clone)]
598 struct AlwaysZeroInner;
599
600 impl CanObserve<u8> for AlwaysZeroInner {
601 fn observe(&mut self, _value: u8) {}
602 }
603
604 impl CanSample<u8> for AlwaysZeroInner {
605 fn sample(&mut self) -> u8 {
606 0
607 }
608 }
609
610 #[test]
611 #[should_panic = "requested bit count leaves too small a margin"]
612 fn grind_rejects_a_request_the_u64_cap_no_longer_allows() {
613 let mut challenger = mk::<BinaryField128>();
618 let _ = challenger.grind(63);
619 }
620
621 #[test]
622 fn grind_accepts_the_widest_request_the_u64_cap_allows() {
623 let mut challenger: BinaryChallenger<BinaryField128, AlwaysZeroInner> =
629 BinaryChallenger::new(AlwaysZeroInner);
630 let bits = 56.min(usize::BITS as usize - 1);
631 let witness = challenger.grind(bits);
632 assert!(challenger.check_witness(bits, witness));
633 }
634
635 #[test]
636 fn a_bitstring_sample_reads_a_fixed_number_of_bytes() {
637 let mut challenger = mk::<BinaryField128>();
640 let sampled = challenger.sample_bits(31);
641
642 let mut inner = mk_inner();
643 let bytes: [u8; BITS_SAMPLE_BYTES] = core::array::from_fn(|_| inner.sample());
644
645 assert_eq!(BITS_SAMPLE_BYTES, 8);
646 assert_eq!(
647 sampled,
648 (u64::from_le_bytes(bytes) & ((1 << 31) - 1)) as usize
649 );
650
651 let next = challenger.sample_bits(8);
653 let bytes: [u8; BITS_SAMPLE_BYTES] = core::array::from_fn(|_| inner.sample());
654 assert_eq!(next, (u64::from_le_bytes(bytes) & 0xff) as usize);
655 }
656
657 #[test]
658 fn grind_satisfies_check() {
659 let mut challenger = mk::<BinaryField128>();
660 let witness = challenger.clone().grind(8);
661 assert!(challenger.check_witness(8, witness));
662 }
663
664 #[test]
665 fn grind_over_a_narrow_level_satisfies_check() {
666 let mut challenger = mk::<BinaryField32>();
667 let witness = challenger.clone().grind(8);
668 assert!(challenger.check_witness(8, witness));
669 }
670
671 #[test]
672 fn grind_of_zero_bits_is_free() {
673 let mut challenger = mk::<BinaryField128>();
674 let mut shadow = challenger.clone();
675
676 let witness = challenger.grind(0);
677 assert_eq!(witness, BinaryField128::ZERO);
678
679 for _ in 0..32 {
681 let expected: u8 = shadow.inner.sample();
682 assert_eq!(challenger.inner.sample(), expected);
683 }
684 }
685
686 #[test]
687 fn grind_of_zero_bits_is_free_on_a_level_narrower_than_the_margin() {
688 let mut challenger = mk::<Gf2>();
691 let mut shadow = challenger.clone();
692
693 let witness = challenger.grind(0);
694 assert_eq!(witness, Gf2::ZERO);
695
696 for _ in 0..32 {
698 let expected: u8 = shadow.inner.sample();
699 assert_eq!(challenger.inner.sample(), expected);
700 }
701 }
702
703 #[test]
704 fn a_wrong_witness_fails_the_check() {
705 let mut challenger = mk::<BinaryField128>();
706 let witness = challenger.clone().grind(8);
707
708 let mut wrong = challenger.clone();
711 assert!(!wrong.check_witness(8, witness + BinaryField128::ONE));
712 assert!(challenger.check_witness(8, witness));
713 }
714
715 #[test]
717 fn field_challenger_algebra_helpers_round_trip() {
718 let mut challenger = mk::<BinaryField8>();
719 challenger.observe_algebra_element(a128());
720 let sampled: BinaryField128 = challenger.sample_algebra_element();
721
722 let mut expected = mk::<BinaryField8>();
723 expected
724 .observe_slice(BasedVectorSpace::<BinaryField8>::as_basis_coefficients_slice(&a128()));
725 let expected: BinaryField128 = expected.sample();
726
727 assert_eq!(sampled, expected);
728 }
729}