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