mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 00:42:42 +00:00
Remove c-kzg (#8930)
#7330 Removes `c-kzg` from our `kzg` crate and rely fully on the `rust_eth_kzg` crate. This removes the old `Blob` type entirely and instead handles `rust_eth_kzg::KzgBlobRef`s directly which allows us to avoid some extra stack allocations . Similarly, we make `Bytes32` and `Bytes48` type aliases rather than structs as this fits better with the new `rust_eth_kzg` API. Co-Authored-By: Mac L <mjladson@pm.me>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -4825,7 +4825,6 @@ name = "kzg"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"c-kzg",
|
||||
"criterion",
|
||||
"educe",
|
||||
"ethereum_hashing",
|
||||
|
||||
@@ -117,9 +117,6 @@ bitvec = "1"
|
||||
bls = { path = "crypto/bls" }
|
||||
byteorder = "1"
|
||||
bytes = "1.11.1"
|
||||
# Turn off c-kzg's default features which include `blst/portable`. We can turn on blst's portable
|
||||
# feature ourselves when desired.
|
||||
c-kzg = { version = "2.1", default-features = false }
|
||||
cargo_metadata = "0.19"
|
||||
clap = { version = "4.5.4", features = ["derive", "cargo", "wrap_help"] }
|
||||
clap_utils = { path = "common/clap_utils" }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use kzg::{
|
||||
Blob as KzgBlob, Bytes48, Cell as KzgCell, CellRef as KzgCellRef, CellsAndKzgProofs,
|
||||
Error as KzgError, Kzg, KzgBlobRef,
|
||||
Cell as KzgCell, CellRef as KzgCellRef, CellsAndKzgProofs, Error as KzgError, Kzg, KzgBlobRef,
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
use ssz_types::{FixedVector, VariableList};
|
||||
@@ -15,18 +14,18 @@ use types::{
|
||||
SignedBeaconBlock, SignedBeaconBlockHeader, SignedBlindedBeaconBlock, Slot,
|
||||
};
|
||||
|
||||
/// Converts a blob ssz List object to an array to be used with the kzg
|
||||
/// crypto library.
|
||||
fn ssz_blob_to_crypto_blob<E: EthSpec>(blob: &Blob<E>) -> Result<KzgBlob, KzgError> {
|
||||
KzgBlob::from_bytes(blob.as_ref()).map_err(Into::into)
|
||||
/// Converts a blob ssz FixedVector to a reference to a fixed-size array
|
||||
/// to be used with `rust_eth_kzg`.
|
||||
fn ssz_blob_to_kzg_blob_ref<E: EthSpec>(blob: &Blob<E>) -> Result<KzgBlobRef<'_>, KzgError> {
|
||||
blob.as_ref().try_into().map_err(|e| {
|
||||
KzgError::InconsistentArrayLength(format!(
|
||||
"blob should have a guaranteed size due to FixedVector: {e:?}"
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn ssz_blob_to_crypto_blob_boxed<E: EthSpec>(blob: &Blob<E>) -> Result<Box<KzgBlob>, KzgError> {
|
||||
ssz_blob_to_crypto_blob::<E>(blob).map(Box::new)
|
||||
}
|
||||
|
||||
/// Converts a cell ssz List object to an array to be used with the kzg
|
||||
/// crypto library.
|
||||
/// Converts a cell ssz FixedVector to a reference to a fixed-size array
|
||||
/// to be used with `rust_eth_kzg`.
|
||||
fn ssz_cell_to_crypto_cell<E: EthSpec>(cell: &Cell<E>) -> Result<KzgCellRef<'_>, KzgError> {
|
||||
let cell_bytes: &[u8] = cell.as_ref();
|
||||
cell_bytes
|
||||
@@ -42,8 +41,8 @@ pub fn validate_blob<E: EthSpec>(
|
||||
kzg_proof: KzgProof,
|
||||
) -> Result<(), KzgError> {
|
||||
let _timer = crate::metrics::start_timer(&crate::metrics::KZG_VERIFICATION_SINGLE_TIMES);
|
||||
let kzg_blob = ssz_blob_to_crypto_blob_boxed::<E>(blob)?;
|
||||
kzg.verify_blob_kzg_proof(&kzg_blob, kzg_commitment, kzg_proof)
|
||||
let kzg_blob = ssz_blob_to_kzg_blob_ref::<E>(blob)?;
|
||||
kzg.verify_blob_kzg_proof(kzg_blob, kzg_commitment, kzg_proof)
|
||||
}
|
||||
|
||||
/// Validate a batch of `DataColumnSidecar`.
|
||||
@@ -72,7 +71,7 @@ where
|
||||
}
|
||||
|
||||
for &proof in data_column.kzg_proofs() {
|
||||
proofs.push(Bytes48::from(proof));
|
||||
proofs.push(proof.0);
|
||||
}
|
||||
|
||||
// In Gloas, commitments come from the block's ExecutionPayloadBid, not the sidecar.
|
||||
@@ -90,7 +89,7 @@ where
|
||||
};
|
||||
|
||||
for &commitment in kzg_commitments.iter() {
|
||||
commitments.push(Bytes48::from(commitment));
|
||||
commitments.push(commitment.0);
|
||||
}
|
||||
|
||||
let expected_len = column_indices.len();
|
||||
@@ -120,7 +119,7 @@ pub fn validate_blobs<E: EthSpec>(
|
||||
let _timer = crate::metrics::start_timer(&crate::metrics::KZG_VERIFICATION_BATCH_TIMES);
|
||||
let blobs = blobs
|
||||
.into_iter()
|
||||
.map(|blob| ssz_blob_to_crypto_blob::<E>(blob))
|
||||
.map(|blob| ssz_blob_to_kzg_blob_ref::<E>(blob))
|
||||
.collect::<Result<Vec<_>, KzgError>>()?;
|
||||
|
||||
kzg.verify_blob_kzg_proof_batch(&blobs, expected_kzg_commitments, kzg_proofs)
|
||||
@@ -132,8 +131,8 @@ pub fn compute_blob_kzg_proof<E: EthSpec>(
|
||||
blob: &Blob<E>,
|
||||
kzg_commitment: KzgCommitment,
|
||||
) -> Result<KzgProof, KzgError> {
|
||||
let kzg_blob = ssz_blob_to_crypto_blob_boxed::<E>(blob)?;
|
||||
kzg.compute_blob_kzg_proof(&kzg_blob, kzg_commitment)
|
||||
let kzg_blob = ssz_blob_to_kzg_blob_ref::<E>(blob)?;
|
||||
kzg.compute_blob_kzg_proof(kzg_blob, kzg_commitment)
|
||||
}
|
||||
|
||||
/// Compute the kzg commitment for a given blob.
|
||||
@@ -141,8 +140,8 @@ pub fn blob_to_kzg_commitment<E: EthSpec>(
|
||||
kzg: &Kzg,
|
||||
blob: &Blob<E>,
|
||||
) -> Result<KzgCommitment, KzgError> {
|
||||
let kzg_blob = ssz_blob_to_crypto_blob_boxed::<E>(blob)?;
|
||||
kzg.blob_to_kzg_commitment(&kzg_blob)
|
||||
let kzg_blob = ssz_blob_to_kzg_blob_ref::<E>(blob)?;
|
||||
kzg.blob_to_kzg_commitment(kzg_blob)
|
||||
}
|
||||
|
||||
/// Compute the kzg proof for a given blob and an evaluation point z.
|
||||
@@ -151,10 +150,9 @@ pub fn compute_kzg_proof<E: EthSpec>(
|
||||
blob: &Blob<E>,
|
||||
z: Hash256,
|
||||
) -> Result<(KzgProof, Hash256), KzgError> {
|
||||
let z = z.0.into();
|
||||
let kzg_blob = ssz_blob_to_crypto_blob_boxed::<E>(blob)?;
|
||||
kzg.compute_kzg_proof(&kzg_blob, &z)
|
||||
.map(|(proof, z)| (proof, Hash256::from_slice(&z.to_vec())))
|
||||
let kzg_blob = ssz_blob_to_kzg_blob_ref::<E>(blob)?;
|
||||
kzg.compute_kzg_proof(kzg_blob, &z.0)
|
||||
.map(|(proof, z)| (proof, Hash256::from_slice(&z)))
|
||||
}
|
||||
|
||||
/// Verify a `kzg_proof` for a `kzg_commitment` that evaluating a polynomial at `z` results in `y`
|
||||
@@ -165,7 +163,7 @@ pub fn verify_kzg_proof<E: EthSpec>(
|
||||
z: Hash256,
|
||||
y: Hash256,
|
||||
) -> Result<bool, KzgError> {
|
||||
kzg.verify_kzg_proof(kzg_commitment, &z.0.into(), &y.0.into(), kzg_proof)
|
||||
kzg.verify_kzg_proof(kzg_commitment, &z.0, &y.0, kzg_proof)
|
||||
}
|
||||
|
||||
/// Build data column sidecars from a signed beacon block and its blobs.
|
||||
|
||||
@@ -989,7 +989,7 @@ pub fn generate_pow_block(
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use kzg::{Bytes48, CellRef, KzgBlobRef, trusted_setup::get_trusted_setup};
|
||||
use kzg::{CellRef, KzgBlobRef, trusted_setup::get_trusted_setup};
|
||||
use types::{MainnetEthSpec, MinimalEthSpec};
|
||||
|
||||
#[test]
|
||||
@@ -1015,10 +1015,11 @@ mod test {
|
||||
fn validate_blob_bundle_v1<E: EthSpec>() -> Result<(), String> {
|
||||
let kzg = load_kzg()?;
|
||||
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle_v1::<E>()?;
|
||||
let kzg_blob = kzg::Blob::from_bytes(blob.as_ref())
|
||||
.map(Box::new)
|
||||
.map_err(|e| format!("Error converting blob to kzg blob: {e:?}"))?;
|
||||
kzg.verify_blob_kzg_proof(&kzg_blob, kzg_commitment, kzg_proof)
|
||||
let kzg_blob: KzgBlobRef = blob
|
||||
.as_ref()
|
||||
.try_into()
|
||||
.map_err(|e| format!("Error converting blob to kzg blob ref: {e:?}"))?;
|
||||
kzg.verify_blob_kzg_proof(kzg_blob, kzg_commitment, kzg_proof)
|
||||
.map_err(|e| format!("Invalid blobs bundle: {e:?}"))
|
||||
}
|
||||
|
||||
@@ -1028,8 +1029,8 @@ mod test {
|
||||
load_test_blobs_bundle_v2::<E>().map(|(commitment, proofs, blob)| {
|
||||
let kzg_blob: KzgBlobRef = blob.as_ref().try_into().unwrap();
|
||||
(
|
||||
vec![Bytes48::from(commitment); proofs.len()],
|
||||
proofs.into_iter().map(|p| p.into()).collect::<Vec<_>>(),
|
||||
vec![commitment.0; proofs.len()],
|
||||
proofs.into_iter().map(|p| p.0).collect::<Vec<_>>(),
|
||||
kzg.compute_cells(kzg_blob).unwrap(),
|
||||
)
|
||||
})?;
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{fmt::Debug, hash::Hash, sync::Arc};
|
||||
use bls::Signature;
|
||||
use context_deserialize::context_deserialize;
|
||||
use educe::Educe;
|
||||
use kzg::{BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT, Blob as KzgBlob, Kzg, KzgCommitment, KzgProof};
|
||||
use kzg::{BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT, Kzg, KzgCommitment, KzgProof};
|
||||
use merkle_proof::{MerkleTreeError, merkle_root_from_branch, verify_merkle_proof};
|
||||
use rand::Rng;
|
||||
use safe_arith::ArithError;
|
||||
@@ -253,14 +253,17 @@ impl<E: EthSpec> BlobSidecar<E> {
|
||||
|
||||
let blob = Blob::<E>::new(blob_bytes)
|
||||
.map_err(|e| format!("error constructing random blob: {:?}", e))?;
|
||||
let kzg_blob = KzgBlob::from_bytes(&blob).unwrap();
|
||||
let kzg_blob: &[u8; BYTES_PER_BLOB] = blob
|
||||
.as_ref()
|
||||
.try_into()
|
||||
.map_err(|e| format!("error converting blob to kzg blob ref: {:?}", e))?;
|
||||
|
||||
let commitment = kzg
|
||||
.blob_to_kzg_commitment(&kzg_blob)
|
||||
.blob_to_kzg_commitment(kzg_blob)
|
||||
.map_err(|e| format!("error computing kzg commitment: {:?}", e))?;
|
||||
|
||||
let proof = kzg
|
||||
.compute_blob_kzg_proof(&kzg_blob, commitment)
|
||||
.compute_blob_kzg_proof(kzg_blob, commitment)
|
||||
.map_err(|e| format!("error computing kzg proof: {:?}", e))?;
|
||||
|
||||
Ok(Self {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pub mod consts;
|
||||
|
||||
pub use kzg::{Blob as KzgBlob, Error as KzgError, Kzg, KzgCommitment, KzgProof};
|
||||
pub use kzg::{Error as KzgError, Kzg, KzgCommitment, KzgProof};
|
||||
|
||||
use ssz_types::VariableList;
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ fake_crypto = []
|
||||
|
||||
[dependencies]
|
||||
arbitrary = { workspace = true, optional = true }
|
||||
c-kzg = { workspace = true }
|
||||
educe = { workspace = true }
|
||||
ethereum_hashing = { workspace = true }
|
||||
ethereum_serde_utils = { workspace = true }
|
||||
@@ -28,7 +27,6 @@ tree_hash = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
[[bench]]
|
||||
name = "benchmark"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use c_kzg::KzgSettings;
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use kzg::{trusted_setup::get_trusted_setup, TrustedSetup, NO_PRECOMPUTE};
|
||||
use kzg::trusted_setup::get_trusted_setup;
|
||||
use rust_eth_kzg::{DASContext, TrustedSetup as PeerDASTrustedSetup};
|
||||
|
||||
pub fn bench_init_context(c: &mut Criterion) {
|
||||
@@ -20,21 +19,6 @@ pub fn bench_init_context(c: &mut Criterion) {
|
||||
)
|
||||
})
|
||||
});
|
||||
c.bench_function("Initialize context c-kzg (4844)", |b| {
|
||||
b.iter(|| {
|
||||
let trusted_setup: TrustedSetup =
|
||||
serde_json::from_reader(trusted_setup_bytes.as_slice())
|
||||
.map_err(|e| format!("Unable to read trusted setup file: {}", e))
|
||||
.expect("should have trusted setup");
|
||||
KzgSettings::load_trusted_setup(
|
||||
&trusted_setup.g1_monomial(),
|
||||
&trusted_setup.g1_lagrange(),
|
||||
&trusted_setup.g2_monomial(),
|
||||
NO_PRECOMPUTE,
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_init_context);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use c_kzg::BYTES_PER_COMMITMENT;
|
||||
use crate::{Bytes48, BYTES_PER_COMMITMENT};
|
||||
use educe::Educe;
|
||||
use ethereum_hashing::hash_fixed;
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
@@ -14,7 +14,7 @@ pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01;
|
||||
#[derive(Educe, Clone, Copy, Encode, Decode)]
|
||||
#[educe(PartialEq, Eq, Hash)]
|
||||
#[ssz(struct_behaviour = "transparent")]
|
||||
pub struct KzgCommitment(pub [u8; c_kzg::BYTES_PER_COMMITMENT]);
|
||||
pub struct KzgCommitment(pub [u8; BYTES_PER_COMMITMENT]);
|
||||
|
||||
impl KzgCommitment {
|
||||
pub fn calculate_versioned_hash(&self) -> Hash256 {
|
||||
@@ -24,13 +24,13 @@ impl KzgCommitment {
|
||||
}
|
||||
|
||||
pub fn empty_for_testing() -> Self {
|
||||
KzgCommitment([0; c_kzg::BYTES_PER_COMMITMENT])
|
||||
KzgCommitment([0; BYTES_PER_COMMITMENT])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KzgCommitment> for c_kzg::Bytes48 {
|
||||
impl From<KzgCommitment> for Bytes48 {
|
||||
fn from(value: KzgCommitment) -> Self {
|
||||
value.0.into()
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use c_kzg::BYTES_PER_PROOF;
|
||||
use crate::BYTES_PER_PROOF;
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -11,12 +11,6 @@ use tree_hash::{PackedEncoding, TreeHash};
|
||||
#[ssz(struct_behaviour = "transparent")]
|
||||
pub struct KzgProof(pub [u8; BYTES_PER_PROOF]);
|
||||
|
||||
impl From<KzgProof> for c_kzg::Bytes48 {
|
||||
fn from(value: KzgProof) -> Self {
|
||||
value.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl KzgProof {
|
||||
/// Creates a valid proof using `G1_POINT_AT_INFINITY`.
|
||||
pub fn empty() -> Self {
|
||||
|
||||
@@ -12,11 +12,12 @@ pub use crate::{
|
||||
trusted_setup::TrustedSetup,
|
||||
};
|
||||
|
||||
pub use c_kzg::{
|
||||
Blob, Bytes32, Bytes48, KzgSettings, BYTES_PER_BLOB, BYTES_PER_COMMITMENT,
|
||||
BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF, FIELD_ELEMENTS_PER_BLOB,
|
||||
pub use rust_eth_kzg::constants::{
|
||||
BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_FIELD_ELEMENT, FIELD_ELEMENTS_PER_BLOB,
|
||||
};
|
||||
|
||||
pub const BYTES_PER_PROOF: usize = 48;
|
||||
|
||||
use crate::trusted_setup::load_trusted_setup;
|
||||
use rayon::prelude::*;
|
||||
pub use rust_eth_kzg::{
|
||||
@@ -25,13 +26,6 @@ pub use rust_eth_kzg::{
|
||||
};
|
||||
use tracing::{instrument, Span};
|
||||
|
||||
/// Disables the fixed-base multi-scalar multiplication optimization for computing
|
||||
/// cell KZG proofs, because `rust-eth-kzg` already handles the precomputation.
|
||||
///
|
||||
/// Details about `precompute` parameter can be found here:
|
||||
/// <https://github.com/ethereum/c-kzg-4844/pull/545/files>
|
||||
pub const NO_PRECOMPUTE: u64 = 0;
|
||||
|
||||
// Note: Both `NUMBER_OF_COLUMNS` and `CELLS_PER_EXT_BLOB` are preset values - however this
|
||||
// is a constant in the KZG library - be aware that overriding `NUMBER_OF_COLUMNS` will break KZG
|
||||
// operations.
|
||||
@@ -39,14 +33,15 @@ pub type CellsAndKzgProofs = ([Cell; CELLS_PER_EXT_BLOB], [KzgProof; CELLS_PER_E
|
||||
|
||||
pub type KzgBlobRef<'a> = &'a [u8; BYTES_PER_BLOB];
|
||||
|
||||
type Bytes32 = [u8; 32];
|
||||
type Bytes48 = [u8; 48];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// An error from initialising the trusted setup.
|
||||
TrustedSetupError(String),
|
||||
/// An error from the underlying kzg library.
|
||||
Kzg(c_kzg::Error),
|
||||
/// A prover/verifier error from the rust-eth-kzg library.
|
||||
PeerDASKZG(rust_eth_kzg::Error),
|
||||
/// An error from the rust-eth-kzg library.
|
||||
Kzg(rust_eth_kzg::Error),
|
||||
/// The kzg verification failed
|
||||
KzgVerificationFailed,
|
||||
/// Misc indexing error
|
||||
@@ -57,38 +52,29 @@ pub enum Error {
|
||||
DASContextUninitialized,
|
||||
}
|
||||
|
||||
impl From<c_kzg::Error> for Error {
|
||||
fn from(value: c_kzg::Error) -> Self {
|
||||
impl From<rust_eth_kzg::Error> for Error {
|
||||
fn from(value: rust_eth_kzg::Error) -> Self {
|
||||
Error::Kzg(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper over a kzg library that holds the trusted setup parameters.
|
||||
/// A wrapper over the rust-eth-kzg library that holds the trusted setup parameters.
|
||||
#[derive(Debug)]
|
||||
pub struct Kzg {
|
||||
trusted_setup: KzgSettings,
|
||||
context: DASContext,
|
||||
}
|
||||
|
||||
impl Kzg {
|
||||
pub fn new_from_trusted_setup_no_precomp(trusted_setup: &[u8]) -> Result<Self, Error> {
|
||||
let (ckzg_trusted_setup, rkzg_trusted_setup) = load_trusted_setup(trusted_setup)?;
|
||||
let rkzg_trusted_setup = load_trusted_setup(trusted_setup)?;
|
||||
let context = DASContext::new(&rkzg_trusted_setup, rust_eth_kzg::UsePrecomp::No);
|
||||
|
||||
Ok(Self {
|
||||
trusted_setup: KzgSettings::load_trusted_setup(
|
||||
&ckzg_trusted_setup.g1_monomial(),
|
||||
&ckzg_trusted_setup.g1_lagrange(),
|
||||
&ckzg_trusted_setup.g2_monomial(),
|
||||
NO_PRECOMPUTE,
|
||||
)?,
|
||||
context,
|
||||
})
|
||||
Ok(Self { context })
|
||||
}
|
||||
|
||||
/// Load the kzg trusted setup parameters from a vec of G1 and G2 points.
|
||||
pub fn new_from_trusted_setup(trusted_setup: &[u8]) -> Result<Self, Error> {
|
||||
let (ckzg_trusted_setup, rkzg_trusted_setup) = load_trusted_setup(trusted_setup)?;
|
||||
let rkzg_trusted_setup = load_trusted_setup(trusted_setup)?;
|
||||
|
||||
// It's not recommended to change the config parameter for precomputation as storage
|
||||
// grows exponentially, but the speedup is exponential - after a while the speedup
|
||||
@@ -100,15 +86,7 @@ impl Kzg {
|
||||
},
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
trusted_setup: KzgSettings::load_trusted_setup(
|
||||
&ckzg_trusted_setup.g1_monomial(),
|
||||
&ckzg_trusted_setup.g1_lagrange(),
|
||||
&ckzg_trusted_setup.g2_monomial(),
|
||||
NO_PRECOMPUTE,
|
||||
)?,
|
||||
context,
|
||||
})
|
||||
Ok(Self { context })
|
||||
}
|
||||
|
||||
fn context(&self) -> &DASContext {
|
||||
@@ -118,34 +96,35 @@ impl Kzg {
|
||||
/// Compute the kzg proof given a blob and its kzg commitment.
|
||||
pub fn compute_blob_kzg_proof(
|
||||
&self,
|
||||
blob: &Blob,
|
||||
blob: KzgBlobRef<'_>,
|
||||
kzg_commitment: KzgCommitment,
|
||||
) -> Result<KzgProof, Error> {
|
||||
self.trusted_setup
|
||||
.compute_blob_kzg_proof(blob, &kzg_commitment.into())
|
||||
.map(|proof| KzgProof(proof.to_bytes().into_inner()))
|
||||
.map_err(Into::into)
|
||||
let proof = self
|
||||
.context()
|
||||
.compute_blob_kzg_proof(blob, &kzg_commitment.0)
|
||||
.map_err(Error::Kzg)?;
|
||||
Ok(KzgProof(proof))
|
||||
}
|
||||
|
||||
/// Verify a kzg proof given the blob, kzg commitment and kzg proof.
|
||||
pub fn verify_blob_kzg_proof(
|
||||
&self,
|
||||
blob: &Blob,
|
||||
blob: KzgBlobRef<'_>,
|
||||
kzg_commitment: KzgCommitment,
|
||||
kzg_proof: KzgProof,
|
||||
) -> Result<(), Error> {
|
||||
if cfg!(feature = "fake_crypto") {
|
||||
return Ok(());
|
||||
}
|
||||
if !self.trusted_setup.verify_blob_kzg_proof(
|
||||
blob,
|
||||
&kzg_commitment.into(),
|
||||
&kzg_proof.into(),
|
||||
)? {
|
||||
Err(Error::KzgVerificationFailed)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
self.context()
|
||||
.verify_blob_kzg_proof(blob, &kzg_commitment.0, &kzg_proof.0)
|
||||
.map_err(|e| {
|
||||
if e.is_proof_invalid() {
|
||||
Error::KzgVerificationFailed
|
||||
} else {
|
||||
Error::Kzg(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Verify a batch of blob commitment proof triplets.
|
||||
@@ -154,52 +133,48 @@ impl Kzg {
|
||||
/// TODO(pawan): test performance against a parallelized rayon impl.
|
||||
pub fn verify_blob_kzg_proof_batch(
|
||||
&self,
|
||||
blobs: &[Blob],
|
||||
blobs: &[KzgBlobRef<'_>],
|
||||
kzg_commitments: &[KzgCommitment],
|
||||
kzg_proofs: &[KzgProof],
|
||||
) -> Result<(), Error> {
|
||||
if cfg!(feature = "fake_crypto") {
|
||||
return Ok(());
|
||||
}
|
||||
let commitments_bytes = kzg_commitments
|
||||
.iter()
|
||||
.map(|comm| Bytes48::from(*comm))
|
||||
.collect::<Vec<_>>();
|
||||
let blob_refs: Vec<&[u8; BYTES_PER_BLOB]> = blobs.to_vec();
|
||||
let commitment_refs: Vec<&[u8; 48]> = kzg_commitments.iter().map(|c| &c.0).collect();
|
||||
let proof_refs: Vec<&[u8; 48]> = kzg_proofs.iter().map(|p| &p.0).collect();
|
||||
|
||||
let proofs_bytes = kzg_proofs
|
||||
.iter()
|
||||
.map(|proof| Bytes48::from(*proof))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !self.trusted_setup.verify_blob_kzg_proof_batch(
|
||||
blobs,
|
||||
&commitments_bytes,
|
||||
&proofs_bytes,
|
||||
)? {
|
||||
Err(Error::KzgVerificationFailed)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
self.context()
|
||||
.verify_blob_kzg_proof_batch(blob_refs, commitment_refs, proof_refs)
|
||||
.map_err(|e| {
|
||||
if e.is_proof_invalid() {
|
||||
Error::KzgVerificationFailed
|
||||
} else {
|
||||
Error::Kzg(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts a blob to a kzg commitment.
|
||||
pub fn blob_to_kzg_commitment(&self, blob: &Blob) -> Result<KzgCommitment, Error> {
|
||||
self.trusted_setup
|
||||
pub fn blob_to_kzg_commitment(&self, blob: KzgBlobRef<'_>) -> Result<KzgCommitment, Error> {
|
||||
let commitment = self
|
||||
.context()
|
||||
.blob_to_kzg_commitment(blob)
|
||||
.map(|commitment| KzgCommitment(commitment.to_bytes().into_inner()))
|
||||
.map_err(Into::into)
|
||||
.map_err(Error::Kzg)?;
|
||||
Ok(KzgCommitment(commitment))
|
||||
}
|
||||
|
||||
/// Computes the kzg proof for a given `blob` and an evaluation point `z`
|
||||
pub fn compute_kzg_proof(
|
||||
&self,
|
||||
blob: &Blob,
|
||||
blob: KzgBlobRef<'_>,
|
||||
z: &Bytes32,
|
||||
) -> Result<(KzgProof, Bytes32), Error> {
|
||||
self.trusted_setup
|
||||
.compute_kzg_proof(blob, z)
|
||||
.map(|(proof, y)| (KzgProof(proof.to_bytes().into_inner()), y))
|
||||
.map_err(Into::into)
|
||||
let (proof, y) = self
|
||||
.context()
|
||||
.compute_kzg_proof(blob, *z)
|
||||
.map_err(Error::Kzg)?;
|
||||
Ok((KzgProof(proof), y))
|
||||
}
|
||||
|
||||
/// Verifies a `kzg_proof` for a `kzg_commitment` that evaluating a polynomial at `z` results in `y`
|
||||
@@ -213,9 +188,14 @@ impl Kzg {
|
||||
if cfg!(feature = "fake_crypto") {
|
||||
return Ok(true);
|
||||
}
|
||||
self.trusted_setup
|
||||
.verify_kzg_proof(&kzg_commitment.into(), z, y, &kzg_proof.into())
|
||||
.map_err(Into::into)
|
||||
match self
|
||||
.context()
|
||||
.verify_kzg_proof(&kzg_commitment.0, *z, *y, &kzg_proof.0)
|
||||
{
|
||||
Ok(()) => Ok(true),
|
||||
Err(e) if e.is_proof_invalid() => Ok(false),
|
||||
Err(e) => Err(Error::Kzg(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the cells and associated proofs for a given `blob`.
|
||||
@@ -226,18 +206,15 @@ impl Kzg {
|
||||
let (cells, proofs) = self
|
||||
.context()
|
||||
.compute_cells_and_kzg_proofs(blob)
|
||||
.map_err(Error::PeerDASKZG)?;
|
||||
.map_err(Error::Kzg)?;
|
||||
|
||||
// Convert the proof type to a c-kzg proof type
|
||||
let c_kzg_proof = proofs.map(KzgProof);
|
||||
Ok((cells, c_kzg_proof))
|
||||
let kzg_proofs = proofs.map(KzgProof);
|
||||
Ok((cells, kzg_proofs))
|
||||
}
|
||||
|
||||
/// Computes the cells for a given `blob`.
|
||||
pub fn compute_cells(&self, blob: KzgBlobRef<'_>) -> Result<[Cell; CELLS_PER_EXT_BLOB], Error> {
|
||||
self.context()
|
||||
.compute_cells(blob)
|
||||
.map_err(Error::PeerDASKZG)
|
||||
self.context().compute_cells(blob).map_err(Error::Kzg)
|
||||
}
|
||||
|
||||
/// Verifies a batch of cell-proof-commitment triplets.
|
||||
@@ -291,8 +268,8 @@ impl Kzg {
|
||||
|
||||
for (cell, proof, commitment) in &column_data {
|
||||
cells.push(*cell);
|
||||
proofs.push(proof.as_ref());
|
||||
commitments.push(commitment.as_ref());
|
||||
proofs.push(proof);
|
||||
commitments.push(commitment);
|
||||
}
|
||||
|
||||
// Create per-chunk tracing span for visualizing parallel processing.
|
||||
@@ -319,7 +296,7 @@ impl Kzg {
|
||||
Err(e) if e.is_proof_invalid() => {
|
||||
Err((Some(column_index), Error::KzgVerificationFailed))
|
||||
}
|
||||
Err(e) => Err((Some(column_index), Error::PeerDASKZG(e))),
|
||||
Err(e) => Err((Some(column_index), Error::Kzg(e))),
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<()>, (Option<u64>, Error)>>()?;
|
||||
@@ -335,10 +312,9 @@ impl Kzg {
|
||||
let (cells, proofs) = self
|
||||
.context()
|
||||
.recover_cells_and_kzg_proofs(cell_ids.to_vec(), cells.to_vec())
|
||||
.map_err(Error::PeerDASKZG)?;
|
||||
.map_err(Error::Kzg)?;
|
||||
|
||||
// Convert the proof type to a c-kzg proof type
|
||||
let c_kzg_proof = proofs.map(KzgProof);
|
||||
Ok((cells, c_kzg_proof))
|
||||
let kzg_proofs = proofs.map(KzgProof);
|
||||
Ok((cells, kzg_proofs))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ struct G1Point([u8; BYTES_PER_G1_POINT]);
|
||||
struct G2Point([u8; BYTES_PER_G2_POINT]);
|
||||
|
||||
/// Contains the trusted setup parameters that are required to instantiate a
|
||||
/// `c_kzg::KzgSettings` object.
|
||||
/// `rust_eth_kzg::TrustedSetup` object.
|
||||
///
|
||||
/// The serialize/deserialize implementations are written according to
|
||||
/// the format specified in the ethereum consensus specs trusted setup files.
|
||||
@@ -155,19 +155,9 @@ fn strip_prefix(s: &str) -> &str {
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads the trusted setup from JSON.
|
||||
///
|
||||
/// ## Note:
|
||||
/// Currently we load both c-kzg and rust-eth-kzg trusted setup structs, because c-kzg is still being
|
||||
/// used for 4844. Longer term we're planning to switch all KZG operations to the rust-eth-kzg
|
||||
/// crate, and we'll be able to maintain a single trusted setup struct.
|
||||
pub(crate) fn load_trusted_setup(
|
||||
trusted_setup: &[u8],
|
||||
) -> Result<(TrustedSetup, PeerDASTrustedSetup), Error> {
|
||||
let ckzg_trusted_setup: TrustedSetup = serde_json::from_slice(trusted_setup)
|
||||
.map_err(|e| Error::TrustedSetupError(format!("{e:?}")))?;
|
||||
/// Loads the trusted setup from JSON bytes into a `rust_eth_kzg::TrustedSetup`.
|
||||
pub(crate) fn load_trusted_setup(trusted_setup: &[u8]) -> Result<PeerDASTrustedSetup, Error> {
|
||||
let trusted_setup_json = std::str::from_utf8(trusted_setup)
|
||||
.map_err(|e| Error::TrustedSetupError(format!("{e:?}")))?;
|
||||
let rkzg_trusted_setup = PeerDASTrustedSetup::from_json(trusted_setup_json);
|
||||
Ok((ckzg_trusted_setup, rkzg_trusted_setup))
|
||||
Ok(PeerDASTrustedSetup::from_json(trusted_setup_json))
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ deny = [
|
||||
{ crate = "derivative", reason = "use educe or derive_more instead" },
|
||||
{ crate = "ark-ff", reason = "present in Cargo.lock but not needed by Lighthouse" },
|
||||
{ crate = "openssl", reason = "non-Rust dependency, use rustls instead" },
|
||||
{ crate = "c-kzg", reason = "non-Rust dependency, use rust_eth_kzg instead" },
|
||||
{ crate = "strum", deny-multiple-versions = true, reason = "takes a long time to compile" },
|
||||
{ crate = "reqwest", deny-multiple-versions = true, reason = "takes a long time to compile" },
|
||||
{ crate = "aes", deny-multiple-versions = true, reason = "takes a long time to compile" },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
use crate::case_result::compare_result;
|
||||
use kzg::{Bytes48, Error as KzgError};
|
||||
use kzg::Error as KzgError;
|
||||
use serde::Deserialize;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -47,8 +47,8 @@ impl<E: EthSpec> Case for KZGVerifyCellKZGProofBatch<E> {
|
||||
|
||||
let result =
|
||||
parse_input(&self.input).and_then(|(cells, proofs, cell_indices, commitments)| {
|
||||
let proofs: Vec<Bytes48> = proofs.iter().map(|&proof| proof.into()).collect();
|
||||
let commitments: Vec<Bytes48> = commitments.iter().map(|&c| c.into()).collect();
|
||||
let proofs = proofs.iter().map(|&proof| proof.0).collect::<Vec<_>>();
|
||||
let commitments = commitments.iter().map(|&c| c.0).collect::<Vec<_>>();
|
||||
let cells = cells.iter().map(|c| c.as_ref()).collect::<Vec<_>>();
|
||||
let kzg = get_kzg();
|
||||
match kzg.verify_cell_proof_batch(&cells, &proofs, cell_indices, &commitments) {
|
||||
|
||||
Reference in New Issue
Block a user