p3_challenger/
grinding_challenger.rs

1use p3_field::{Field, PrimeField, PrimeField32, PrimeField64};
2use p3_maybe_rayon::prelude::*;
3use p3_symmetric::CryptographicPermutation;
4use tracing::instrument;
5
6use crate::{CanObserve, CanSampleBits, DuplexChallenger, MultiField32Challenger};
7
8pub trait GrindingChallenger:
9    CanObserve<Self::Witness> + CanSampleBits<usize> + Sync + Clone
10{
11    type Witness: Field;
12
13    fn grind(&mut self, bits: usize) -> Self::Witness;
14
15    #[must_use]
16    fn check_witness(&mut self, bits: usize, witness: Self::Witness) -> bool {
17        self.observe(witness);
18        self.sample_bits(bits) == 0
19    }
20}
21
22impl<F, P, const WIDTH: usize, const RATE: usize> GrindingChallenger
23    for DuplexChallenger<F, P, WIDTH, RATE>
24where
25    F: PrimeField64,
26    P: CryptographicPermutation<[F; WIDTH]>,
27{
28    type Witness = F;
29
30    #[instrument(name = "grind for proof-of-work witness", skip_all)]
31    fn grind(&mut self, bits: usize) -> Self::Witness {
32        assert!(bits < (usize::BITS as usize));
33        assert!((1 << bits) < F::ORDER_U64);
34
35        let witness = (0..F::ORDER_U64)
36            .into_par_iter()
37            .map(|i| F::from_canonical_u64(i))
38            .find_any(|witness| self.clone().check_witness(bits, *witness))
39            .expect("failed to find witness");
40        assert!(self.check_witness(bits, witness));
41        witness
42    }
43}
44
45impl<F, PF, P, const WIDTH: usize, const RATE: usize> GrindingChallenger
46    for MultiField32Challenger<F, PF, P, WIDTH, RATE>
47where
48    F: PrimeField32,
49    PF: PrimeField,
50    P: CryptographicPermutation<[PF; WIDTH]>,
51{
52    type Witness = F;
53
54    #[instrument(name = "grind for proof-of-work witness", skip_all)]
55    fn grind(&mut self, bits: usize) -> Self::Witness {
56        assert!(bits < (usize::BITS as usize));
57        assert!((1 << bits) < F::ORDER_U64);
58        let witness = (0..F::ORDER_U64)
59            .into_par_iter()
60            .map(F::from_canonical_u64)
61            .find_any(|witness| self.clone().check_witness(bits, *witness))
62            .expect("failed to find witness");
63        assert!(self.check_witness(bits, witness));
64        witness
65    }
66}