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]] [[package]]
name = "c-kzg" name = "c-kzg"
version = "0.1.0" 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 = [ dependencies = [
"hex", "hex",
"libc", "libc",

View File

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

View File

@ -3,7 +3,7 @@ use crate::*;
use safe_arith::SafeArith; use safe_arith::SafeArith;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use ssz_types::typenum::{ 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, U16777216, U2, U2048, U256, U32, U4, U4096, U512, U625, U64, U65536, U8, U8192,
}; };
use std::fmt::{self, Debug}; 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 MaxBlobsPerBlock: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type FieldElementsPerBlob: 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) * 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`. /// Must be set to `SyncCommitteeSize / SyncCommitteeSubnetCount`.
type SyncSubcommitteeSize: Unsigned + Clone + Sync + Send + Debug + PartialEq; 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 default_spec() -> ChainSpec;
fn spec_name() -> EthSpecId; fn spec_name() -> EthSpecId;
@ -293,7 +299,9 @@ impl EthSpec for MainnetEthSpec {
type MinGasLimit = U5000; type MinGasLimit = U5000;
type MaxExtraDataBytes = U32; type MaxExtraDataBytes = U32;
type MaxBlobsPerBlock = U16; // 2**4 = 16 type MaxBlobsPerBlock = U16; // 2**4 = 16
type BytesPerFieldElement = U32;
type FieldElementsPerBlob = U4096; type FieldElementsPerBlob = U4096;
type BytesPerBlob = U131072;
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
@ -347,7 +355,9 @@ impl EthSpec for MinimalEthSpec {
MaxExtraDataBytes, MaxExtraDataBytes,
MaxBlsToExecutionChanges, MaxBlsToExecutionChanges,
MaxBlobsPerBlock, MaxBlobsPerBlock,
FieldElementsPerBlob FieldElementsPerBlob,
BytesPerFieldElement,
BytesPerBlob
}); });
fn default_spec() -> ChainSpec { fn default_spec() -> ChainSpec {
@ -396,6 +406,8 @@ impl EthSpec for GnosisEthSpec {
type MaxWithdrawalsPerPayload = U16; type MaxWithdrawalsPerPayload = U16;
type MaxBlobsPerBlock = U16; // 2**4 = 16 type MaxBlobsPerBlock = U16; // 2**4 = 16
type FieldElementsPerBlob = U4096; type FieldElementsPerBlob = U4096;
type BytesPerFieldElement = U32;
type BytesPerBlob = U131072;
fn default_spec() -> ChainSpec { fn default_spec() -> ChainSpec {
ChainSpec::gnosis() ChainSpec::gnosis()

View File

@ -198,7 +198,7 @@ pub type Uint256 = ethereum_types::U256;
pub type Address = H160; pub type Address = H160;
pub type ForkVersion = [u8; 4]; pub type ForkVersion = [u8; 4];
pub type BLSFieldElement = Uint256; 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 type VersionedHash = Hash256;
pub use bls::{ pub use bls::{

View File

@ -19,4 +19,4 @@ eth2_serde_utils = "0.1.1"
hex = "0.4.2" hex = "0.4.2"
eth2_hashing = "0.3.0" eth2_hashing = "0.3.0"
ethereum-types = "0.12.1" 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_commitment;
mod kzg_proof; 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 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)] #[derive(Debug)]
pub enum Error { pub enum Error {
InvalidTrustedSetup(CKzgError), InvalidTrustedSetup(CKzgError),
InvalidKzgCommitment(CKzgError),
InvalidKzgProof(CKzgError),
KzgVerificationFailed(CKzgError),
EmptyBlobs,
EmptyKzgCommitments,
InvalidLength(String),
KzgProofComputationFailed(CKzgError),
} }
pub struct Kzg { pub struct Kzg {
_trusted_setup: KZGSettings, trusted_setup: KZGSettings,
} }
impl Kzg { impl Kzg {
pub fn new_from_file(file_path: PathBuf) -> Result<Self, Error> { pub fn new_from_file(file_path: PathBuf) -> Result<Self, Error> {
Ok(Self { Ok(Self {
_trusted_setup: KZGSettings::load_trusted_setup(file_path) trusted_setup: KZGSettings::load_trusted_setup(file_path)
.map_err(|e| Error::InvalidTrustedSetup(e))?, .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(),
)
}
} }