ab_proof_of_space/
chia.rs1#[cfg(feature = "alloc")]
3use crate::TableGenerator;
4use crate::chiapos::Tables;
5#[cfg(feature = "alloc")]
6use crate::chiapos::TablesCache;
7use crate::{PosTableType, Table};
8use ab_core_primitives::pos::{PosProof, PosSeed};
9
10const K: u8 = PosProof::K;
11
12#[derive(Debug, Default, Clone)]
16#[cfg(feature = "alloc")]
17pub struct ChiaTableGenerator {
18 tables_cache: TablesCache<K>,
19}
20
21#[cfg(feature = "alloc")]
22impl TableGenerator<ChiaTable> for ChiaTableGenerator {
23 fn generate(&mut self, seed: &PosSeed) -> ChiaTable {
24 ChiaTable {
25 tables: Tables::<K>::create((*seed).into(), &mut self.tables_cache),
26 }
27 }
28
29 #[cfg(any(feature = "parallel", test))]
30 fn generate_parallel(&mut self, seed: &PosSeed) -> ChiaTable {
31 ChiaTable {
32 tables: Tables::<K>::create_parallel((*seed).into(), &mut self.tables_cache),
33 }
34 }
35}
36
37#[derive(Debug)]
41pub struct ChiaTable {
42 #[cfg(feature = "alloc")]
43 tables: Tables<K>,
44}
45
46impl ab_core_primitives::solutions::SolutionPotVerifier for ChiaTable {
47 fn is_proof_valid(seed: &PosSeed, challenge_index: u32, proof: &PosProof) -> bool {
48 let mut challenge = [0; 32];
49 challenge[..size_of::<u32>()].copy_from_slice(&challenge_index.to_le_bytes());
50 Tables::<K>::verify(seed, &challenge, proof).is_some()
51 }
52}
53
54impl Table for ChiaTable {
55 const TABLE_TYPE: PosTableType = PosTableType::Chia;
56 #[cfg(feature = "alloc")]
57 type Generator = ChiaTableGenerator;
58
59 #[cfg(feature = "alloc")]
60 fn generate(seed: &PosSeed) -> ChiaTable {
61 Self {
62 tables: Tables::<K>::create_simple((*seed).into()),
63 }
64 }
65
66 #[cfg(all(feature = "alloc", any(feature = "parallel", test)))]
67 fn generate_parallel(seed: &PosSeed) -> ChiaTable {
68 Self {
69 tables: Tables::<K>::create_parallel((*seed).into(), &mut TablesCache::default()),
70 }
71 }
72
73 #[cfg(feature = "alloc")]
74 fn find_proof(&self, challenge_index: u32) -> Option<PosProof> {
75 let first_challenge_bytes = challenge_index.to_le_bytes();
76
77 self.tables
78 .find_proof(first_challenge_bytes)
79 .next()
80 .map(PosProof::from)
81 }
82
83 fn is_proof_valid(seed: &PosSeed, challenge_index: u32, proof: &PosProof) -> bool {
84 <Self as ab_core_primitives::solutions::SolutionPotVerifier>::is_proof_valid(
85 seed,
86 challenge_index,
87 proof,
88 )
89 }
90}
91
92#[cfg(all(feature = "alloc", test))]
93#[cfg(not(miri))]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn basic() {
99 let seed = PosSeed::from([
100 35, 2, 52, 4, 51, 55, 23, 84, 91, 10, 111, 12, 13, 222, 151, 16, 228, 211, 254, 45, 92,
101 198, 204, 10, 9, 10, 11, 129, 139, 171, 15, 23,
102 ]);
103
104 let table = ChiaTable::generate(&seed);
105 let table_parallel = ChiaTable::generate_parallel(&seed);
106
107 assert!(table.find_proof(1232460437).is_none());
108 assert!(table_parallel.find_proof(1232460437).is_none());
109
110 {
111 let challenge_index = 600426542;
112 let proof = table.find_proof(challenge_index).unwrap();
113 assert_eq!(proof, table_parallel.find_proof(challenge_index).unwrap());
114 assert!(ChiaTable::is_proof_valid(&seed, challenge_index, &proof));
115 }
116 }
117}