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 portable_simd,
18 ptr_as_ref_unchecked,
19 ptr_as_uninit,
20 step_trait,
21 sync_unsafe_cell,
22 vec_into_raw_parts
23)]
24
25pub mod chia;
26pub mod chiapos;
27pub mod shim;
28
29#[cfg(feature = "alloc")]
30extern crate alloc;
31
32#[cfg(feature = "alloc")]
33use ab_core_primitives::pieces::Record;
34use ab_core_primitives::pos::{PosProof, PosSeed};
35use ab_core_primitives::sectors::SBucket;
36use ab_core_primitives::solutions::SolutionPotVerifier;
37#[cfg(feature = "alloc")]
38use alloc::boxed::Box;
39#[cfg(feature = "alloc")]
40use core::fmt;
41
42#[derive(Debug, Clone, Copy)]
44pub enum PosTableType {
45 Chia,
47 Shim,
49}
50
51#[derive(Debug)]
55#[cfg(feature = "alloc")]
56#[repr(C)]
57pub struct PosProofs {
58 pub found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
66 pub proofs: [PosProof; Record::NUM_CHUNKS],
68}
69
70#[cfg(feature = "alloc")]
72impl PosProofs {
73 #[inline]
78 pub fn for_s_bucket(&self, s_bucket: SBucket) -> Option<PosProof> {
79 let proof_index = Self::proof_index_for_s_bucket(self.found_proofs, s_bucket)?;
80
81 Some(self.proofs[proof_index])
82 }
83
84 #[inline(always)]
85 fn proof_index_for_s_bucket(
86 found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
87 s_bucket: SBucket,
88 ) -> Option<usize> {
89 let bits_offset = usize::from(s_bucket);
90 let found_proofs_byte_offset = bits_offset / u8::BITS as usize;
91 let found_proofs_bit_offset = bits_offset as u32 % u8::BITS;
92 let (found_proofs_before, found_proofs_after) =
93 found_proofs.split_at(found_proofs_byte_offset);
94 if (found_proofs_after[0] & (1 << found_proofs_bit_offset)) == 0 {
95 return None;
96 }
97 let proof_index = found_proofs_before
98 .iter()
99 .map(|&bits| bits.count_ones())
100 .sum::<u32>()
101 + found_proofs_after[0]
102 .unbounded_shl(u8::BITS - found_proofs_bit_offset)
103 .count_ones();
104
105 Some(proof_index as usize)
106 }
107}
108
109#[cfg(feature = "alloc")]
114pub trait TableGenerator<T: Table>:
115 fmt::Debug + Default + Clone + Send + Sync + Sized + 'static
116{
117 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs>;
122
123 #[cfg(feature = "parallel")]
126 fn create_proofs_parallel(&self, seed: &PosSeed) -> Box<PosProofs> {
127 self.create_proofs(seed)
128 }
129}
130
131pub trait Table: SolutionPotVerifier + Sized + Send + Sync + 'static {
133 const TABLE_TYPE: PosTableType;
135 #[cfg(feature = "alloc")]
137 type Generator: TableGenerator<Self>;
138
139 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool;
141
142 #[cfg(feature = "alloc")]
144 fn generator() -> Self::Generator {
145 Self::Generator::default()
146 }
147}