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 generic_const_exprs,
10 step_trait
11)]
12#![cfg_attr(test, feature(float_erf))]
13#![cfg_attr(feature = "parallel", feature(exact_size_is_empty, sync_unsafe_cell))]
14#![cfg_attr(
15 feature = "alloc",
16 feature(iter_array_chunks, maybe_uninit_fill, ptr_as_uninit)
17)]
18#![cfg_attr(any(feature = "alloc", test), feature(portable_simd))]
19
20pub mod chia;
21pub mod chiapos;
22pub mod shim;
23
24#[cfg(feature = "alloc")]
25extern crate alloc;
26
27#[cfg(feature = "alloc")]
28use ab_core_primitives::pieces::Record;
29use ab_core_primitives::pos::{PosProof, PosSeed};
30use ab_core_primitives::sectors::SBucket;
31use ab_core_primitives::solutions::SolutionPotVerifier;
32#[cfg(feature = "alloc")]
33use alloc::boxed::Box;
34#[cfg(feature = "alloc")]
35use core::fmt;
36
37#[derive(Debug, Clone, Copy)]
39pub enum PosTableType {
40 Chia,
42 Shim,
44}
45
46#[derive(Debug)]
50#[cfg(feature = "alloc")]
51#[repr(C)]
52pub struct PosProofs {
53 pub found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
61 pub proofs: [PosProof; Record::NUM_CHUNKS],
63}
64
65#[cfg(feature = "alloc")]
67impl PosProofs {
68 #[inline]
73 pub fn for_s_bucket(&self, s_bucket: SBucket) -> Option<PosProof> {
74 let proof_index = Self::proof_index_for_s_bucket(self.found_proofs, s_bucket)?;
75
76 Some(self.proofs[proof_index])
77 }
78
79 #[inline(always)]
80 fn proof_index_for_s_bucket(
81 found_proofs: [u8; Record::NUM_S_BUCKETS / u8::BITS as usize],
82 s_bucket: SBucket,
83 ) -> Option<usize> {
84 let bits_offset = usize::from(s_bucket);
85 let found_proofs_byte_offset = bits_offset / u8::BITS as usize;
86 let found_proofs_bit_offset = bits_offset as u32 % u8::BITS;
87 let (found_proofs_before, found_proofs_after) =
88 found_proofs.split_at(found_proofs_byte_offset);
89 if (found_proofs_after[0] & (1 << found_proofs_bit_offset)) == 0 {
90 return None;
91 }
92 let proof_index = found_proofs_before
93 .iter()
94 .map(|&bits| bits.count_ones())
95 .sum::<u32>()
96 + found_proofs_after[0]
97 .unbounded_shl(u8::BITS - found_proofs_bit_offset)
98 .count_ones();
99
100 Some(proof_index as usize)
101 }
102}
103
104#[cfg(feature = "alloc")]
109pub trait TableGenerator<T: Table>:
110 fmt::Debug + Default + Clone + Send + Sync + Sized + 'static
111{
112 fn create_proofs(&self, seed: &PosSeed) -> Box<PosProofs>;
117
118 #[cfg(feature = "parallel")]
121 fn create_proofs_parallel(&self, seed: &PosSeed) -> Box<PosProofs> {
122 self.create_proofs(seed)
123 }
124}
125
126pub trait Table: SolutionPotVerifier + Sized + Send + Sync + 'static {
128 const TABLE_TYPE: PosTableType;
130 #[cfg(feature = "alloc")]
132 type Generator: TableGenerator<Self>;
133
134 fn is_proof_valid(seed: &PosSeed, s_bucket: SBucket, proof: &PosProof) -> bool;
136
137 #[cfg(feature = "alloc")]
139 fn generator() -> Self::Generator {
140 Self::Generator::default()
141 }
142}