Skip to content

Commit

Permalink
fix comments
Browse files Browse the repository at this point in the history
  • Loading branch information
bxue-l2 committed Jan 15, 2025
1 parent 1c3f2c0 commit a1c9374
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 104 deletions.
2 changes: 0 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion bin/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ tracing.workspace = true
async-trait.workspace = true
rust-kzg-bn254.workspace = true
num.workspace = true
anyhow.workspace = true

ark-bn254.workspace = true

Expand Down
138 changes: 69 additions & 69 deletions bin/client/src/cached_eigenda_provider.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
use kona_preimage::CommsClient;
use kona_preimage::errors::PreimageOracleError;
use alloy_primitives::Bytes;
use async_trait::async_trait;
use alloy_rlp::Decodable;
use async_trait::async_trait;
use kona_preimage::errors::PreimageOracleError;
use kona_preimage::CommsClient;

use kona_proof::errors::OracleProviderError;
use hokulea_proof::eigenda_provider::OracleEigenDAProvider;
use hokulea_eigenda::EigenDABlobProvider;
use hokulea_eigenda::BlobInfo;
use hokulea_eigenda::EigenDABlobProvider;
use hokulea_proof::eigenda_provider::OracleEigenDAProvider;
use kona_proof::errors::OracleProviderError;

use crate::witness::EigenDABlobWitness;

use rust_kzg_bn254::kzg::KZG;
use rust_kzg_bn254::blob::Blob;
use num::BigUint;
use rust_kzg_bn254::blob::Blob;
use rust_kzg_bn254::kzg::KZG;


/// CachedOracleEigenDAProvider is a wrapper outside OracleEigenDAProvider. Its intended use
/// case is to fetch all eigenda blobs received during the derivation pipeline. So that it
/// is able to compute and cache the kzg witnesses, which can be verified inside ZKVM by checking
/// the point opening at the random Fiat Shamir evaluation index.
#[derive(Debug, Clone)]
pub struct CachedOracleEigenDAProvider<T: CommsClient> {
/// The preimage oracle client.
Expand All @@ -32,98 +35,96 @@ impl<T: CommsClient> CachedOracleEigenDAProvider<T> {
}

#[async_trait]
impl <T: CommsClient + Sync + Send> EigenDABlobProvider for CachedOracleEigenDAProvider<T> {
impl<T: CommsClient + Sync + Send> EigenDABlobProvider for CachedOracleEigenDAProvider<T> {
type Error = OracleProviderError;

async fn get_blob(&mut self, cert: &Bytes) -> Result<Bytes, Self::Error> {
match self.oracle.get_blob(cert).await {
Ok(b) => {
let item_slice = cert.as_ref();
let cert_blob_info = match BlobInfo::decode(&mut &item_slice[4..]) {
Ok(c) => c,
Err(_) => return Err(OracleProviderError::Preimage(
PreimageOracleError::Other("does not contain header".into(),
))),
};

let output = self.compute_and_save_witness(&b)?;
// make sure locally computed proof equals to returned proof from the provider
if output[..32] != cert_blob_info.blob_header.commitment.x[..] ||
output[32..64] != cert_blob_info.blob_header.commitment.y[..]{
return Err(OracleProviderError::Preimage(
PreimageOracleError::Other("proxy commitment is different from computed commitment proxy".into())));
};

let commitment = Bytes::copy_from_slice(
&[cert_blob_info.blob_header.commitment.x, cert_blob_info.blob_header.commitment.y]
.concat());

let kzg_proof = Bytes::copy_from_slice(&output[64..128]);

// push data into witness
self.witness.write(b.clone().into(), commitment, kzg_proof.into());

Ok(b.into())
},
Err(e) => Err(e),
}
let blob = self.oracle.get_blob(cert).await?;
let cert_blob_info = match BlobInfo::decode(&mut &cert[4..]) {
Ok(c) => c,
Err(_) => {
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"does not contain header".into(),
)))
}
};

let output = self.compute_witness(&blob)?;
// make sure locally computed proof equals to returned proof from the provider
if output[..32] != cert_blob_info.blob_header.commitment.x[..]
|| output[32..64] != cert_blob_info.blob_header.commitment.y[..]
{
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"proxy commitment is different from computed commitment proxy".into(),
)));
};

let commitment = Bytes::copy_from_slice(&output[..64]);

let kzg_proof = Bytes::copy_from_slice(&output[64..128]);

// push data into witness
self.witness
.write(blob.clone().into(), commitment, kzg_proof.into());

Ok(blob)
}
}


