1#![no_std]
3#![expect(incomplete_features, reason = "generic_const_*")]
4#![warn(rust_2018_idioms, missing_debug_implementations, missing_docs)]
5#![feature(
6 const_block_items,
7 const_convert,
8 const_trait_impl,
9 generic_const_args,
10 generic_const_items,
11 impl_restriction,
12 inherent_associated_types,
13 macroless_generic_const_args,
14 min_generic_const_args,
15 mut_restriction,
16 portable_simd,
17 step_trait
18)]
19#![cfg_attr(test, feature(float_erf))]
20#![cfg_attr(feature = "parallel", feature(exact_size_is_empty, sync_unsafe_cell))]
21#![cfg_attr(
22 feature = "alloc",
23 feature(iter_array_chunks, maybe_uninit_fill, ptr_as_uninit)
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#[cfg(feature = "alloc")]
43use core::hint;
44
45#[derive(Debug, Clone, Copy)]
47pub enum PosTableType {
48 Chia,
50 Shim,
52}
53
54#[derive(Debug)]
58#[cfg(feature = "alloc")]
59#[repr(C)]
60pub struct PosProofs {
61 pub mut(self) found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
69 pub mut(self) proofs: [PosProof; const { Record::NUM_CHUNKS }],
71}
72
73#[cfg(feature = "alloc")]
75impl PosProofs {
76 #[inline]
81 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
82 pub fn for_s_bucket(&self, s_bucket: SBucket) -> Option<PosProof> {
83 let proof_index = Self::proof_index_for_s_bucket(&self.found_proofs, s_bucket)?;
84
85 unsafe {
87 hint::assert_unchecked(proof_index < Record::NUM_CHUNKS);
88 }
89
90 Some(self.proofs[proof_index])
91 }
92
93 #[inline(always)]
94 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
95 fn proof_index_for_s_bucket(
96 found_proofs: &[u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
97 s_bucket: SBucket,
98 ) -> Option<usize> {
99 let bits_offset = usize::from(s_bucket);
100 let found_proofs_byte_offset = bits_offset / u8::BITS as usize;
101 let found_proofs_bit_offset = bits_offset as u32 % u8::BITS;
102 let (found_proofs_before, found_proofs_after) =
103 found_proofs.split_at(found_proofs_byte_offset);
104 if (found_proofs_after[0] & (1 << found_proofs_bit_offset)) == 0 {
105 return None;
106 }
107 let proof_index = found_proofs_before
108 .iter()
109 .map(|&bits| bits.count_ones())
110 .sum::<u32>()
111 + found_proofs_after[0]
112 .unbounded_shl(u8::BITS - found_proofs_bit_offset)
113 .count_ones();
114
115 Some(proof_index as usize)
116 }
117}
118
119#[cfg(feature = "alloc")]
124pub trait TableGenerator<T: Table>:
125 fmt::Debug + Default + Clone + Send + Sync + Sized + 'static
126{
127 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs>;
132
133 #[cfg(feature = "parallel")]
136 fn create_proofs_parallel(&self, seed: &PosSeed) -> Box<PosProofs> {
137 self.create_proofs(seed)
138 }
139}
140
141pub trait Table: SolutionPotVerifier + Sized + Send + Sync + 'static {
143 const TABLE_TYPE: PosTableType;
145 #[cfg(feature = "alloc")]
147 type Generator: TableGenerator<Self>;
148
149 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool;
151
152 #[cfg(feature = "alloc")]
154 fn generator() -> Self::Generator {
155 Self::Generator::default()
156 }
157}