subspace_erasure_coding/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(test)]
4mod tests;
5
6extern crate alloc;
7
8#[cfg(not(feature = "std"))]
9use alloc::string::String;
10use alloc::sync::Arc;
11#[cfg(not(feature = "std"))]
12use alloc::vec::Vec;
13use core::num::NonZeroUsize;
14use kzg::{FFTSettings, PolyRecover, DAS, FFTG1, G1};
15use rust_kzg_blst::types::fft_settings::FsFFTSettings;
16use rust_kzg_blst::types::g1::FsG1;
17use rust_kzg_blst::types::poly::FsPoly;
18use subspace_kzg::{Commitment, Polynomial, Scalar};
19
20#[derive(Debug, Clone)]
24pub struct ErasureCoding {
25 fft_settings: Arc<FsFFTSettings>,
26}
27
28impl ErasureCoding {
29 pub fn new(scale: NonZeroUsize) -> Result<Self, String> {
34 let fft_settings = Arc::new(FsFFTSettings::new(scale.get())?);
35
36 Ok(Self { fft_settings })
37 }
38
39 pub fn max_shards(&self) -> usize {
41 self.fft_settings.max_width
42 }
43
44 pub fn extend(&self, source: &[Scalar]) -> Result<Vec<Scalar>, String> {
48 self.fft_settings
51 .das_fft_extension(Scalar::slice_to_repr(source))
52 .map(Scalar::vec_from_repr)
53 }
54
55 pub fn recover(&self, shards: &[Option<Scalar>]) -> Result<Vec<Scalar>, String> {
60 let poly = FsPoly::recover_poly_from_samples(
61 Scalar::slice_option_to_repr(shards),
62 &self.fft_settings,
63 )?;
64
65 Ok(Scalar::vec_from_repr(poly.coeffs))
66 }
67
68 pub fn recover_poly(&self, shards: &[Option<Scalar>]) -> Result<Polynomial, String> {
74 let mut poly = Polynomial::from(FsPoly::recover_poly_coeffs_from_samples(
75 Scalar::slice_option_to_repr(shards),
76 &self.fft_settings,
77 )?);
78
79 poly.normalize();
80
81 Ok(poly)
82 }
83
84 pub fn recover_source(
89 &self,
90 shards: &[Option<Scalar>],
91 ) -> Result<impl ExactSizeIterator<Item = Scalar>, String> {
92 Ok(self.recover(shards)?.into_iter().step_by(2))
93 }
94
95 pub fn extend_commitments(
99 &self,
100 commitments: &[Commitment],
101 ) -> Result<Vec<Commitment>, String> {
102 let mut coeffs = self
104 .fft_settings
105 .fft_g1(Commitment::slice_to_repr(commitments), true)?;
106
107 coeffs.resize(coeffs.len() * 2, FsG1::identity());
109
110 self.fft_settings
112 .fft_g1(&coeffs, false)
113 .map(Commitment::vec_from_repr)
114 }
115}