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_block_items,
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 portable_simd,
16 ptr_as_ref_unchecked,
17 ptr_as_uninit,
18 step_trait,
19 sync_unsafe_cell
20)]
21
22pub mod chia;
23pub mod chiapos;
24pub mod shim;
25
26#[cfg(feature = "alloc")]
27extern crate alloc;
28
29#[cfg(feature = "alloc")]
30use ab_core_primitives::pieces::Record;
31use ab_core_primitives::pos::{PosProof, PosSeed};
32use ab_core_primitives::sectors::SBucket;
33use ab_core_primitives::solutions::SolutionPotVerifier;
34#[cfg(feature = "alloc")]
35use alloc::boxed::Box;
36#[cfg(feature = "alloc")]
37use core::fmt;
38
39#[derive(Debug, Clone, Copy)]
41pub enum PosTableType {
42 Chia,
44 Shim,
46}
47
48#[derive(Debug)]
52#[cfg(feature = "alloc")]
53#[repr(C)]
54pub struct PosProofs {
55 pub found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
63 pub proofs: [PosProof; Record::NUM_CHUNKS],
65}
66
67#[cfg(feature = "alloc")]
69impl PosProofs {
70 #[inline]
75 pub fn for_s_bucket(&self, s_bucket: SBucket) -> Option<PosProof> {
76 let proof_index = Self::proof_index_for_s_bucket(self.found_proofs, s_bucket)?;
77
78 Some(self.proofs[proof_index])
79 }
80
81 #[inline(always)]
82 fn proof_index_for_s_bucket(
83 found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
84 s_bucket: SBucket,
85 ) -> Option<usize> {
86 let bits_offset = usize::from(s_bucket);
87 let found_proofs_byte_offset = bits_offset / u8::BITS as usize;
88 let found_proofs_bit_offset = bits_offset as u32 % u8::BITS;
89 let (found_proofs_before, found_proofs_after) =
90 found_proofs.split_at(found_proofs_byte_offset);
91 if (found_proofs_after[0] & (1 << found_proofs_bit_offset)) == 0 {
92 return None;
93 }
94 let proof_index = found_proofs_before
95 .iter()
96 .map(|&bits| bits.count_ones())
97 .sum::<u32>()
98 + found_proofs_after[0]
99 .unbounded_shl(u8::BITS - found_proofs_bit_offset)
100 .count_ones();
101
102 Some(proof_index as usize)
103 }
104}
105
106#[cfg(feature = "alloc")]
111pub trait TableGenerator<T: Table>:
112 fmt::Debug + Default + Clone + Send + Sync + Sized + 'static
113{
114 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs>;
119
120 #[cfg(feature = "parallel")]
123 fn create_proofs_parallel(&self, seed: &PosSeed) -> Box<PosProofs> {
124 self.create_proofs(seed)
125 }
126}
127
128pub trait Table: SolutionPotVerifier + Sized + Send + Sync + 'static {
130 const TABLE_TYPE: PosTableType;
132 #[cfg(feature = "alloc")]
134 type Generator: TableGenerator<Self>;
135
136 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool;
138
139 #[cfg(feature = "alloc")]
141 fn generator() -> Self::Generator {
142 Self::Generator::default()
143 }
144}