ab_proof_of_space/
chia.rs

1//! Chia proof of space implementation
2#[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/// Proof of space table generator.
13///
14/// Chia implementation.
15#[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/// Proof of space table.
38///
39/// Chia implementation.
40#[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 mut challenge = [0; 32];
76        challenge[..size_of::<u32>()].copy_from_slice(&challenge_index.to_le_bytes());
77
78        self.tables
79            .find_proof(&challenge)
80            .next()
81            .map(PosProof::from)
82    }
83
84    fn is_proof_valid(seed: &PosSeed, challenge_index: u32, proof: &PosProof) -> bool {
85        <Self as ab_core_primitives::solutions::SolutionPotVerifier>::is_proof_valid(
86            seed,
87            challenge_index,
88            proof,
89        )
90    }
91}
92
93#[cfg(all(feature = "alloc", test))]
94#[cfg(not(miri))]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn basic() {
100        let seed = PosSeed::from([
101            35, 2, 52, 4, 51, 55, 23, 84, 91, 10, 111, 12, 13, 222, 151, 16, 228, 211, 254, 45, 92,
102            198, 204, 10, 9, 10, 11, 129, 139, 171, 15, 23,
103        ]);
104
105        let table = ChiaTable::generate(&seed);
106        let table_parallel = ChiaTable::generate_parallel(&seed);
107
108        assert!(table.find_proof(1232460437).is_none());
109        assert!(table_parallel.find_proof(1232460437).is_none());
110
111        {
112            let challenge_index = 600426542;
113            let proof = table.find_proof(challenge_index).unwrap();
114            assert_eq!(proof, table_parallel.find_proof(challenge_index).unwrap());
115            assert!(ChiaTable::is_proof_valid(&seed, challenge_index, &proof));
116        }
117    }
118}