ab_proof_of_space/
shim.rs1#[cfg(all(feature = "alloc", test, not(miri)))]
5mod tests;
6
7#[cfg(feature = "alloc")]
8use crate::PosProofs;
9#[cfg(feature = "alloc")]
10use crate::TableGenerator;
11use crate::{PosTableType, Table};
12#[cfg(feature = "alloc")]
13use ab_core_primitives::pieces::Record;
14use ab_core_primitives::pos::{PosProof, PosSeed};
15use ab_core_primitives::sectors::SBucket;
16#[cfg(feature = "alloc")]
17use alloc::boxed::Box;
18use core::iter;
19
20#[derive(Debug, Default, Clone)]
24#[cfg(feature = "alloc")]
25pub struct ShimTableGenerator;
26
27#[cfg(feature = "alloc")]
28impl TableGenerator<ShimTable> for ShimTableGenerator {
29 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs> {
30 let mut proofs = unsafe { Box::<PosProofs>::new_zeroed().assume_init() };
32
33 let mut num_found_proofs = 0_usize;
34 'outer: for (s_buckets, found_proofs) in (0..Record::NUM_S_BUCKETS as u32)
35 .array_chunks::<{ u8::BITS as usize }>()
36 .zip(&mut proofs.found_proofs)
37 {
38 for (proof_offset, s_bucket) in s_buckets.into_iter().enumerate() {
39 if let Some(proof) = find_proof(seed, s_bucket) {
40 *found_proofs |= 1 << proof_offset;
41
42 proofs.proofs[num_found_proofs] = proof;
43 num_found_proofs += 1;
44
45 if num_found_proofs == Record::NUM_CHUNKS {
46 break 'outer;
47 }
48 }
49 }
50 }
51
52 proofs
53 }
54}
55
56#[derive(Debug)]
60pub struct ShimTable;
61
62impl ab_core_primitives::solutions::SolutionPotVerifier for ShimTable {
63 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool {
64 let Some(correct_proof) = find_proof(seed, u32::from(s_bucket)) else {
65 return false;
66 };
67
68 &correct_proof == proof
69 }
70}
71
72impl Table for ShimTable {
73 const TABLE_TYPE: PosTableType = PosTableType::Shim;
74 #[cfg(feature = "alloc")]
75 type Generator = ShimTableGenerator;
76
77 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool {
78 <Self as ab_core_primitives::solutions::SolutionPotVerifier>::is_proof_valid(
79 seed, s_bucket, proof,
80 )
81 }
82}
83
84fn find_proof(seed: &PosSeed, challenge_index: u32) -> Option<PosProof> {
85 let quality = ab_blake3::single_block_hash(&challenge_index.to_le_bytes())
86 .expect("Less than a single block worth of bytes; qed");
87 if quality[0].is_multiple_of(3) {
88 None
89 } else {
90 let mut proof = PosProof::default();
91 proof
92 .iter_mut()
93 .zip(seed.iter().chain(iter::repeat(quality.iter()).flatten()))
94 .for_each(|(output, input)| {
95 *output = *input;
96 });
97
98 Some(proof)
99 }
100}