Skip to content

Commit

Permalink
PeerDAS: Add raw functions like eip4844
Browse files Browse the repository at this point in the history
* fix clippy

* add comments after debug

* add placeholder byte into `recovered_cells` and `recovered_proofs`
  • Loading branch information
hangleang committed Jan 17, 2025
1 parent cb71d62 commit 68e0697
Showing 1 changed file with 139 additions and 4 deletions.
143 changes: 139 additions & 4 deletions kzg/src/das.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use core::fmt::Debug;
use rayon::prelude::*;

use alloc::{
format,
string::{String, ToString},
vec,
vec::Vec,
Expand All @@ -12,15 +13,18 @@ use alloc::{
use crate::{
common_utils::{reverse_bit_order, reverse_bits_limited},
eip_4844::{
blob_to_polynomial, compute_powers, hash, hash_to_bls_field, BYTES_PER_COMMITMENT,
BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF,
blob_to_polynomial, bytes_to_blob, compute_powers, hash, hash_to_bls_field, BYTES_PER_BLOB,
BYTES_PER_COMMITMENT, BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF,
},
eth, FFTFr, FFTSettings, Fr, G1Affine, G1Fp, G1LinComb, KZGSettings, PairingVerify, Poly,
FFTG1, G1, G2,
eth::{self, BYTES_PER_CELL, CELLS_PER_EXT_BLOB, FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB},
FFTFr, FFTSettings, Fr, G1Affine, G1Fp, G1LinComb, KZGSettings, PairingVerify, Poly, FFTG1, G1,
G2,
};

pub const RANDOM_CHALLENGE_KZG_CELL_BATCH_DOMAIN: [u8; 16] = *b"RCKZGCBATCH__V1_";

pub type CellsKzgProofs = (Vec<[u8; BYTES_PER_CELL]>, Vec<[u8; BYTES_PER_PROOF]>);

macro_rules! cfg_iter_mut {
($collection:expr) => {{
#[cfg(feature = "parallel")]
Expand Down Expand Up @@ -216,6 +220,40 @@ pub trait DAS<B: EcBackend> {
Ok(())
}

// TODO: there might be some fishy is the bytes conversion
fn recover_cells_and_kzg_proofs_raw(
&self,
cell_indices: &[usize],
cells: &[[u8; BYTES_PER_CELL]],
) -> Result<CellsKzgProofs, String>
where
<B as EcBackend>::G1: Copy,
<B as EcBackend>::Fr: Copy,
{
let nested_cells = cfg_iter!(cells)
.map(|bytes| bytes_to_cell::<B>(bytes))
.collect::<Result<Vec<Vec<_>>, _>>()?;
let cells = nested_cells.into_iter().flatten().collect::<Vec<_>>();

let mut recovered_cells = [B::Fr::zero(); FIELD_ELEMENTS_PER_EXT_BLOB];
let mut recovered_proofs = [B::G1::zero(); CELLS_PER_EXT_BLOB];

let _ = self.recover_cells_and_kzg_proofs(
&mut recovered_cells,
Some(&mut recovered_proofs),
cell_indices,
&cells,
);

let converted_cells = cells_elements_to_cells_bytes::<B>(&recovered_cells)?;
let converted_proofs = recovered_proofs
.into_iter()
.map(|proof| proof.to_bytes())
.collect::<Vec<_>>();

Ok((converted_cells, converted_proofs))
}

fn compute_cells_and_kzg_proofs(
&self,
cells: Option<&mut [B::Fr]>,
Expand Down Expand Up @@ -261,6 +299,35 @@ pub trait DAS<B: EcBackend> {
Ok(())
}

// TODO: same as above
fn compute_cells_and_kzg_proofs_raw(
&self,
blob: [u8; BYTES_PER_BLOB],
) -> Result<CellsKzgProofs, String>
where
<B as EcBackend>::G1: Copy,
<B as EcBackend>::Fr: Copy,
{
let blob = bytes_to_blob(&blob)?;

let mut recovered_cells = [B::Fr::zero(); FIELD_ELEMENTS_PER_EXT_BLOB];
let mut recovered_proofs = [B::G1::zero(); CELLS_PER_EXT_BLOB];

let _ = self.compute_cells_and_kzg_proofs(
Some(&mut recovered_cells),
Some(&mut recovered_proofs),
&blob,
);

let converted_cells = cells_elements_to_cells_bytes::<B>(&recovered_cells)?;
let converted_proofs = recovered_proofs
.into_iter()
.map(|proof| proof.to_bytes())
.collect::<Vec<_>>();

Ok((converted_cells, converted_proofs))
}

fn verify_cell_kzg_proof_batch(
&self,
commitments: &[B::G1],
Expand Down Expand Up @@ -362,6 +429,74 @@ pub trait DAS<B: EcBackend> {
power_of_s,
))
}

fn verify_cell_kzg_proof_batch_raw(
&self,
commitments: &[[u8; BYTES_PER_COMMITMENT]],
cell_indices: &[usize],
cells: &[[u8; BYTES_PER_CELL]],
proofs: &[[u8; BYTES_PER_PROOF]],
) -> Result<bool, String> {
let commitments = cfg_iter!(commitments)
.map(|commitment| B::G1::from_bytes(commitment))
.collect::<Result<Vec<_>, _>>()?;

let nested_cells = cfg_iter!(cells)
.map(|bytes| bytes_to_cell::<B>(bytes))
.collect::<Result<Vec<Vec<_>>, _>>()?;
let cells = nested_cells.into_iter().flatten().collect::<Vec<_>>();

let proofs = cfg_iter!(proofs)
.map(|proof| B::G1::from_bytes(proof))
.collect::<Result<Vec<_>, _>>()?;

self.verify_cell_kzg_proof_batch(&commitments, cell_indices, &cells, &proofs)
}
}

fn bytes_to_cell<B: EcBackend>(bytes: &[u8]) -> Result<Vec<B::Fr>, String> {
if bytes.len() != BYTES_PER_CELL {
return Err(format!(
"Invalid byte length. Expected {} got {}",
BYTES_PER_CELL,
bytes.len(),
));
}

bytes
.chunks(BYTES_PER_FIELD_ELEMENT)
.map(B::Fr::from_bytes)
.collect()
}

fn cells_elements_to_cells_bytes<B: EcBackend>(
bytes: &[B::Fr],
) -> Result<Vec<[u8; BYTES_PER_CELL]>, String> {
// NOTE: chunk_size = BYTES_PER_CELL / BYTES_PER_FIELD_ELEMENT
let chunk_size = FIELD_ELEMENTS_PER_CELL;
if bytes.len() % chunk_size != 0 {
return Err(format!("Invalid byte length. got {}", bytes.len(),));
}

bytes
.chunks(chunk_size)
.map(|cell_bytes| {
let mut result = [0u8; BYTES_PER_CELL];
for (idx, field_element) in cell_bytes.iter().enumerate() {
let bytes_element = field_element.to_bytes();
let start = idx * BYTES_PER_FIELD_ELEMENT;
let end = start + BYTES_PER_FIELD_ELEMENT;
if end > BYTES_PER_CELL {
return Err(format!(
"Invalid cell byte length. Expected {} got {}",
BYTES_PER_CELL, end,
));
}
result[start..end].copy_from_slice(&bytes_element);
}
Ok(result)
})
.collect()
}

fn shift_poly<B: EcBackend>(poly: &mut [B::Fr], shift_factor: &B::Fr) {
Expand Down

0 comments on commit 68e0697

Please sign in to comment.