From 2cfcb5120777b6d43d08eb883105afff3599f941 Mon Sep 17 00:00:00 2001 From: Pawan Dhananjay Date: Wed, 13 Sep 2023 19:14:30 -0700 Subject: [PATCH] Blob references in ckzg (#4723) * Move to using references in ckzg functions * cleanup TrustedSetup a bit * Remove BYTES_PER_FIELD_ELEMENT from KzgPreset --- Cargo.lock | 32 +++++++--- beacon_node/beacon_chain/src/kzg_utils.rs | 10 ++-- consensus/types/src/blob_sidecar.rs | 8 +-- crypto/kzg/Cargo.toml | 4 +- crypto/kzg/src/lib.rs | 71 ++++++++++++----------- crypto/kzg/src/trusted_setup.rs | 20 +------ 6 files changed, 72 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce7b930bd..f0f5d1d11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -749,16 +749,18 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.64.0" -source = "git+https://github.com/rust-lang/rust-bindgen?rev=0de11f0a521611ac8738b7b01d19dddaf3899e66#0de11f0a521611ac8738b7b01d19dddaf3899e66" +version = "0.66.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.3.3", "cexpr", "clang-sys", "lazy_static", "lazycell", "log", "peeking_take_while", + "prettyplease", "proc-macro2", "quote", "regex", @@ -983,9 +985,10 @@ dependencies = [ [[package]] name = "c-kzg" version = "0.1.0" -source = "git+https://github.com/ethereum//c-kzg-4844?rev=fa3c62989527073fdce8b2138bb27a52bb2407c5#fa3c62989527073fdce8b2138bb27a52bb2407c5" +source = "git+https://github.com/ethereum//c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d#f5f6f863d475847876a2bd5ee252058d37c3a15d" dependencies = [ - "bindgen 0.64.0", + "bindgen 0.66.1", + "blst", "cc", "glob", "hex", @@ -996,9 +999,10 @@ dependencies = [ [[package]] name = "c-kzg" version = "0.1.0" -source = "git+https://github.com/ethereum/c-kzg-4844?rev=fa3c62989527073fdce8b2138bb27a52bb2407c5#fa3c62989527073fdce8b2138bb27a52bb2407c5" +source = "git+https://github.com/ethereum/c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d#f5f6f863d475847876a2bd5ee252058d37c3a15d" dependencies = [ - "bindgen 0.64.0", + "bindgen 0.66.1", + "blst", "cc", "glob", "hex", @@ -4046,8 +4050,8 @@ name = "kzg" version = "0.1.0" dependencies = [ "arbitrary", - "c-kzg 0.1.0 (git+https://github.com/ethereum//c-kzg-4844?rev=fa3c62989527073fdce8b2138bb27a52bb2407c5)", - "c-kzg 0.1.0 (git+https://github.com/ethereum/c-kzg-4844?rev=fa3c62989527073fdce8b2138bb27a52bb2407c5)", + "c-kzg 0.1.0 (git+https://github.com/ethereum//c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d)", + "c-kzg 0.1.0 (git+https://github.com/ethereum/c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d)", "derivative", "ethereum_hashing", "ethereum_serde_utils", @@ -6154,6 +6158,16 @@ dependencies = [ "sensitive_url", ] +[[package]] +name = "prettyplease" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" +dependencies = [ + "proc-macro2", + "syn 2.0.28", +] + [[package]] name = "primeorder" version = "0.13.2" diff --git a/beacon_node/beacon_chain/src/kzg_utils.rs b/beacon_node/beacon_chain/src/kzg_utils.rs index 8898ab83b..144e21367 100644 --- a/beacon_node/beacon_chain/src/kzg_utils.rs +++ b/beacon_node/beacon_chain/src/kzg_utils.rs @@ -17,7 +17,7 @@ pub fn validate_blob( kzg_proof: KzgProof, ) -> Result { kzg.verify_blob_kzg_proof( - ssz_blob_to_crypto_blob::(&blob)?, + &ssz_blob_to_crypto_blob::(&blob)?, kzg_commitment, kzg_proof, ) @@ -45,7 +45,7 @@ pub fn compute_blob_kzg_proof( kzg_commitment: KzgCommitment, ) -> Result { // Avoid this blob clone - kzg.compute_blob_kzg_proof(ssz_blob_to_crypto_blob::(blob)?, kzg_commitment) + kzg.compute_blob_kzg_proof(&ssz_blob_to_crypto_blob::(blob)?, kzg_commitment) } /// Compute the kzg commitment for a given blob. @@ -53,7 +53,7 @@ pub fn blob_to_kzg_commitment( kzg: &Kzg, blob: &Blob, ) -> Result { - kzg.blob_to_kzg_commitment(ssz_blob_to_crypto_blob::(blob)?) + kzg.blob_to_kzg_commitment(&ssz_blob_to_crypto_blob::(blob)?) } /// Compute the kzg proof for a given blob and an evaluation point z. @@ -63,7 +63,7 @@ pub fn compute_kzg_proof( z: Hash256, ) -> Result<(KzgProof, Hash256), KzgError> { let z = z.0.into(); - kzg.compute_kzg_proof(ssz_blob_to_crypto_blob::(blob)?, z) + kzg.compute_kzg_proof(&ssz_blob_to_crypto_blob::(blob)?, &z) .map(|(proof, z)| (proof, Hash256::from_slice(&z.to_vec()))) } @@ -75,5 +75,5 @@ pub fn verify_kzg_proof( z: Hash256, y: Hash256, ) -> Result { - kzg.verify_kzg_proof(kzg_commitment, z.0.into(), y.0.into(), kzg_proof) + kzg.verify_kzg_proof(kzg_commitment, &z.0.into(), &y.0.into(), kzg_proof) } diff --git a/consensus/types/src/blob_sidecar.rs b/consensus/types/src/blob_sidecar.rs index b6eef688b..97233530f 100644 --- a/consensus/types/src/blob_sidecar.rs +++ b/consensus/types/src/blob_sidecar.rs @@ -1,7 +1,7 @@ use crate::test_utils::TestRandom; use crate::{Blob, EthSpec, Hash256, SignedRoot, Slot}; use derivative::Derivative; -use kzg::{Kzg, KzgCommitment, KzgPreset, KzgProof}; +use kzg::{Kzg, KzgCommitment, KzgPreset, KzgProof, BYTES_PER_FIELD_ELEMENT}; use rand::Rng; use serde_derive::{Deserialize, Serialize}; use ssz::Encode; @@ -136,7 +136,7 @@ impl BlobSidecar { // each field element contained in the blob is < BLS_MODULUS for i in 0..T::Kzg::FIELD_ELEMENTS_PER_BLOB { let Some(byte) = blob_bytes.get_mut( - i.checked_mul(T::Kzg::BYTES_PER_FIELD_ELEMENT) + i.checked_mul(BYTES_PER_FIELD_ELEMENT) .ok_or("overflow".to_string())?, ) else { return Err(format!("blob byte index out of bounds: {:?}", i)); @@ -149,11 +149,11 @@ impl BlobSidecar { let kzg_blob = T::blob_from_bytes(&blob).unwrap(); let commitment = kzg - .blob_to_kzg_commitment(kzg_blob.clone()) + .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 { diff --git a/crypto/kzg/Cargo.toml b/crypto/kzg/Cargo.toml index e2f65b799..b1e933795 100644 --- a/crypto/kzg/Cargo.toml +++ b/crypto/kzg/Cargo.toml @@ -16,8 +16,8 @@ serde_derive = "1.0.116" ethereum_serde_utils = "0.5.0" hex = "0.4.2" ethereum_hashing = "1.0.0-beta.2" -c-kzg = { git = "https://github.com/ethereum/c-kzg-4844", rev = "fa3c62989527073fdce8b2138bb27a52bb2407c5" , features = ["mainnet-spec"]} -c_kzg_min = { package = "c-kzg", git = "https://github.com/ethereum//c-kzg-4844", rev = "fa3c62989527073fdce8b2138bb27a52bb2407c5", features = ["minimal-spec"], optional = true } +c-kzg = { git = "https://github.com/ethereum/c-kzg-4844", rev = "f5f6f863d475847876a2bd5ee252058d37c3a15d" , features = ["mainnet-spec", "serde"]} +c_kzg_min = { package = "c-kzg", git = "https://github.com/ethereum//c-kzg-4844", rev = "f5f6f863d475847876a2bd5ee252058d37c3a15d", features = ["minimal-spec", "serde"], optional = true } arbitrary = { version = "1.0", features = ["derive"] } [features] diff --git a/crypto/kzg/src/lib.rs b/crypto/kzg/src/lib.rs index dc0883e4d..d7870c15b 100644 --- a/crypto/kzg/src/lib.rs +++ b/crypto/kzg/src/lib.rs @@ -8,7 +8,7 @@ use std::ops::Deref; use std::str::FromStr; pub use crate::{kzg_commitment::KzgCommitment, kzg_proof::KzgProof, trusted_setup::TrustedSetup}; -pub use c_kzg::{Bytes32, Bytes48, BYTES_PER_COMMITMENT, BYTES_PER_PROOF}; +pub use c_kzg::{Bytes32, Bytes48, BYTES_PER_COMMITMENT, BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF}; #[derive(Debug)] pub enum Error { @@ -24,6 +24,8 @@ pub enum Error { pub enum CryptoError { CKzg(c_kzg::Error), CKzgMin(c_kzg_min::Error), + /// Trusted setup is for the incorrect kzg preset. + InconsistentTrustedSetup, } impl From for CryptoError { @@ -69,7 +71,6 @@ pub trait KzgPreset: type Error: Into; const BYTES_PER_BLOB: usize; - const BYTES_PER_FIELD_ELEMENT: usize; const FIELD_ELEMENTS_PER_BLOB: usize; fn spec_name() -> KzgPresetId; @@ -87,13 +88,13 @@ pub trait KzgPreset: fn load_trusted_setup(trusted_setup: TrustedSetup) -> Result; fn compute_blob_kzg_proof( - blob: Self::Blob, + blob: &Self::Blob, kzg_commitment: KzgCommitment, trusted_setup: &Self::KzgSettings, ) -> Result; fn verify_blob_kzg_proof( - blob: Self::Blob, + blob: &Self::Blob, kzg_commitment: KzgCommitment, kzg_proof: KzgProof, trusted_setup: &Self::KzgSettings, @@ -107,20 +108,20 @@ pub trait KzgPreset: ) -> Result; fn blob_to_kzg_commitment( - blob: Self::Blob, + blob: &Self::Blob, trusted_setup: &Self::KzgSettings, ) -> Result; fn compute_kzg_proof( - blob: Self::Blob, - z: Self::Bytes32, + blob: &Self::Blob, + z: &Self::Bytes32, trusted_setup: &Self::KzgSettings, ) -> Result<(KzgProof, Self::Bytes32), CryptoError>; fn verify_kzg_proof( kzg_commitment: KzgCommitment, - z: Self::Bytes32, - y: Self::Bytes32, + z: &Self::Bytes32, + y: &Self::Bytes32, kzg_proof: KzgProof, trusted_setup: &Self::KzgSettings, ) -> Result; @@ -136,7 +137,6 @@ macro_rules! implement_kzg_preset { type Error = $module_name::Error; const BYTES_PER_BLOB: usize = $module_name::BYTES_PER_BLOB; - const BYTES_PER_FIELD_ELEMENT: usize = $module_name::BYTES_PER_FIELD_ELEMENT; const FIELD_ELEMENTS_PER_BLOB: usize = $module_name::FIELD_ELEMENTS_PER_BLOB; fn spec_name() -> KzgPresetId { @@ -146,21 +146,24 @@ macro_rules! implement_kzg_preset { fn load_trusted_setup( trusted_setup: TrustedSetup, ) -> Result { + if trusted_setup.g1_len() != Self::FIELD_ELEMENTS_PER_BLOB { + return Err(CryptoError::InconsistentTrustedSetup); + } $module_name::KzgSettings::load_trusted_setup( - trusted_setup.g1_points(), - trusted_setup.g2_points(), + &trusted_setup.g1_points(), + &trusted_setup.g2_points(), ) .map_err(CryptoError::from) } fn compute_blob_kzg_proof( - blob: Self::Blob, + blob: &Self::Blob, kzg_commitment: KzgCommitment, trusted_setup: &Self::KzgSettings, ) -> Result { $module_name::KzgProof::compute_blob_kzg_proof( blob, - kzg_commitment.into(), + &kzg_commitment.into(), trusted_setup, ) .map(|proof| KzgProof(proof.to_bytes().into_inner())) @@ -168,15 +171,15 @@ macro_rules! implement_kzg_preset { } fn verify_blob_kzg_proof( - blob: Self::Blob, + blob: &Self::Blob, kzg_commitment: KzgCommitment, kzg_proof: KzgProof, trusted_setup: &Self::KzgSettings, ) -> Result { $module_name::KzgProof::verify_blob_kzg_proof( blob, - kzg_commitment.into(), - kzg_proof.into(), + &kzg_commitment.into(), + &kzg_proof.into(), trusted_setup, ) .map_err(CryptoError::from) @@ -198,7 +201,7 @@ macro_rules! implement_kzg_preset { } fn blob_to_kzg_commitment( - blob: Self::Blob, + blob: &Self::Blob, trusted_setup: &Self::KzgSettings, ) -> Result { $module_name::KzgCommitment::blob_to_kzg_commitment(blob, trusted_setup) @@ -207,8 +210,8 @@ macro_rules! implement_kzg_preset { } fn compute_kzg_proof( - blob: Self::Blob, - z: Self::Bytes32, + blob: &Self::Blob, + z: &Self::Bytes32, trusted_setup: &Self::KzgSettings, ) -> Result<(KzgProof, Self::Bytes32), CryptoError> { $module_name::KzgProof::compute_kzg_proof(blob, z, trusted_setup) @@ -218,16 +221,16 @@ macro_rules! implement_kzg_preset { fn verify_kzg_proof( kzg_commitment: KzgCommitment, - z: Self::Bytes32, - y: Self::Bytes32, + z: &Self::Bytes32, + y: &Self::Bytes32, kzg_proof: KzgProof, trusted_setup: &Self::KzgSettings, ) -> Result { $module_name::KzgProof::verify_kzg_proof( - kzg_commitment.into(), + &kzg_commitment.into(), z, y, - kzg_proof.into(), + &kzg_proof.into(), trusted_setup, ) .map_err(CryptoError::from) @@ -274,7 +277,7 @@ impl Kzg

{ /// Compute the kzg proof given a blob and its kzg commitment. pub fn compute_blob_kzg_proof( &self, - blob: P::Blob, + blob: &P::Blob, kzg_commitment: KzgCommitment, ) -> Result { P::compute_blob_kzg_proof(blob, kzg_commitment, &self.trusted_setup) @@ -284,7 +287,7 @@ impl Kzg

{ /// Verify a kzg proof given the blob, kzg commitment and kzg proof. pub fn verify_blob_kzg_proof( &self, - blob: P::Blob, + blob: &P::Blob, kzg_commitment: KzgCommitment, kzg_proof: KzgProof, ) -> Result { @@ -322,17 +325,17 @@ impl Kzg

{ } /// Converts a blob to a kzg commitment. - pub fn blob_to_kzg_commitment(&self, blob: P::Blob) -> Result { + pub fn blob_to_kzg_commitment(&self, blob: &P::Blob) -> Result { P::blob_to_kzg_commitment(blob, &self.trusted_setup).map_err(Error::InvalidBlob) } /// Computes the kzg proof for a given `blob` and an evaluation point `z` pub fn compute_kzg_proof( &self, - blob: P::Blob, - z: Bytes32, + blob: &P::Blob, + z: &Bytes32, ) -> Result<(KzgProof, Bytes32), Error> { - P::compute_kzg_proof(blob, P::bytes32_in(z), &self.trusted_setup) + P::compute_kzg_proof(blob, &P::bytes32_in(*z), &self.trusted_setup) .map_err(Error::KzgProofComputationFailed) .map(|(proof, y)| (proof, P::bytes32_out(y))) } @@ -341,14 +344,14 @@ impl Kzg

{ pub fn verify_kzg_proof( &self, kzg_commitment: KzgCommitment, - z: Bytes32, - y: Bytes32, + z: &Bytes32, + y: &Bytes32, kzg_proof: KzgProof, ) -> Result { P::verify_kzg_proof( kzg_commitment, - P::bytes32_in(z), - P::bytes32_in(y), + &P::bytes32_in(*z), + &P::bytes32_in(*y), kzg_proof, &self.trusted_setup, ) diff --git a/crypto/kzg/src/trusted_setup.rs b/crypto/kzg/src/trusted_setup.rs index 6abf3d30c..fbc4cfa4d 100644 --- a/crypto/kzg/src/trusted_setup.rs +++ b/crypto/kzg/src/trusted_setup.rs @@ -1,4 +1,4 @@ -use c_kzg::{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT, FIELD_ELEMENTS_PER_BLOB}; +use c_kzg::{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; use serde::{ de::{self, Deserializer, Visitor}, Deserialize, Serialize, @@ -22,7 +22,6 @@ struct G2Point([u8; BYTES_PER_G2_POINT]); #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct TrustedSetup { #[serde(rename = "setup_G1_lagrange")] - #[serde(deserialize_with = "deserialize_g1_points")] g1_points: Vec, #[serde(rename = "setup_G2")] g2_points: Vec, @@ -134,23 +133,6 @@ impl<'de> Deserialize<'de> for G2Point { } } -fn deserialize_g1_points<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let mut decoded: Vec = serde::de::Deserialize::deserialize(deserializer)?; - // FIELD_ELEMENTS_PER_BLOB is a compile time parameter that - // depends on whether lighthouse is compiled with minimal or mainnet features. - // Minimal and mainnet trusted setup parameters differ only by the - // number of G1 points they contain. - // - // Hence, we truncate the number of G1 points after deserialisation - // to ensure that we have the right number of g1 points in the - // trusted setup. - decoded.truncate(FIELD_ELEMENTS_PER_BLOB); - Ok(decoded) -} - fn strip_prefix(s: &str) -> &str { if let Some(stripped) = s.strip_prefix("0x") { stripped