// nitro code https://github.com/Layr-Labs/nitro/blob/14f09745b74321f91d1f702c3e7bb5eb7d0e49ce/arbitrator/prover/src/kzgbn254.rs#L30
// nitro code https://github.com/Layr-Labs/nitro/blob/14f09745b74321f91d1f702c3e7bb5eb7d0e49ce/arbitrator/prover/src/kzgbn254.rs#L141
// could refactor in the future, such that both host and client can compute the proof
impl<T: CommsClient + Sync + Send> CachedOracleEigenDAProvider<T> {
fn compute_and_save_witness(&mut self, blob: &[u8]) -> Result<Vec<u8>, OracleProviderError> {
/// Return Bytes array so that the host can reuse the code
fn compute_witness(&mut self, blob: &[u8]) -> Result<Vec<u8>, OracleProviderError> {
// TODO remove the need for G2 access
// Add command line to specify where are g1 and g2 path
// In the future, it might make sense to let the proxy to return such
// value, instead of local computation
let mut kzg = match KZG::setup(
let mut kzg = KZG::setup(
"resources/g1.32mb.point",
"",
"resources/g2.point.powerOf2",
268435456,
1024,
) {
Ok(k) => k,
Err(_) => return Err(OracleProviderError::Preimage(
PreimageOracleError::Other("does not contain header".into(),
))),
};
)
.map_err(|_| {
OracleProviderError::Preimage(PreimageOracleError::Other(
"does not contain header".into(),
))
})?;

let input = Blob::new(blob);
let input_poly = input.to_polynomial_eval_form();

kzg.data_setup_custom(1, input.len().try_into().unwrap()).unwrap();
kzg.data_setup_custom(1, input.len().try_into().unwrap())
.unwrap();

let mut output = vec![0u8; 0];
let mut commitment_and_proof = vec![0u8; 0];

let commitment = match kzg.commit_eval_form(&input_poly) {
Ok(c) => c,
Err(_) => return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"kzg.commit_eval_form".into()))),
};
let commitment = kzg.commit_eval_form(&input_poly).map_err(|_| {
OracleProviderError::Preimage(PreimageOracleError::Other("kzg.commit_eval_form".into()))
})?;

// TODO the library should have returned the bytes, or provide a helper
// for conversion. For both proof and commitment
let commitment_x_bigint: BigUint = commitment.x.into();
let commitment_y_bigint: BigUint = commitment.y.into();

self.append_left_padded_biguint_be(&mut output, &commitment_x_bigint);
self.append_left_padded_biguint_be(&mut output, &commitment_y_bigint);
self.append_left_padded_biguint_be(&mut commitment_and_proof, &commitment_x_bigint);
self.append_left_padded_biguint_be(&mut commitment_and_proof, &commitment_y_bigint);

let proof = match kzg.compute_blob_proof(&input, &commitment) {
Ok(p) => p,
Err(_) => return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"kzg.compute_blob_kzg_proof {}".into()))),
};
let proof = kzg.compute_blob_proof(&input, &commitment).map_err(|_| {
OracleProviderError::Preimage(PreimageOracleError::Other(
"kzg.compute_blob_kzg_proof {}".into(),
))
})?;
let proof_x_bigint: BigUint = proof.x.into();
let proof_y_bigint: BigUint = proof.y.into();

self.append_left_padded_biguint_be(&mut output, &proof_x_bigint);
self.append_left_padded_biguint_be(&mut output, &proof_y_bigint);
self.append_left_padded_biguint_be(&mut commitment_and_proof, &proof_x_bigint);
self.append_left_padded_biguint_be(&mut commitment_and_proof, &proof_y_bigint);

Ok(output)
Ok(commitment_and_proof)
}

pub fn append_left_padded_biguint_be(&self, vec: &mut Vec<u8>, biguint: &BigUint) {
Expand All @@ -132,5 +133,4 @@ impl<T: CommsClient + Sync + Send> CachedOracleEigenDAProvider<T> {
vec.extend(std::iter::repeat(0).take(padding));
vec.extend_from_slice(&bytes);
}

}
46 changes: 27 additions & 19 deletions bin/client/src/witness.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use alloy_primitives::Bytes;
use alloc::vec::Vec;
use rust_kzg_bn254::kzg::KZG;
use rust_kzg_bn254::blob::Blob;
use ark_bn254::{G1Affine, Fq};
use alloy_primitives::Bytes;
use ark_bn254::{Fq, G1Affine};
use ark_ff::PrimeField;
use rust_kzg_bn254::blob::Blob;
use rust_kzg_bn254::kzg::KZG;
use tracing::info;

#[derive(Debug, Clone)]
Expand All @@ -18,7 +18,7 @@ impl EigenDABlobWitness {
EigenDABlobWitness {
eigenda_blobs: Vec::new(),
commitments: Vec::new(),
proofs: Vec::new(),
proofs: Vec::new(),
}
}

Expand All @@ -30,7 +30,8 @@ impl EigenDABlobWitness {
}

