Skip to main content

subspace_kzg/
lib.rs

1//! KZG primitives for Subspace Network
2
3#[cfg(test)]
4mod tests;
5
6extern crate alloc;
7
8use alloc::collections::BTreeMap;
9use alloc::collections::btree_map::Entry;
10#[cfg(not(feature = "std"))]
11use alloc::string::{String, ToString};
12use alloc::sync::Arc;
13#[cfg(not(feature = "std"))]
14use alloc::vec::Vec;
15use core::mem;
16use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into};
17use kzg::eip_4844::{BYTES_PER_G1, BYTES_PER_G2};
18use kzg::{FFTFr, FFTSettings, Fr, G1, G2, KZGSettings};
19#[cfg(feature = "std")]
20use parking_lot::Mutex;
21use rust_kzg_blst::types::fft_settings::FsFFTSettings;
22use rust_kzg_blst::types::fr::FsFr;
23use rust_kzg_blst::types::g1::FsG1;
24use rust_kzg_blst::types::g2::FsG2;
25use rust_kzg_blst::types::kzg_settings::FsKZGSettings;
26use rust_kzg_blst::types::poly::FsPoly;
27#[cfg(not(feature = "std"))]
28use spin::Mutex;
29use static_assertions::const_assert_eq;
30use subspace_core_primitives::ScalarBytes;
31use subspace_core_primitives::pieces::{RecordCommitment, RecordWitness};
32use subspace_core_primitives::segments::SegmentCommitment;
33use subspace_core_primitives::solutions::ChunkWitness;
34use tracing::debug;
35
36/// Embedded KZG settings as bytes, too big for `no_std` in most cases
37/// Generated using following command (using current Ethereum KZG Summoning Ceremony):
38/// ```bash
39/// curl -s https://seq.ceremony.ethereum.org/info/current_state | jq '.transcripts[3].powersOfTau' | jq -r '.G1Powers + .G2Powers | map(.[2:]) | join("")' | xxd -r -p - eth-public-parameters.bin
40/// ```
41pub const EMBEDDED_KZG_SETTINGS_BYTES: &[u8] = include_bytes!("eth-public-parameters.bin");
42/// Number of G1 powers stored in [`EMBEDDED_KZG_SETTINGS_BYTES`]
43pub const NUM_G1_POWERS: usize = 32_768;
44/// Number of G2 powers stored in [`EMBEDDED_KZG_SETTINGS_BYTES`]
45pub const NUM_G2_POWERS: usize = 65;
46
47// Symmetric function is present in tests
48/// Function turns bytes into `FsKZGSettings`, it is up to the user to ensure that bytes make sense,
49/// otherwise result can be very wrong (but will not panic).
50fn bytes_to_kzg_settings(
51    bytes: &[u8],
52    num_g1_powers: usize,
53    num_g2_powers: usize,
54) -> Result<FsKZGSettings, String> {
55    if bytes.len() != BYTES_PER_G1 * num_g1_powers + BYTES_PER_G2 * num_g2_powers {
56        return Err("Invalid bytes length".to_string());
57    }
58
59    let (secret_g1_bytes, secret_g2_bytes) = bytes.split_at(BYTES_PER_G1 * num_g1_powers);
60    let secret_g1 = secret_g1_bytes
61        .as_chunks::<BYTES_PER_G1>()
62        .0
63        .iter()
64        .map(|bytes| FsG1::from_bytes(bytes))
65        .collect::<Result<Vec<_>, _>>()?;
66    let secret_g2 = secret_g2_bytes
67        .as_chunks::<BYTES_PER_G2>()
68        .0
69        .iter()
70        .map(|bytes| FsG2::from_bytes(bytes))
71        .collect::<Result<Vec<_>, _>>()?;
72
73    let fft_settings = FsFFTSettings::new(
74        num_g1_powers
75            .checked_sub(1)
76            .expect("Checked to be not empty above; qed")
77            .ilog2() as usize,
78    )
79    .expect("Scale is within allowed bounds; qed");
80
81    // Below is the same as `FsKZGSettings::new(&s1, &s2, num_g1_powers, &fft_settings)`, but without
82    // extra checks (parameters are static anyway) and without unnecessary allocations
83    // TODO: Switch to `::new()` constructor once
84    //  https://github.com/grandinetech/rust-kzg/issues/264 is resolved
85    Ok(FsKZGSettings {
86        fs: fft_settings,
87        secret_g1,
88        secret_g2,
89        precomputation: None,
90    })
91}
92
93/// Commitment to polynomial
94#[derive(Debug, Clone, From)]
95pub struct Polynomial(FsPoly);
96
97impl Polynomial {
98    /// Normalize polynomial by removing trailing zeroes
99    pub fn normalize(&mut self) {
100        let trailing_zeroes = self
101            .0
102            .coeffs
103            .iter()
104            .rev()
105            .take_while(|coeff| coeff.is_zero())
106            .count();
107        self.0
108            .coeffs
109            .truncate((self.0.coeffs.len() - trailing_zeroes).max(1));
110    }
111}
112
113/// Representation of a single BLS12-381 scalar value.
114#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Deref, DerefMut)]
115#[repr(transparent)]
116pub struct Scalar(FsFr);
117
118const_assert_eq!(
119    mem::size_of::<Option<Scalar>>(),
120    mem::size_of::<Option<FsFr>>()
121);
122const_assert_eq!(
123    mem::align_of::<Option<Scalar>>(),
124    mem::align_of::<Option<FsFr>>()
125);
126
127impl From<&[u8; ScalarBytes::SAFE_BYTES]> for Scalar {
128    #[inline]
129    fn from(value: &[u8; ScalarBytes::SAFE_BYTES]) -> Self {
130        let mut bytes = [0u8; ScalarBytes::FULL_BYTES];
131        bytes[1..].copy_from_slice(value);
132        Self::try_from(bytes).expect("Safe bytes always fit into scalar and thus succeed; qed")
133    }
134}
135
136impl From<[u8; ScalarBytes::SAFE_BYTES]> for Scalar {
137    #[inline]
138    fn from(value: [u8; ScalarBytes::SAFE_BYTES]) -> Self {
139        Self::from(&value)
140    }
141}
142
143impl TryFrom<&[u8; ScalarBytes::FULL_BYTES]> for Scalar {
144    type Error = String;
145
146    #[inline]
147    fn try_from(value: &[u8; ScalarBytes::FULL_BYTES]) -> Result<Self, Self::Error> {
148        Self::try_from(*value)
149    }
150}
151
152impl TryFrom<[u8; ScalarBytes::FULL_BYTES]> for Scalar {
153    type Error = String;
154
155    #[inline]
156    fn try_from(value: [u8; ScalarBytes::FULL_BYTES]) -> Result<Self, Self::Error> {
157        FsFr::from_bytes(&value).map(Scalar)
158    }
159}
160
161impl TryFrom<&ScalarBytes> for Scalar {
162    type Error = String;
163
164    #[inline]
165    fn try_from(value: &ScalarBytes) -> Result<Self, Self::Error> {
166        FsFr::from_bytes(value.as_ref()).map(Scalar)
167    }
168}
169
170impl TryFrom<ScalarBytes> for Scalar {
171    type Error = String;
172
173    #[inline]
174    fn try_from(value: ScalarBytes) -> Result<Self, Self::Error> {
175        Self::try_from(&value)
176    }
177}
178
179impl From<&Scalar> for [u8; ScalarBytes::FULL_BYTES] {
180    #[inline]
181    fn from(value: &Scalar) -> Self {
182        value.0.to_bytes()
183    }
184}
185
186impl From<Scalar> for [u8; ScalarBytes::FULL_BYTES] {
187    #[inline]
188    fn from(value: Scalar) -> Self {
189        Self::from(&value)
190    }
191}
192
193impl From<&Scalar> for ScalarBytes {
194    #[inline]
195    fn from(value: &Scalar) -> Self {
196        ScalarBytes::from(value.0.to_bytes())
197    }
198}
199
200impl From<Scalar> for ScalarBytes {
201    #[inline]
202    fn from(value: Scalar) -> Self {
203        Self::from(&value)
204    }
205}
206
207impl Scalar {
208    /// Convert scalar into bytes
209    pub fn to_bytes(&self) -> [u8; ScalarBytes::FULL_BYTES] {
210        self.into()
211    }
212
213    /// Convert scalar into safe bytes, returns `None` if not possible to convert due to larger
214    /// internal value
215    pub fn try_to_safe_bytes(&self) -> Option<[u8; ScalarBytes::SAFE_BYTES]> {
216        let bytes = self.to_bytes();
217        if bytes[0] == 0 {
218            Some(bytes[1..].try_into().expect("Correct length; qed"))
219        } else {
220            None
221        }
222    }
223
224    /// Convenient conversion from slice of scalar to underlying representation for efficiency
225    /// purposes.
226    #[inline]
227    pub fn slice_to_repr(value: &[Self]) -> &[FsFr] {
228        // SAFETY: `Scalar` is `#[repr(transparent)]` and guaranteed to have the same memory layout
229        unsafe { mem::transmute(value) }
230    }
231
232    /// Convenient conversion from slice of underlying representation to scalar for efficiency
233    /// purposes.
234    #[inline]
235    pub fn slice_from_repr(value: &[FsFr]) -> &[Self] {
236        // SAFETY: `Scalar` is `#[repr(transparent)]` and guaranteed to have the same memory layout
237        unsafe { mem::transmute(value) }
238    }
239
240    /// Convenient conversion from slice of optional scalar to underlying representation for efficiency
241    /// purposes.
242    #[inline]
243    pub fn slice_option_to_repr(value: &[Option<Self>]) -> &[Option<FsFr>] {
244        // SAFETY: `Scalar` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
245        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
246        // transparent wrappers
247        unsafe { mem::transmute(value) }
248    }
249
250    /// Convenient conversion from slice of optional underlying representation to scalar for efficiency
251    /// purposes.
252    #[inline]
253    pub fn slice_option_from_repr(value: &[Option<FsFr>]) -> &[Option<Self>] {
254        // SAFETY: `Scalar` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
255        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
256        // transparent wrappers
257        unsafe { mem::transmute(value) }
258    }
259
260    /// Convenient conversion from mutable slice of scalar to underlying representation for
261    /// efficiency purposes.
262    #[inline]
263    pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [FsFr] {
264        // SAFETY: `Scalar` is `#[repr(transparent)]` and guaranteed to have the same memory layout
265        unsafe { mem::transmute(value) }
266    }
267
268    /// Convenient conversion from mutable slice of underlying representation to scalar for
269    /// efficiency purposes.
270    #[inline]
271    pub fn slice_mut_from_repr(value: &mut [FsFr]) -> &mut [Self] {
272        // SAFETY: `Scalar` is `#[repr(transparent)]` and guaranteed to have the same memory layout
273        unsafe { mem::transmute(value) }
274    }
275
276    /// Convenient conversion from optional mutable slice of scalar to underlying representation for
277    /// efficiency purposes.
278    #[inline]
279    pub fn slice_option_mut_to_repr(value: &mut [Option<Self>]) -> &mut [Option<FsFr>] {
280        // SAFETY: `Scalar` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
281        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
282        // transparent wrappers
283        unsafe { mem::transmute(value) }
284    }
285
286    /// Convenient conversion from optional mutable slice of underlying representation to scalar for
287    /// efficiency purposes.
288    #[inline]
289    pub fn slice_option_mut_from_repr(value: &mut [Option<FsFr>]) -> &mut [Option<Self>] {
290        // SAFETY: `Scalar` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
291        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
292        // transparent wrappers
293        unsafe { mem::transmute(value) }
294    }
295
296    /// Convenient conversion from vector of scalar to underlying representation for efficiency
297    /// purposes.
298    #[inline]
299    pub fn vec_to_repr(value: Vec<Self>) -> Vec<FsFr> {
300        // SAFETY: `Scalar` is `#[repr(transparent)]` and guaranteed to have the same memory
301        //  layout, original vector is not dropped
302        unsafe {
303            let mut value = mem::ManuallyDrop::new(value);
304            Vec::from_raw_parts(
305                value.as_mut_ptr() as *mut FsFr,
306                value.len(),
307                value.capacity(),
308            )
309        }
310    }
311
312    /// Convenient conversion from vector of underlying representation to scalar for efficiency
313    /// purposes.
314    #[inline]
315    pub fn vec_from_repr(value: Vec<FsFr>) -> Vec<Self> {
316        // SAFETY: `Scalar` is `#[repr(transparent)]` and guaranteed to have the same memory
317        //  layout, original vector is not dropped
318        unsafe {
319            let mut value = mem::ManuallyDrop::new(value);
320            Vec::from_raw_parts(
321                value.as_mut_ptr() as *mut Self,
322                value.len(),
323                value.capacity(),
324            )
325        }
326    }
327
328    /// Convenient conversion from vector of optional scalar to underlying representation for
329    /// efficiency purposes.
330    #[inline]
331    pub fn vec_option_to_repr(value: Vec<Option<Self>>) -> Vec<Option<FsFr>> {
332        // SAFETY: `Scalar` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
333        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
334        // transparent wrappers, original vector is not dropped
335        unsafe {
336            let mut value = mem::ManuallyDrop::new(value);
337            Vec::from_raw_parts(
338                value.as_mut_ptr() as *mut Option<FsFr>,
339                value.len(),
340                value.capacity(),
341            )
342        }
343    }
344
345    /// Convenient conversion from vector of optional underlying representation to scalar for
346    /// efficiency purposes.
347    #[inline]
348    pub fn vec_option_from_repr(value: Vec<Option<FsFr>>) -> Vec<Option<Self>> {
349        // SAFETY: `Scalar` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
350        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
351        // transparent wrappers, original vector is not dropped
352        unsafe {
353            let mut value = mem::ManuallyDrop::new(value);
354            Vec::from_raw_parts(
355                value.as_mut_ptr() as *mut Option<Self>,
356                value.len(),
357                value.capacity(),
358            )
359        }
360    }
361}
362
363/// Commitment to polynomial
364#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, From, Into, AsRef, AsMut, Deref, DerefMut)]
365#[repr(transparent)]
366pub struct Commitment(FsG1);
367
368const_assert_eq!(
369    mem::size_of::<Option<Commitment>>(),
370    mem::size_of::<Option<FsG1>>()
371);
372const_assert_eq!(
373    mem::align_of::<Option<Commitment>>(),
374    mem::align_of::<Option<FsG1>>()
375);
376
377impl Commitment {
378    /// Commitment size in bytes.
379    const SIZE: usize = 48;
380
381    /// Convert commitment to raw bytes
382    #[inline]
383    pub fn to_bytes(&self) -> [u8; Self::SIZE] {
384        self.0.to_bytes()
385    }
386
387    /// Try to deserialize commitment from raw bytes
388    #[inline]
389    pub fn try_from_bytes(bytes: &[u8; Self::SIZE]) -> Result<Self, String> {
390        Ok(Commitment(FsG1::from_bytes(bytes)?))
391    }
392
393    /// Convenient conversion from slice of commitment to underlying representation for efficiency
394    /// purposes.
395    #[inline]
396    pub fn slice_to_repr(value: &[Self]) -> &[FsG1] {
397        // SAFETY: `Commitment` is `#[repr(transparent)]` and guaranteed to have the same memory
398        // layout
399        unsafe { mem::transmute(value) }
400    }
401
402    /// Convenient conversion from slice of underlying representation to commitment for efficiency
403    /// purposes.
404    #[inline]
405    pub fn slice_from_repr(value: &[FsG1]) -> &[Self] {
406        // SAFETY: `Commitment` is `#[repr(transparent)]` and guaranteed to have the same memory
407        // layout
408        unsafe { mem::transmute(value) }
409    }
410
411    /// Convenient conversion from slice of optional commitment to underlying representation for
412    /// efficiency purposes.
413    #[inline]
414    pub fn slice_option_to_repr(value: &[Option<Self>]) -> &[Option<FsG1>] {
415        // SAFETY: `Commitment` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
416        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
417        // transparent wrappers
418        unsafe { mem::transmute(value) }
419    }
420
421    /// Convenient conversion from slice of optional underlying representation to commitment for
422    /// efficiency purposes.
423    #[inline]
424    pub fn slice_option_from_repr(value: &[Option<FsG1>]) -> &[Option<Self>] {
425        // SAFETY: `Commitment` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
426        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
427        // transparent wrappers
428        unsafe { mem::transmute(value) }
429    }
430
431    /// Convenient conversion from mutable slice of commitment to underlying representation for
432    /// efficiency purposes.
433    #[inline]
434    pub fn slice_mut_to_repr(value: &mut [Self]) -> &mut [FsG1] {
435        // SAFETY: `Commitment` is `#[repr(transparent)]` and guaranteed to have the same memory
436        // layout
437        unsafe { mem::transmute(value) }
438    }
439
440    /// Convenient conversion from mutable slice of underlying representation to commitment for
441    /// efficiency purposes.
442    #[inline]
443    pub fn slice_mut_from_repr(value: &mut [FsG1]) -> &mut [Self] {
444        // SAFETY: `Commitment` is `#[repr(transparent)]` and guaranteed to have the same memory
445        // layout
446        unsafe { mem::transmute(value) }
447    }
448
449    /// Convenient conversion from optional mutable slice of commitment to underlying representation
450    /// for efficiency purposes.
451    #[inline]
452    pub fn slice_option_mut_to_repr(value: &mut [Option<Self>]) -> &mut [Option<FsG1>] {
453        // SAFETY: `Commitment` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
454        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
455        // transparent wrappers
456        unsafe { mem::transmute(value) }
457    }
458
459    /// Convenient conversion from optional mutable slice of underlying representation to commitment
460    /// for efficiency purposes.
461    #[inline]
462    pub fn slice_option_mut_from_repr(value: &mut [Option<FsG1>]) -> &mut [Option<Self>] {
463        // SAFETY: `Commitment` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
464        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
465        // transparent wrappers
466        unsafe { mem::transmute(value) }
467    }
468
469    /// Convenient conversion from vector of commitment to underlying representation for efficiency
470    /// purposes.
471    #[inline]
472    pub fn vec_to_repr(value: Vec<Self>) -> Vec<FsG1> {
473        // SAFETY: `Commitment` is `#[repr(transparent)]` and guaranteed to have the same memory
474        //  layout, original vector is not dropped
475        unsafe {
476            let mut value = mem::ManuallyDrop::new(value);
477            Vec::from_raw_parts(
478                value.as_mut_ptr() as *mut FsG1,
479                value.len(),
480                value.capacity(),
481            )
482        }
483    }
484
485    /// Convenient conversion from vector of underlying representation to commitment for efficiency
486    /// purposes.
487    #[inline]
488    pub fn vec_from_repr(value: Vec<FsG1>) -> Vec<Self> {
489        // SAFETY: `Commitment` is `#[repr(transparent)]` and guaranteed to have the same memory
490        //  layout, original vector is not dropped
491        unsafe {
492            let mut value = mem::ManuallyDrop::new(value);
493            Vec::from_raw_parts(
494                value.as_mut_ptr() as *mut Self,
495                value.len(),
496                value.capacity(),
497            )
498        }
499    }
500
501    /// Convenient conversion from vector of optional commitment to underlying representation for
502    /// efficiency purposes.
503    #[inline]
504    pub fn vec_option_to_repr(value: Vec<Option<Self>>) -> Vec<Option<FsG1>> {
505        // SAFETY: `Commitment` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
506        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
507        // transparent wrappers, original vector is not dropped
508        unsafe {
509            let mut value = mem::ManuallyDrop::new(value);
510            Vec::from_raw_parts(
511                value.as_mut_ptr() as *mut Option<FsG1>,
512                value.len(),
513                value.capacity(),
514            )
515        }
516    }
517
518    /// Convenient conversion from vector of optional underlying representation to commitment for
519    /// efficiency purposes.
520    #[inline]
521    pub fn vec_option_from_repr(value: Vec<Option<FsG1>>) -> Vec<Option<Self>> {
522        // SAFETY: `Commitment` is `#[repr(transparent)]` containing `#[repr(C)]` and we assume the
523        // compiler lays out optional `repr(C)` plain old data arrays the same as their optional
524        // transparent wrappers, original vector is not dropped
525        unsafe {
526            let mut value = mem::ManuallyDrop::new(value);
527            Vec::from_raw_parts(
528                value.as_mut_ptr() as *mut Option<Self>,
529                value.len(),
530                value.capacity(),
531            )
532        }
533    }
534}
535
536impl From<Commitment> for RecordCommitment {
537    #[inline]
538    fn from(commitment: Commitment) -> Self {
539        RecordCommitment::from(commitment.to_bytes())
540    }
541}
542
543impl TryFrom<&RecordCommitment> for Commitment {
544    type Error = String;
545
546    #[inline]
547    fn try_from(commitment: &RecordCommitment) -> Result<Self, Self::Error> {
548        Commitment::try_from(**commitment)
549    }
550}
551
552impl TryFrom<RecordCommitment> for Commitment {
553    type Error = String;
554
555    #[inline]
556    fn try_from(commitment: RecordCommitment) -> Result<Self, Self::Error> {
557        Commitment::try_from(&commitment)
558    }
559}
560
561impl From<Commitment> for SegmentCommitment {
562    #[inline]
563    fn from(commitment: Commitment) -> Self {
564        SegmentCommitment::from(commitment.to_bytes())
565    }
566}
567
568impl TryFrom<&SegmentCommitment> for Commitment {
569    type Error = String;
570
571    #[inline]
572    fn try_from(commitment: &SegmentCommitment) -> Result<Self, Self::Error> {
573        Commitment::try_from(**commitment)
574    }
575}
576
577impl TryFrom<SegmentCommitment> for Commitment {
578    type Error = String;
579
580    #[inline]
581    fn try_from(commitment: SegmentCommitment) -> Result<Self, Self::Error> {
582        Commitment::try_from(&commitment)
583    }
584}
585
586impl From<Commitment> for [u8; Commitment::SIZE] {
587    #[inline]
588    fn from(commitment: Commitment) -> Self {
589        commitment.to_bytes()
590    }
591}
592
593impl From<&Commitment> for [u8; Commitment::SIZE] {
594    #[inline]
595    fn from(commitment: &Commitment) -> Self {
596        commitment.to_bytes()
597    }
598}
599
600impl TryFrom<&[u8; Self::SIZE]> for Commitment {
601    type Error = String;
602
603    #[inline]
604    fn try_from(bytes: &[u8; Self::SIZE]) -> Result<Self, Self::Error> {
605        Self::try_from_bytes(bytes)
606    }
607}
608
609impl TryFrom<[u8; Self::SIZE]> for Commitment {
610    type Error = String;
611
612    #[inline]
613    fn try_from(bytes: [u8; Self::SIZE]) -> Result<Self, Self::Error> {
614        Self::try_from(&bytes)
615    }
616}
617
618/// Witness for polynomial evaluation
619#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, From, Into, AsRef, AsMut, Deref, DerefMut)]
620#[repr(transparent)]
621pub struct Witness(FsG1);
622
623impl Witness {
624    /// Commitment size in bytes.
625    const SIZE: usize = 48;
626
627    /// Convert witness to raw bytes
628    pub fn to_bytes(&self) -> [u8; Self::SIZE] {
629        self.0.to_bytes()
630    }
631
632    /// Try to deserialize witness from raw bytes
633    pub fn try_from_bytes(bytes: &[u8; Self::SIZE]) -> Result<Self, String> {
634        Ok(Witness(FsG1::from_bytes(bytes)?))
635    }
636}
637
638impl From<Witness> for RecordWitness {
639    #[inline]
640    fn from(witness: Witness) -> Self {
641        RecordWitness::from(witness.to_bytes())
642    }
643}
644
645impl TryFrom<&RecordWitness> for Witness {
646    type Error = String;
647
648    #[inline]
649    fn try_from(witness: &RecordWitness) -> Result<Self, Self::Error> {
650        Witness::try_from(**witness)
651    }
652}
653
654impl TryFrom<RecordWitness> for Witness {
655    type Error = String;
656
657    #[inline]
658    fn try_from(witness: RecordWitness) -> Result<Self, Self::Error> {
659        Witness::try_from(&witness)
660    }
661}
662
663impl From<Witness> for ChunkWitness {
664    #[inline]
665    fn from(witness: Witness) -> Self {
666        ChunkWitness::from(witness.to_bytes())
667    }
668}
669
670impl TryFrom<&ChunkWitness> for Witness {
671    type Error = String;
672
673    #[inline]
674    fn try_from(witness: &ChunkWitness) -> Result<Self, Self::Error> {
675        Witness::try_from(**witness)
676    }
677}
678
679impl TryFrom<ChunkWitness> for Witness {
680    type Error = String;
681
682    #[inline]
683    fn try_from(witness: ChunkWitness) -> Result<Self, Self::Error> {
684        Witness::try_from(&witness)
685    }
686}
687
688impl From<Witness> for [u8; Witness::SIZE] {
689    #[inline]
690    fn from(witness: Witness) -> Self {
691        witness.to_bytes()
692    }
693}
694
695impl From<&Witness> for [u8; Witness::SIZE] {
696    #[inline]
697    fn from(witness: &Witness) -> Self {
698        witness.to_bytes()
699    }
700}
701
702impl TryFrom<&[u8; Self::SIZE]> for Witness {
703    type Error = String;
704
705    #[inline]
706    fn try_from(bytes: &[u8; Self::SIZE]) -> Result<Self, Self::Error> {
707        Self::try_from_bytes(bytes)
708    }
709}
710
711impl TryFrom<[u8; Self::SIZE]> for Witness {
712    type Error = String;
713
714    #[inline]
715    fn try_from(bytes: [u8; Self::SIZE]) -> Result<Self, Self::Error> {
716        Self::try_from(&bytes)
717    }
718}
719
720#[derive(Debug)]
721struct Inner {
722    kzg_settings: FsKZGSettings,
723    fft_settings_cache: Mutex<BTreeMap<usize, Arc<FsFFTSettings>>>,
724}
725
726/// Wrapper data structure for working with KZG commitment scheme
727#[derive(Debug, Clone)]
728pub struct Kzg {
729    inner: Arc<Inner>,
730}
731
732impl Kzg {
733    /// Create new instance with embedded KZG settings.
734    ///
735    /// NOTE: Prefer cloning to instantiation since cloning is cheap and instantiation is not!
736    #[expect(
737        clippy::new_without_default,
738        reason = "Default must not be implemented, because Kzg should be cloned instead. Cloning is cheap and instantiation is not."
739    )]
740    pub fn new() -> Self {
741        let kzg_settings =
742            bytes_to_kzg_settings(EMBEDDED_KZG_SETTINGS_BYTES, NUM_G1_POWERS, NUM_G2_POWERS)
743                .expect("Static bytes are correct, there is a test for this; qed");
744
745        let inner = Arc::new(Inner {
746            kzg_settings,
747            fft_settings_cache: Mutex::default(),
748        });
749
750        Self { inner }
751    }
752
753    /// Create polynomial from data. Data must be multiple of 32 bytes, each containing up to 254
754    /// bits of information.
755    ///
756    /// The resulting polynomial is in coefficient form.
757    pub fn poly(&self, data: &[Scalar]) -> Result<Polynomial, String> {
758        let poly = FsPoly {
759            coeffs: self
760                .get_fft_settings(data.len())?
761                .fft_fr(Scalar::slice_to_repr(data), true)?,
762        };
763        Ok(Polynomial(poly))
764    }
765
766    /// Computes a `Commitment` to `polynomial`
767    pub fn commit(&self, polynomial: &Polynomial) -> Result<Commitment, String> {
768        self.inner
769            .kzg_settings
770            .commit_to_poly(&polynomial.0)
771            .map(Commitment)
772    }
773
774    /// Computes a `Witness` of evaluation of `polynomial` at `index`
775    pub fn create_witness(
776        &self,
777        polynomial: &Polynomial,
778        num_values: usize,
779        index: u32,
780    ) -> Result<Witness, String> {
781        let x = self
782            .get_fft_settings(num_values)?
783            .get_expanded_roots_of_unity_at(index as usize);
784        self.inner
785            .kzg_settings
786            .compute_proof_single(&polynomial.0, &x)
787            .map(Witness)
788    }
789
790    /// Verifies that `value` is the evaluation at `index` of the polynomial created from
791    /// `num_values` values matching the `commitment`.
792    pub fn verify(
793        &self,
794        commitment: &Commitment,
795        num_values: usize,
796        index: u32,
797        value: &Scalar,
798        witness: &Witness,
799    ) -> bool {
800        let fft_settings = match self.get_fft_settings(num_values) {
801            Ok(fft_settings) => fft_settings,
802            Err(error) => {
803                debug!(error, "Failed to derive fft settings");
804                return false;
805            }
806        };
807        let x = fft_settings.get_expanded_roots_of_unity_at(index as usize);
808
809        match self
810            .inner
811            .kzg_settings
812            .check_proof_single(&commitment.0, &witness.0, &x, value)
813        {
814            Ok(result) => result,
815            Err(error) => {
816                debug!(error, "Failed to check proof");
817                false
818            }
819        }
820    }
821
822    /// Get FFT settings for specified number of values, uses internal cache to avoid derivation
823    /// every time.
824    fn get_fft_settings(&self, num_values: usize) -> Result<Arc<FsFFTSettings>, String> {
825        let num_values = num_values.next_power_of_two();
826        Ok(
827            match self.inner.fft_settings_cache.lock().entry(num_values) {
828                Entry::Vacant(entry) => {
829                    let fft_settings = Arc::new(FsFFTSettings::new(num_values.ilog2() as usize)?);
830                    entry.insert(Arc::clone(&fft_settings));
831                    fft_settings
832                }
833                Entry::Occupied(entry) => Arc::clone(entry.get()),
834            },
835        )
836    }
837}