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 gca_const_items,
10 gca_macroless_args,
11 gca_min_const_items,
12 generic_const_items,
13 impl_restriction,
14 inherent_associated_types,
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(feature = "alloc", feature(maybe_uninit_fill, ptr_as_uninit))]
22
23pub mod chia;
24pub mod chiapos;
25pub mod shim;
26
27#[cfg(feature = "alloc")]
28extern crate alloc;
29
30#[cfg(feature = "alloc")]
31use ab_core_primitives::pieces::Record;
32use ab_core_primitives::pos::{PosProof, PosSeed};
33use ab_core_primitives::sectors::SBucket;
34use ab_core_primitives::solutions::SolutionPotVerifier;
35#[cfg(feature = "alloc")]
36use alloc::boxed::Box;
37#[cfg(feature = "alloc")]
38use core::fmt;
39#[cfg(feature = "alloc")]
40use core::hint;
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 mut(self) found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
68 pub mut(self) proofs: [PosProof; const { Record::NUM_CHUNKS }],
70}
71
72#[cfg(feature = "alloc")]
74impl PosProofs {
75 #[inline]
80 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
81 pub fn for_s_bucket(&self, s_bucket: SBucket) -> Option<PosProof> {
82 let proof_index = Self::proof_index_for_s_bucket(&self.found_proofs, s_bucket)?;
83
84 unsafe {
86 hint::assert_unchecked(proof_index < Record::NUM_CHUNKS);
87 }
88
89 Some(self.proofs[proof_index])
90 }
91
92 #[inline(always)]
93 #[cfg_attr(feature = "no-panic", no_panic::no_panic)]
94 fn proof_index_for_s_bucket(
95 found_proofs: &[u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
96 s_bucket: SBucket,
97 ) -> Option<usize> {
98 let bits_offset = usize::from(s_bucket);
99 let found_proofs_byte_offset = bits_offset / u8::BITS as usize;
100 let found_proofs_bit_offset = bits_offset as u32 % u8::BITS;
101 let (found_proofs_before, found_proofs_after) =
102 found_proofs.split_at(found_proofs_byte_offset);
103 if (found_proofs_after[0] & (1 << found_proofs_bit_offset)) == 0 {
104 return None;
105 }
106 let proof_index = found_proofs_before
107 .iter()
108 .map(|&bits| bits.count_ones())
109 .sum::<u32>()
110 + found_proofs_after[0]
111 .unbounded_shl(u8::BITS - found_proofs_bit_offset)
112 .count_ones();
113
114 Some(proof_index as usize)
115 }
116}
117
118#[cfg(feature = "alloc")]
123pub trait TableGenerator<T: Table>:
124 fmt::Debug + Default + Clone + Send + Sync + Sized + 'static
125{
126 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs>;
131
132 #[cfg(feature = "parallel")]
135 fn create_proofs_parallel(&self, seed: &PosSeed) -> Box<PosProofs> {
136 self.create_proofs(seed)
137 }
138}
139
140pub trait Table: SolutionPotVerifier + Sized + Send + Sync + 'static {
142 const TABLE_TYPE: PosTableType;
144 #[cfg(feature = "alloc")]
146 type Generator: TableGenerator<Self>;
147
148 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool;
150
151 #[cfg(feature = "alloc")]
153 fn generator() -> Self::Generator {
154 Self::Generator::default()
155 }
156}