pub fn verify(&self) -> bool {
// TODO we should have to specify the details to get a kzg to perform a verification
// TODO we should not need so many g1 and g2 points for kzg verification
// improve kzg library instead
let kzg = match KZG::setup(
"resources/g1.32mb.point",
"",
Expand All @@ -42,32 +43,39 @@ impl EigenDABlobWitness {
Err(e) => panic!("cannot setup kzg {}", e),
};


info!("lib_blobs len {:?}", self.eigenda_blobs.len());

// transform to rust-kzg-bn254 inputs types
// TODO should make library do the parsing the return result
let lib_blobs: Vec<Blob> = self.eigenda_blobs.iter().map(|b| Blob::new(b)).collect();
let lib_commitments: Vec<G1Affine> = self.commitments.iter().map(|c| {
let x = Fq::from_be_bytes_mod_order(&c[..32]);
let y = Fq::from_be_bytes_mod_order(&c[32..64]);
G1Affine::new(x, y)
}).collect();
let lib_proofs: Vec<G1Affine> = self.proofs.iter().map(|p| {
let x = Fq::from_be_bytes_mod_order(&p[..32]);
let y = Fq::from_be_bytes_mod_order(&p[32..64]);
let lib_commitments: Vec<G1Affine> = self
.commitments
.iter()
.map(|c| {
let x = Fq::from_be_bytes_mod_order(&c[..32]);
let y = Fq::from_be_bytes_mod_order(&c[32..64]);
G1Affine::new(x, y)
})
.collect();
let lib_proofs: Vec<G1Affine> = self
.proofs
.iter()
.map(|p| {
let x = Fq::from_be_bytes_mod_order(&p[..32]);
let y = Fq::from_be_bytes_mod_order(&p[32..64]);

G1Affine::new(x, y)
}).collect();
G1Affine::new(x, y)
})
.collect();
let pairing_result = kzg
.verify_blob_kzg_proof_batch(&lib_blobs, &lib_commitments, &lib_proofs)
.unwrap();

//info!("lib_blobs {:?}", lib_blobs);
//info!("lib_commitments {:?}", lib_commitments);
//info!("lib_proofs {:?}", lib_proofs);
//info!("pairing_result {:?}", pairing_result);

return pairing_result
return pairing_result;
}
}
1 change: 0 additions & 1 deletion bin/host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ reqwest.workspace = true
async-trait.workspace = true
tokio = { workspace = true, features = ["full"] }
clap = { workspace = true, features = ["derive", "env"] }
num.workspace = true

[dev-dependencies]
proptest.workspace = true
21 changes: 9 additions & 12 deletions bin/host/src/eigenda_fetcher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,15 @@ where
let cert_blob_info = BlobInfo::decode(&mut &item_slice[4..]).unwrap();

// Proxy should return a cert whose data_length measured in symbol (i.e. 32 Bytes)
let blob_length = cert_blob_info.blob_header.data_length as u64;
warn!("blob length: {:?}", blob_length);
let data_length = cert_blob_info.blob_header.data_length as u64;
warn!("data length: {:?}", data_length);

let eigenda_blob = EigenDABlobData::encode(rollup_data.as_ref());

if eigenda_blob.blob.len() != blob_length as usize * BYTES_PER_FIELD_ELEMENT {
if eigenda_blob.blob.len() != data_length as usize * BYTES_PER_FIELD_ELEMENT {
return Err(
anyhow!("data size from cert does not equal to reconstructed data codec_rollup_data_len {} blob size {}",
eigenda_blob.blob.len(), blob_length as usize * BYTES_PER_FIELD_ELEMENT));
eigenda_blob.blob.len(), data_length as usize * BYTES_PER_FIELD_ELEMENT));
}

// Write all the field elements to the key-value store.
Expand All @@ -176,9 +176,9 @@ where
blob_key[..32].copy_from_slice(cert_blob_info.blob_header.commitment.x.as_ref());
blob_key[32..64].copy_from_slice(cert_blob_info.blob_header.commitment.y.as_ref());

trace!("cert_blob_info blob_length {:?}", blob_length);
trace!("cert_blob_info data_length {:?}", data_length);

for i in 0..blob_length {
for i in 0..data_length {
blob_key[88..].copy_from_slice(i.to_be_bytes().as_ref());
let blob_key_hash = keccak256(blob_key.as_ref());

Expand All @@ -192,11 +192,10 @@ where
)?;
}

// proof is at the random point
// TODO currenlty proof is only computed in the client side if cached_eigenda_provider
// is used. We can add this back, if hosts needs to get the proof.
// Write the KZG Proof as the last element, needed for ZK
blob_key[88..].copy_from_slice((blob_length).to_be_bytes().as_ref());


//blob_key[88..].copy_from_slice((data_length).to_be_bytes().as_ref());
//let blob_key_hash = keccak256(blob_key.as_ref());
//kv_write_lock.set(
// PreimageKey::new(*blob_key_hash, PreimageKeyType::Keccak256).into(),
Expand All @@ -219,6 +218,4 @@ where

Ok(())
}


}

0 comments on commit a1c9374

Please sign in to comment.