Skip to main content

spongefish/drivers/
p3_koala_bear.rs

1//! Plonky3's KoalaBear field codec implementation
2use p3_field::PrimeField32;
3use p3_koala_bear::KoalaBear;
4
5use crate::{
6    codecs::{Decoding, Encoding},
7    io::NargDeserialize,
8    VerificationError, VerificationResult,
9};
10
11const KOALABEAR_ZERO: KoalaBear = unsafe { core::mem::transmute(0u32) };
12
13// Make KoalaBear a valid Unit type
14impl crate::Unit for KoalaBear {
15    const ZERO: Self = KOALABEAR_ZERO;
16}
17
18// Implement Decoding for KoalaBear
19//
20// Following the same reasoning as BabyBear:
21// We use [u8; 8] (64 bits) and reduce modulo ORDER_U32
22// to get sufficient indistinguishability.
23//
24// For KoalaBear with modulus 2^31 - 2^24 + 1 = 2,130,706,433:
25// - Sampling 32 bits would give us ~31.2 bits of indistinguishability (weak)
26// - Sampling 64 bits gives us ~64.3 bits of indistinguishability (sufficient)
27impl Decoding<[u8]> for KoalaBear {
28    type Repr = [u8; 8];
29
30    fn decode(buf: Self::Repr) -> Self {
31        let n = u64::from_le_bytes(buf);
32        Self::new((n % u64::from(Self::ORDER_U32)) as u32)
33    }
34}
35
36// Implement Deserialize for KoalaBear
37impl NargDeserialize for KoalaBear {
38    fn deserialize_from_narg(buf: &mut &[u8]) -> VerificationResult<Self> {
39        if buf.len() < 4 {
40            return Err(VerificationError);
41        }
42        let mut repr = [0u8; 4];
43        repr.copy_from_slice(&buf[..4]);
44        let value = u32::from_be_bytes(repr);
45
46        // Check that the value is in the valid range
47        if value >= Self::ORDER_U32 {
48            return Err(VerificationError);
49        }
50
51        *buf = &buf[4..];
52        Ok(Self::new(value))
53    }
54}
55
56// Implement Encoding for KoalaBear
57impl Encoding<[u8]> for KoalaBear {
58    fn encode(&self) -> impl AsRef<[u8]> {
59        self.as_canonical_u32().to_be_bytes()
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use alloc::vec::Vec;
66
67    use super::*;
68    use crate::io::NargSerialize;
69
70    #[test]
71    fn test_koalabear_serialize_deserialize() {
72        // Create a field element
73        let element = KoalaBear::new(12345);
74
75        let mut buf = Vec::new();
76        element.serialize_into_narg(&mut buf);
77
78        let deserialized = KoalaBear::deserialize_from_narg(&mut &buf[..]).unwrap();
79        assert_eq!(element, deserialized);
80    }
81
82    #[test]
83    fn test_koalabear_encoding() {
84        let element = KoalaBear::new(67890);
85
86        let encoded = element.encode();
87        let encoded_bytes = encoded.as_ref();
88
89        let deserialized = KoalaBear::deserialize_from_narg(&mut &encoded_bytes[..]).unwrap();
90        assert_eq!(element, deserialized);
91    }
92
93    #[test]
94    fn test_koalabear_out_of_range() {
95        // Try to deserialize a value larger than the modulus
96        let buf = KoalaBear::ORDER_U32.to_be_bytes();
97        let result = KoalaBear::deserialize_from_narg(&mut &buf[..]);
98        assert!(result.is_err());
99    }
100}