ab_proof_of_space/
shim.rs1#[cfg(feature = "alloc")]
5use crate::TableGenerator;
6use crate::{PosTableType, Table};
7use ab_core_primitives::pos::{PosProof, PosSeed};
8use core::iter;
9
10#[derive(Debug, Default, Clone)]
14#[cfg(feature = "alloc")]
15pub struct ShimTableGenerator;
16
17#[cfg(feature = "alloc")]
18impl TableGenerator<ShimTable> for ShimTableGenerator {
19 fn generate(&mut self, seed: &PosSeed) -> ShimTable {
20 ShimTable::generate(seed)
21 }
22}
23
24#[derive(Debug)]
28pub struct ShimTable {
29 #[cfg(feature = "alloc")]
30 seed: PosSeed,
31}
32
33impl ab_core_primitives::solutions::SolutionPotVerifier for ShimTable {
34 fn is_proof_valid(seed: &PosSeed, challenge_index: u32, proof: &PosProof) -> bool {
35 let Some(correct_proof) = find_proof(seed, challenge_index) else {
36 return false;
37 };
38
39 &correct_proof == proof
40 }
41}
42
43impl Table for ShimTable {
44 const TABLE_TYPE: PosTableType = PosTableType::Shim;
45 #[cfg(feature = "alloc")]
46 type Generator = ShimTableGenerator;
47
48 #[cfg(feature = "alloc")]
49 fn generate(seed: &PosSeed) -> ShimTable {
50 Self { seed: *seed }
51 }
52
53 #[cfg(feature = "alloc")]
54 fn find_proof(&self, challenge_index: u32) -> Option<PosProof> {
55 find_proof(&self.seed, challenge_index)
56 }
57
58 fn is_proof_valid(seed: &PosSeed, challenge_index: u32, proof: &PosProof) -> bool {
59 <Self as ab_core_primitives::solutions::SolutionPotVerifier>::is_proof_valid(
60 seed,
61 challenge_index,
62 proof,
63 )
64 }
65}
66
67fn find_proof(seed: &PosSeed, challenge_index: u32) -> Option<PosProof> {
68 let quality = ab_blake3::single_block_hash(&challenge_index.to_le_bytes())
69 .expect("Less than a single block worth of bytes; qed");
70 if quality[0] % 3 > 0 {
71 let mut proof = PosProof::default();
72 proof
73 .iter_mut()
74 .zip(seed.iter().chain(iter::repeat(quality.iter()).flatten()))
75 .for_each(|(output, input)| {
76 *output = *input;
77 });
78
79 Some(proof)
80 } else {
81 None
82 }
83}
84
85#[cfg(all(feature = "alloc", test))]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn basic() {
91 let seed = PosSeed::from([
92 35, 2, 52, 4, 51, 55, 23, 84, 91, 10, 111, 12, 13, 222, 151, 16, 228, 211, 254, 45, 92,
93 198, 204, 10, 9, 10, 11, 129, 139, 171, 15, 23,
94 ]);
95
96 let table = ShimTable::generate(&seed);
97
98 assert!(table.find_proof(1).is_none());
99
100 {
101 let challenge_index = 0;
102 let proof = table.find_proof(challenge_index).unwrap();
103 assert!(ShimTable::is_proof_valid(&seed, challenge_index, &proof));
104 }
105 }
106}