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 inherent_associated_types,
12 min_generic_const_args,
13 step_trait
14)]
15#![cfg_attr(test, feature(float_erf))]
16#![cfg_attr(feature = "parallel", feature(exact_size_is_empty, sync_unsafe_cell))]
17#![cfg_attr(
18 feature = "alloc",
19 feature(iter_array_chunks, maybe_uninit_fill, ptr_as_uninit)
20)]
21#![cfg_attr(any(feature = "alloc", test), feature(portable_simd))]
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
40#[derive(Debug, Clone, Copy)]
42pub enum PosTableType {
43 Chia,
45 Shim,
47}
48
49#[derive(Debug)]
53#[cfg(feature = "alloc")]
54#[repr(C)]
55pub struct PosProofs {
56 pub found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
64 pub proofs: [PosProof; const { Record::NUM_CHUNKS }],
66}
67
68#[cfg(feature = "alloc")]
70impl PosProofs {
71 #[inline]
76 pub fn for_s_bucket(&self, s_bucket: SBucket) -> Option<PosProof> {
77 let proof_index = Self::proof_index_for_s_bucket(&self.found_proofs, s_bucket)?;
78
79 Some(self.proofs[proof_index])
80 }
81
82 #[inline(always)]
83 fn proof_index_for_s_bucket(
84 found_proofs: &[u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
85 s_bucket: SBucket,
86 ) -> Option<usize> {
87 let bits_offset = usize::from(s_bucket);
88 let found_proofs_byte_offset = bits_offset / u8::BITS as usize;
89 let found_proofs_bit_offset = bits_offset as u32 % u8::BITS;
90 let (found_proofs_before, found_proofs_after) =
91 found_proofs.split_at(found_proofs_byte_offset);
92 if (found_proofs_after[0] & (1 << found_proofs_bit_offset)) == 0 {
93 return None;
94 }
95 let proof_index = found_proofs_before
96 .iter()
97 .map(|&bits| bits.count_ones())
98 .sum::<u32>()
99 + found_proofs_after[0]
100 .unbounded_shl(u8::BITS - found_proofs_bit_offset)
101 .count_ones();
102
103 Some(proof_index as usize)
104 }
105}
106
107#[cfg(feature = "alloc")]
112pub trait TableGenerator<T: Table>:
113 fmt::Debug + Default + Clone + Send + Sync + Sized + 'static
114{
115 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs>;
120
121 #[cfg(feature = "parallel")]
124 fn create_proofs_parallel(&self, seed: &PosSeed) -> Box<PosProofs> {
125 self.create_proofs(seed)
126 }
127}
128
129pub trait Table: SolutionPotVerifier + Sized + Send + Sync + 'static {
131 const TABLE_TYPE: PosTableType;
133 #[cfg(feature = "alloc")]
135 type Generator: TableGenerator<Self>;
136
137 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool;
139
140 #[cfg(feature = "alloc")]
142 fn generator() -> Self::Generator {
143 Self::Generator::default()
144 }
145}