subspace_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 subspace_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,
19}
20
21#[cfg(feature = "alloc")]
22impl TableGenerator<ChiaTable> for ChiaTableGenerator {
23    fn generate(&self, seed: &PosSeed) -> ChiaTable {
24        ChiaTable {
25            tables: Tables::<K>::create((*seed).into(), &self.tables_cache),
26        }
27    }
28
29    #[cfg(feature = "parallel")]
30    fn generate_parallel(&self, seed: &PosSeed) -> ChiaTable {
31        ChiaTable {
32            tables: Tables::<K>::create_parallel((*seed).into(), &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 subspace_core_primitives::solutions::SolutionPotVerifier for ChiaTable {
47    fn is_proof_valid(seed: &PosSeed, challenge_index: u32, proof: &PosProof) -> bool {
48        Tables::<K>::verify_only(seed, challenge_index.to_le_bytes(), proof)
49    }
50}
51
52impl Table for ChiaTable {
53    const TABLE_TYPE: PosTableType = PosTableType::Chia;
54    #[cfg(feature = "alloc")]
55    type Generator = ChiaTableGenerator;
56
57    #[cfg(feature = "alloc")]
58    fn find_proof(&self, challenge_index: u32) -> Option<PosProof> {
59        let first_challenge_bytes = challenge_index.to_le_bytes();
60
61        self.tables
62            .find_proof(first_challenge_bytes)
63            .next()
64            .map(PosProof::from)
65    }
66
67    fn is_proof_valid(seed: &PosSeed, challenge_index: u32, proof: &PosProof) -> bool {
68        <Self as subspace_core_primitives::solutions::SolutionPotVerifier>::is_proof_valid(
69            seed,
70            challenge_index,
71            proof,
72        )
73    }
74}
75
76#[cfg(all(feature = "alloc", test))]
77#[cfg(not(miri))]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn basic() {
83        let seed = PosSeed::from([
84            35, 2, 52, 4, 51, 55, 23, 84, 91, 10, 111, 12, 13, 222, 151, 16, 228, 211, 254, 45, 92,
85            198, 204, 10, 9, 10, 11, 129, 139, 171, 15, 23,
86        ]);
87
88        let generator = ChiaTableGenerator::default();
89        let table = generator.generate(&seed);
90        #[cfg(feature = "parallel")]
91        let table_parallel = generator.generate_parallel(&seed);
92
93        assert!(table.find_proof(1232460437).is_none());
94        #[cfg(feature = "parallel")]
95        assert!(table_parallel.find_proof(1232460437).is_none());
96
97        {
98            let challenge_index = 600426542;
99            let proof = table.find_proof(challenge_index).unwrap();
100            #[cfg(feature = "parallel")]
101            assert_eq!(proof, table_parallel.find_proof(challenge_index).unwrap());
102            assert!(ChiaTable::is_proof_valid(&seed, challenge_index, &proof));
103        }
104    }
105}