1#[cfg(not(feature = "std"))]
2use alloc::string::String;
3
4pub const BYTES_PER_FIELD_ELEMENT: usize = 32;
8pub const FIELD_ELEMENTS_PER_BLOB: usize = 4096;
9pub const BYTES_PER_BLOB: usize = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB;
10pub const FIELD_ELEMENTS_PER_EXT_BLOB: usize = 2 * FIELD_ELEMENTS_PER_BLOB;
11pub const FIELD_ELEMENTS_PER_CELL: usize = 64;
12pub const BYTES_PER_CELL: usize = FIELD_ELEMENTS_PER_CELL * BYTES_PER_FIELD_ELEMENT;
13pub const CELLS_PER_EXT_BLOB: usize = FIELD_ELEMENTS_PER_EXT_BLOB / FIELD_ELEMENTS_PER_CELL;
14
15#[cfg(not(feature = "risc0"))]
19pub const KZG_PRECOMPUTE: u64 = 8;
20#[cfg(feature = "risc0")]
21pub const KZG_PRECOMPUTE: u64 = 0;
22
23type Bytes48 = [u8; 48];
24type Blob = [u8; BYTES_PER_BLOB];
25type Commitment = Bytes48;
26type Proof = Bytes48;
27
28pub fn warm_up_trusted_setup() {
30 #[cfg(feature = "c-kzg")]
31 {
32 let _ = std::thread::Builder::new()
33 .name("kzg-warmup".into())
34 .spawn(|| {
35 std::hint::black_box(c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE));
36 });
37 }
38}
39
40#[derive(thiserror::Error, Debug)]
41pub enum KzgError {
42 #[cfg(feature = "c-kzg")]
43 #[error("c-kzg error: {0}")]
44 CKzg(#[from] c_kzg::Error),
45 #[cfg(feature = "kzg-rs")]
46 #[error("kzg-rs error: {0}")]
47 KzgRs(kzg_rs::KzgError),
48 #[cfg(not(feature = "c-kzg"))]
49 #[error("{0} is not supported without c-kzg feature enabled")]
50 NotSupportedWithoutCKZG(String),
51 #[error("unimplemented: {0}")]
52 Unimplemented(String),
53}
54
55#[cfg(feature = "kzg-rs")]
56impl From<kzg_rs::KzgError> for KzgError {
57 fn from(value: kzg_rs::KzgError) -> Self {
58 KzgError::KzgRs(value)
59 }
60}
61
62#[allow(unused_variables)]
64pub fn verify_cell_kzg_proof_batch(
65 blobs: &[Blob],
66 commitments: &[Commitment],
67 cell_proof: &[Proof],
68) -> Result<bool, KzgError> {
69 #[cfg(not(feature = "c-kzg"))]
70 return Err(KzgError::NotSupportedWithoutCKZG(String::from(
71 "Cell proof verification",
72 )));
73 #[cfg(feature = "c-kzg")]
74 {
75 let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE);
76 let mut cells = Vec::new();
77 for blob in blobs {
78 let blob: c_kzg::Blob = (*blob).into();
79 let cells_blob = c_kzg_settings
80 .compute_cells(&blob)
81 .map_err(KzgError::CKzg)?;
82 cells.extend(*cells_blob);
83 }
84 c_kzg::KzgSettings::verify_cell_kzg_proof_batch(
85 c_kzg_settings,
86 &commitments
87 .iter()
88 .flat_map(|commitment| {
89 std::iter::repeat_n((*commitment).into(), CELLS_PER_EXT_BLOB)
90 })
91 .collect::<Vec<_>>(),
92 &std::iter::repeat_n(0..CELLS_PER_EXT_BLOB as u64, blobs.len())
93 .flatten()
94 .collect::<Vec<_>>(),
95 &cells,
96 &cell_proof
97 .iter()
98 .map(|proof| (*proof).into())
99 .collect::<Vec<_>>(),
100 )
101 .map_err(KzgError::from)
102 }
103}
104
105pub fn verify_blob_kzg_proof(
107 blob: Blob,
108 commitment: Commitment,
109 proof: Proof,
110) -> Result<bool, KzgError> {
111 #[cfg(all(not(feature = "c-kzg"), not(feature = "kzg-rs")))]
112 {
113 let _blob = blob;
114 let _commitment = commitment;
115 let _proof = proof;
116 Err(KzgError::Unimplemented(
117 "One of features c-kzg or kzg-rs should be active".into(),
118 ))
119 }
120 #[cfg(all(not(feature = "c-kzg"), feature = "kzg-rs"))]
121 {
122 kzg_rs::KzgProof::verify_blob_kzg_proof(
123 kzg_rs::Blob(blob),
124 &kzg_rs::Bytes48(commitment),
125 &kzg_rs::Bytes48(proof),
126 &kzg_rs::get_kzg_settings(),
127 )
128 .map_err(KzgError::from)
129 }
130 #[cfg(feature = "c-kzg")]
131 {
132 let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE);
133 c_kzg_settings
134 .verify_blob_kzg_proof(&blob.into(), &commitment.into(), &proof.into())
135 .map_err(KzgError::from)
136 }
137}
138
139#[cfg(feature = "c-kzg")]
140pub fn verify_kzg_proof_batch(
141 blobs: &[Blob],
142 commitments: &[Commitment],
143 cell_proof: &[Proof],
144) -> Result<bool, KzgError> {
145 {
146 let blobs: Vec<_> = blobs.iter().map(|x| c_kzg::Blob::new(*x)).collect();
148 let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE);
149 c_kzg_settings
150 .verify_blob_kzg_proof_batch(
151 &blobs,
152 &commitments
153 .iter()
154 .map(|x| c_kzg::Bytes48::new(*x))
155 .collect::<Vec<_>>(),
156 &cell_proof
157 .iter()
158 .map(|proof| (*proof).into())
159 .collect::<Vec<_>>(),
160 )
161 .map_err(KzgError::from)
162 }
163}
164
165pub fn verify_kzg_proof(
167 commitment_bytes: [u8; 48],
168 z: [u8; 32],
169 y: [u8; 32],
170 proof_bytes: [u8; 48],
171) -> Result<bool, KzgError> {
172 #[cfg(all(not(feature = "c-kzg"), not(feature = "kzg-rs")))]
173 {
174 let _commitment_bytes = commitment_bytes;
175 let _z = z;
176 let _y = y;
177 let _proof_bytes = proof_bytes;
178 Err(KzgError::Unimplemented(
179 "One of features c-kzg or kzg-rs should be active".into(),
180 ))
181 }
182 #[cfg(all(not(feature = "c-kzg"), feature = "kzg-rs"))]
183 {
184 kzg_rs::KzgProof::verify_kzg_proof(
185 &kzg_rs::Bytes48(commitment_bytes),
186 &kzg_rs::Bytes32(z),
187 &kzg_rs::Bytes32(y),
188 &kzg_rs::Bytes48(proof_bytes),
189 &kzg_rs::get_kzg_settings(),
190 )
191 .map_err(KzgError::from)
192 }
193 #[cfg(feature = "c-kzg")]
194 {
195 let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE);
196 c_kzg_settings
197 .verify_kzg_proof(
198 &commitment_bytes.into(),
199 &z.into(),
200 &y.into(),
201 &proof_bytes.into(),
202 )
203 .map_err(KzgError::from)
204 }
205}
206
207#[cfg(feature = "c-kzg")]
208pub fn blob_to_kzg_commitment_and_proof(blob: &Blob) -> Result<(Commitment, Proof), KzgError> {
209 let blob: c_kzg::Blob = (*blob).into();
210
211 let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE);
212
213 let commitment = c_kzg::KzgSettings::blob_to_kzg_commitment(c_kzg_settings, &blob)?;
214
215 let commitment_bytes = commitment.to_bytes();
216 let proof = c_kzg_settings.compute_blob_kzg_proof(&blob, &commitment_bytes)?;
217
218 let proof_bytes = proof.to_bytes();
219
220 Ok((commitment_bytes.into_inner(), proof_bytes.into_inner()))
221}
222
223#[cfg(feature = "c-kzg")]
224pub fn blob_to_commitment_and_cell_proofs(
225 blob: &Blob,
226) -> Result<(Commitment, Vec<Proof>), KzgError> {
227 let c_kzg_settings = c_kzg::ethereum_kzg_settings(KZG_PRECOMPUTE);
228
229 let blob: c_kzg::Blob = (*blob).into();
230
231 let commitment = c_kzg::KzgSettings::blob_to_kzg_commitment(c_kzg_settings, &blob)?;
232
233 let commitment_bytes = commitment.to_bytes();
234
235 let (_cells, cell_proofs) = c_kzg_settings
236 .compute_cells_and_kzg_proofs(&blob)
237 .map_err(KzgError::CKzg)?;
238
239 let cell_proofs = cell_proofs.map(|p| p.to_bytes().into_inner());
240
241 Ok((commitment_bytes.into_inner(), cell_proofs.to_vec()))
242}