lighthouse/crypto/kzg/src/lib.rs

84 lines
2.8 KiB
Rust
Raw Normal View History

2022-11-15 18:46:52 +00:00
mod kzg_commitment;
mod kzg_proof;
2022-11-21 19:51:10 +00:00
pub use crate::{kzg_commitment::KzgCommitment, kzg_proof::KzgProof};
use c_kzg::{Error as CKzgError, KZGSettings, BYTES_PER_FIELD_ELEMENT, FIELD_ELEMENTS_PER_BLOB};
2022-11-15 18:46:52 +00:00
use std::path::PathBuf;
2022-11-21 19:51:10 +00:00
const BYTES_PER_BLOB: usize = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT;
2022-11-15 18:46:52 +00:00
2022-11-21 19:51:10 +00:00
/// The consensus type `Blob` is generic over EthSpec, so it cannot be imported
/// in this crate without creating a cyclic dependency between the kzg and consensus/types crates.
/// So need to use a Vec here unless we think of a smarter way of doing this
type Blob = [u8; BYTES_PER_BLOB];
2022-11-15 18:46:52 +00:00
#[derive(Debug)]
pub enum Error {
InvalidTrustedSetup(CKzgError),
2022-11-21 19:51:10 +00:00
InvalidKzgCommitment(CKzgError),
InvalidKzgProof(CKzgError),
KzgVerificationFailed(CKzgError),
EmptyBlobs,
EmptyKzgCommitments,
InvalidLength(String),
KzgProofComputationFailed(CKzgError),
2022-11-15 18:46:52 +00:00
}
pub struct Kzg {
2022-11-21 19:51:10 +00:00
trusted_setup: KZGSettings,
2022-11-15 18:46:52 +00:00
}
impl Kzg {
pub fn new_from_file(file_path: PathBuf) -> Result<Self, Error> {
Ok(Self {
2022-11-21 19:51:10 +00:00
trusted_setup: KZGSettings::load_trusted_setup(file_path)
.map_err(Error::InvalidTrustedSetup)?,
2022-11-15 18:46:52 +00:00
})
}
2022-11-21 19:51:10 +00:00
pub fn compute_aggregate_kzg_proof(&self, blobs: &[Blob]) -> Result<KzgProof, Error> {
if blobs.len() == 0 {
return Err(Error::EmptyBlobs);
}
c_kzg::KZGProof::compute_aggregate_kzg_proof(blobs, &self.trusted_setup)
.map_err(Error::KzgProofComputationFailed)
.map(|proof| KzgProof(proof.to_bytes()))
}
pub fn verify_aggregate_kzg_proof(
&self,
blobs: &[Blob],
expected_kzg_commitments: &[KzgCommitment],
kzg_aggregated_proof: KzgProof,
) -> Result<bool, Error> {
if blobs.len() == 0 {
return Err(Error::EmptyBlobs);
}
if expected_kzg_commitments.len() == 0 {
return Err(Error::EmptyBlobs);
}
if blobs.len() != expected_kzg_commitments.len() {
return Err(Error::InvalidLength(
"blobs and expected_kzg_commitments should be of same size".to_string(),
));
}
let commitments = expected_kzg_commitments
.into_iter()
.map(|comm| {
c_kzg::KZGCommitment::from_bytes(&comm.0).map_err(Error::InvalidKzgCommitment)
})
.collect::<Result<Vec<c_kzg::KZGCommitment>, Error>>()?;
let proof =
c_kzg::KZGProof::from_bytes(&kzg_aggregated_proof.0).map_err(Error::InvalidKzgProof)?;
proof
.verify_aggregate_kzg_proof(blobs, &commitments, &self.trusted_setup)
.map_err(Error::InvalidKzgProof)
}
2022-11-15 18:46:52 +00:00
2022-11-21 19:51:10 +00:00
pub fn blob_to_kzg_commitment(&self, blob: Blob) -> KzgCommitment {
KzgCommitment(
c_kzg::KZGCommitment::blob_to_kzg_commitment(blob, &self.trusted_setup).to_bytes(),
)
}
2022-11-15 18:46:52 +00:00
}