1#![no_std]
3#![expect(incomplete_features, reason = "generic_const_exprs")]
4#![warn(rust_2018_idioms, missing_debug_implementations, missing_docs)]
5#![feature(
6 const_convert,
7 const_trait_impl,
8 exact_size_is_empty,
9 float_erf,
10 generic_const_exprs,
11 get_mut_unchecked,
12 iter_array_chunks,
13 maybe_uninit_fill,
14 portable_simd,
15 ptr_as_ref_unchecked,
16 ptr_as_uninit,
17 step_trait,
18 sync_unsafe_cell
19)]
20
21pub mod chia;
22pub mod chiapos;
23pub mod shim;
24
25#[cfg(feature = "alloc")]
26extern crate alloc;
27
28#[cfg(feature = "alloc")]
29use ab_core_primitives::pieces::Record;
30use ab_core_primitives::pos::{PosProof, PosSeed};
31use ab_core_primitives::sectors::SBucket;
32use ab_core_primitives::solutions::SolutionPotVerifier;
33#[cfg(feature = "alloc")]
34use alloc::boxed::Box;
35#[cfg(feature = "alloc")]
36use core::fmt;
37
38#[derive(Debug, Clone, Copy)]
40pub enum PosTableType {
41 Chia,
43 Shim,
45}
46
47#[derive(Debug)]
51#[cfg(feature = "alloc")]
52#[repr(C)]
53pub struct PosProofs {
54 pub found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
62 pub proofs: [PosProof; Record::NUM_CHUNKS],
64}
65
66#[cfg(feature = "alloc")]
68impl PosProofs {
69 #[inline]
74 pub fn for_s_bucket(&self, s_bucket: SBucket) -> Option<PosProof> {
75 let proof_index = Self::proof_index_for_s_bucket(self.found_proofs, s_bucket)?;
76
77 Some(self.proofs[proof_index])
78 }
79
80 #[inline(always)]
81 fn proof_index_for_s_bucket(
82 found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
83 s_bucket: SBucket,
84 ) -> Option<usize> {
85 let bits_offset = usize::from(s_bucket);
86 let found_proofs_byte_offset = bits_offset / u8::BITS as usize;
87 let found_proofs_bit_offset = bits_offset as u32 % u8::BITS;
88 let (found_proofs_before, found_proofs_after) =
89 found_proofs.split_at(found_proofs_byte_offset);
90 if (found_proofs_after[0] & (1 << found_proofs_bit_offset)) == 0 {
91 return None;
92 }
93 let proof_index = found_proofs_before
94 .iter()
95 .map(|&bits| bits.count_ones())
96 .sum::<u32>()
97 + found_proofs_after[0]
98 .unbounded_shl(u8::BITS - found_proofs_bit_offset)
99 .count_ones();
100
101 Some(proof_index as usize)
102 }
103}
104
105#[cfg(feature = "alloc")]
110pub trait TableGenerator<T: Table>:
111 fmt::Debug + Default + Clone + Send + Sync + Sized + 'static
112{
113 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs>;
118
119 #[cfg(feature = "parallel")]
122 fn create_proofs_parallel(&self, seed: &PosSeed) -> Box<PosProofs> {
123 self.create_proofs(seed)
124 }
125}
126
127pub trait Table: SolutionPotVerifier + Sized + Send + Sync + 'static {
129 const TABLE_TYPE: PosTableType;
131 #[cfg(feature = "alloc")]
133 type Generator: TableGenerator<Self>;
134
135 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool;
137
138 #[cfg(feature = "alloc")]
140 fn generator() -> Self::Generator {
141 Self::Generator::default()
142 }
143}