Add kzg crate functions

This commit is contained in:
Pawan Dhananjay 2022-11-22 01:21:10 +05:30 committed by realbigsean
parent 3288404ec1
commit e8b5f311aa
No known key found for this signature in database
GPG Key ID: B372B64D866BF8CC
6 changed files with 82 additions and 17 deletions

2
Cargo.lock generated
View File

@ -711,7 +711,7 @@ dependencies = [
[[package]]
name = "c-kzg"
version = "0.1.0"
source = "git+https://github.com/pawanjay176/c-kzg-4844?rev=f4b0c2a84e7a90fa2e0e4e04e5d777be146c6e94#f4b0c2a84e7a90fa2e0e4e04e5d777be146c6e94"
source = "git+https://github.com/pawanjay176/c-kzg-4844?rev=cb3745d26b728ee526dc41912e3e1bc6f17a5eeb#cb3745d26b728ee526dc41912e3e1bc6f17a5eeb"
dependencies = [
"hex",
"libc",

View File

@ -111,11 +111,11 @@ pub fn validate_blob_for_gossip<T: BeaconChainTypes>(
// Verify that blobs are properly formatted
//TODO: add the check while constructing a Blob type from bytes instead of after
for (i, blob) in blob_sidecar.blobs.iter().enumerate() {
if blob.iter().any(|b| *b >= *BLS_MODULUS) {
return Err(BlobError::BlobOutOfRange { blob_index: i });
}
}
// for (i, blob) in blob_sidecar.blobs.iter().enumerate() {
// if blob.iter().any(|b| *b >= *BLS_MODULUS) {
// return Err(BlobError::BlobOutOfRange { blob_index: i });
// }
// }
// Verify that the KZG proof is a valid G1 point
if PublicKey::deserialize(&blob_sidecar.kzg_aggregate_proof.0).is_err() {

View File

@ -3,7 +3,7 @@ use crate::*;
use safe_arith::SafeArith;
use serde_derive::{Deserialize, Serialize};
use ssz_types::typenum::{
bit::B0, UInt, Unsigned, U0, U1024, U1048576, U1073741824, U1099511627776, U128, U16,
bit::B0, UInt, Unsigned, U0, U1024, U1048576, U1073741824, U1099511627776, U128, U131072, U16,
U16777216, U2, U2048, U256, U32, U4, U4096, U512, U625, U64, U65536, U8, U8192,
};
use std::fmt::{self, Debug};
@ -105,6 +105,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
*/
type MaxBlobsPerBlock: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type FieldElementsPerBlob: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type BytesPerFieldElement: Unsigned + Clone + Sync + Send + Debug + PartialEq;
/*
* Derived values (set these CAREFULLY)
*/
@ -123,6 +124,11 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
/// Must be set to `SyncCommitteeSize / SyncCommitteeSubnetCount`.
type SyncSubcommitteeSize: Unsigned + Clone + Sync + Send + Debug + PartialEq;
/// The total length of a blob in bytes.
///
/// Must be set to `BytesPerFieldElement * FieldElementsPerBlob`.
type BytesPerBlob: Unsigned + Clone + Sync + Send + Debug + PartialEq;
fn default_spec() -> ChainSpec;
fn spec_name() -> EthSpecId;
@ -293,7 +299,9 @@ impl EthSpec for MainnetEthSpec {
type MinGasLimit = U5000;
type MaxExtraDataBytes = U32;
type MaxBlobsPerBlock = U16; // 2**4 = 16
type BytesPerFieldElement = U32;
type FieldElementsPerBlob = U4096;
type BytesPerBlob = U131072;
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
@ -347,7 +355,9 @@ impl EthSpec for MinimalEthSpec {
MaxExtraDataBytes,
MaxBlsToExecutionChanges,
MaxBlobsPerBlock,
FieldElementsPerBlob
FieldElementsPerBlob,
BytesPerFieldElement,
BytesPerBlob
});
fn default_spec() -> ChainSpec {
@ -396,6 +406,8 @@ impl EthSpec for GnosisEthSpec {
type MaxWithdrawalsPerPayload = U16;
type MaxBlobsPerBlock = U16; // 2**4 = 16
type FieldElementsPerBlob = U4096;
type BytesPerFieldElement = U32;
type BytesPerBlob = U131072;
fn default_spec() -> ChainSpec {
ChainSpec::gnosis()

View File

@ -198,7 +198,7 @@ pub type Uint256 = ethereum_types::U256;
pub type Address = H160;
pub type ForkVersion = [u8; 4];
pub type BLSFieldElement = Uint256;
pub type Blob<T> = FixedVector<BLSFieldElement, <T as EthSpec>::FieldElementsPerBlob>;
pub type Blob<T> = FixedVector<u8, <T as EthSpec>::BytesPerBlob>;
pub type VersionedHash = Hash256;
pub use bls::{

View File

@ -19,4 +19,4 @@ eth2_serde_utils = "0.1.1"
hex = "0.4.2"
eth2_hashing = "0.3.0"
ethereum-types = "0.12.1"
c-kzg = {git = "https://github.com/pawanjay176/c-kzg-4844", rev = "f4b0c2a84e7a90fa2e0e4e04e5d777be146c6e94" }
c-kzg = {git = "https://github.com/pawanjay176/c-kzg-4844", rev = "cb3745d26b728ee526dc41912e3e1bc6f17a5eeb" }

View File

@ -1,30 +1,83 @@
mod kzg_commitment;
mod kzg_proof;
pub use crate::{kzg_commitment::KzgCommitment, kzg_proof::KzgProof};
use c_kzg::{Error as CKzgError, KZGSettings, BYTES_PER_FIELD_ELEMENT, FIELD_ELEMENTS_PER_BLOB};
use std::path::PathBuf;
use c_kzg::{Error as CKzgError, KZGSettings};
const BYTES_PER_BLOB: usize = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT;
pub use crate::{kzg_commitment::KzgCommitment, kzg_proof::KzgProof};
/// 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];
#[derive(Debug)]
pub enum Error {
InvalidTrustedSetup(CKzgError),
InvalidKzgCommitment(CKzgError),
InvalidKzgProof(CKzgError),
KzgVerificationFailed(CKzgError),
EmptyBlobs,
EmptyKzgCommitments,
InvalidLength(String),
KzgProofComputationFailed(CKzgError),
}
pub struct Kzg {
_trusted_setup: KZGSettings,
trusted_setup: KZGSettings,
}
impl Kzg {
pub fn new_from_file(file_path: PathBuf) -> Result<Self, Error> {
Ok(Self {
_trusted_setup: KZGSettings::load_trusted_setup(file_path)
.map_err(|e| Error::InvalidTrustedSetup(e))?,
trusted_setup: KZGSettings::load_trusted_setup(file_path)
.map_err(Error::InvalidTrustedSetup)?,
})
}
pub fn verify_aggregate_kzg_proof() {}
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 blob_to_kzg_commitment() {}
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)
}
pub fn blob_to_kzg_commitment(&self, blob: Blob) -> KzgCommitment {
KzgCommitment(
c_kzg::KZGCommitment::blob_to_kzg_commitment(blob, &self.trusted_setup).to_bytes(),
)
}
}