Upgrade to v1.4.0-beta.3 (#4862)

## Issue Addressed

Makes lighthouse compliant with new kzg changes in https://github.com/ethereum/consensus-specs/releases/tag/v1.4.0-beta.3

## Proposed Changes

1. Adds new official trusted setup
2. Refactors kzg to match upstream changes in https://github.com/ethereum/c-kzg-4844/pull/377
3. Updates pre-generated `BlobBundle` to work with official trusted setup. ~~Using json here instead of ssz to account for different value of `MaxBlobCommitmentsPerBlock` in minimal and mainnet. By using json, we can just use one pre generated bundle for both minimal and mainnet. Size of 2 separate ssz bundles is approximately equal to one json bundle cc @jimmygchen~~ 
Dunno what I was doing, ssz works without any issues  
4. Stores trusted_setup as just bytes in eth2_network_config so that we don't have kzg dependency in that lib and in lcli. 


Co-authored-by: realbigsean <seananderson33@gmail.com>
Co-authored-by: realbigsean <seananderson33@GMAIL.com>
This commit is contained in:
Pawan Dhananjay 2023-10-21 13:49:27 +00:00
parent 074c4951fc
commit 6315a81260
36 changed files with 142 additions and 467 deletions

21
Cargo.lock generated
View File

@ -874,21 +874,7 @@ dependencies = [
[[package]] [[package]]
name = "c-kzg" name = "c-kzg"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/ethereum//c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d#f5f6f863d475847876a2bd5ee252058d37c3a15d" source = "git+https://github.com/ethereum/c-kzg-4844?rev=748283cced543c486145d5f3f38684becdfe3e1b#748283cced543c486145d5f3f38684becdfe3e1b"
dependencies = [
"bindgen 0.66.1",
"blst",
"cc",
"glob",
"hex",
"libc",
"serde",
]
[[package]]
name = "c-kzg"
version = "0.1.0"
source = "git+https://github.com/ethereum/c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d#f5f6f863d475847876a2bd5ee252058d37c3a15d"
dependencies = [ dependencies = [
"bindgen 0.66.1", "bindgen 0.66.1",
"blst", "blst",
@ -2203,7 +2189,6 @@ dependencies = [
"discv5", "discv5",
"eth2_config", "eth2_config",
"ethereum_ssz", "ethereum_ssz",
"kzg",
"logging", "logging",
"pretty_reqwest_error", "pretty_reqwest_error",
"reqwest", "reqwest",
@ -3844,8 +3829,7 @@ name = "kzg"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"arbitrary", "arbitrary",
"c-kzg 0.1.0 (git+https://github.com/ethereum//c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d)", "c-kzg",
"c-kzg 0.1.0 (git+https://github.com/ethereum/c-kzg-4844?rev=f5f6f863d475847876a2bd5ee252058d37c3a15d)",
"derivative", "derivative",
"ethereum_hashing", "ethereum_hashing",
"ethereum_serde_utils", "ethereum_serde_utils",
@ -3892,7 +3876,6 @@ dependencies = [
"ethereum_ssz", "ethereum_ssz",
"genesis", "genesis",
"int_to_bytes", "int_to_bytes",
"kzg",
"lighthouse_network", "lighthouse_network",
"lighthouse_version", "lighthouse_version",
"log", "log",

View File

@ -481,7 +481,7 @@ pub struct BeaconChain<T: BeaconChainTypes> {
/// they are collected and combined. /// they are collected and combined.
pub data_availability_checker: Arc<DataAvailabilityChecker<T>>, pub data_availability_checker: Arc<DataAvailabilityChecker<T>>,
/// The KZG trusted setup used by this chain. /// The KZG trusted setup used by this chain.
pub kzg: Option<Arc<Kzg<<T::EthSpec as EthSpec>::Kzg>>>, pub kzg: Option<Arc<Kzg>>,
} }
type BeaconBlockAndState<T, Payload> = ( type BeaconBlockAndState<T, Payload> = (

View File

@ -499,7 +499,7 @@ impl<T: EthSpec> KzgVerifiedBlob<T> {
/// Returns an error if the kzg verification check fails. /// Returns an error if the kzg verification check fails.
pub fn verify_kzg_for_blob<T: EthSpec>( pub fn verify_kzg_for_blob<T: EthSpec>(
blob: Arc<BlobSidecar<T>>, blob: Arc<BlobSidecar<T>>,
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
) -> Result<KzgVerifiedBlob<T>, AvailabilityCheckError> { ) -> Result<KzgVerifiedBlob<T>, AvailabilityCheckError> {
let _timer = crate::metrics::start_timer(&crate::metrics::KZG_VERIFICATION_SINGLE_TIMES); let _timer = crate::metrics::start_timer(&crate::metrics::KZG_VERIFICATION_SINGLE_TIMES);
if validate_blob::<T>(kzg, &blob.blob, blob.kzg_commitment, blob.kzg_proof) if validate_blob::<T>(kzg, &blob.blob, blob.kzg_commitment, blob.kzg_proof)
@ -518,7 +518,7 @@ pub fn verify_kzg_for_blob<T: EthSpec>(
/// in a loop since this function kzg verifies a list of blobs more efficiently. /// in a loop since this function kzg verifies a list of blobs more efficiently.
pub fn verify_kzg_for_blob_list<T: EthSpec>( pub fn verify_kzg_for_blob_list<T: EthSpec>(
blob_list: &BlobSidecarList<T>, blob_list: &BlobSidecarList<T>,
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
) -> Result<(), AvailabilityCheckError> { ) -> Result<(), AvailabilityCheckError> {
let _timer = crate::metrics::start_timer(&crate::metrics::KZG_VERIFICATION_BATCH_TIMES); let _timer = crate::metrics::start_timer(&crate::metrics::KZG_VERIFICATION_BATCH_TIMES);
let (blobs, (commitments, proofs)): (Vec<_>, (Vec<_>, Vec<_>)) = blob_list let (blobs, (commitments, proofs)): (Vec<_>, (Vec<_>, Vec<_>)) = blob_list

View File

@ -50,7 +50,7 @@ pub struct DataAvailabilityChecker<T: BeaconChainTypes> {
processing_cache: RwLock<ProcessingCache<T::EthSpec>>, processing_cache: RwLock<ProcessingCache<T::EthSpec>>,
availability_cache: Arc<OverflowLRUCache<T>>, availability_cache: Arc<OverflowLRUCache<T>>,
slot_clock: T::SlotClock, slot_clock: T::SlotClock,
kzg: Option<Arc<Kzg<<T::EthSpec as EthSpec>::Kzg>>>, kzg: Option<Arc<Kzg>>,
log: Logger, log: Logger,
spec: ChainSpec, spec: ChainSpec,
} }
@ -79,7 +79,7 @@ impl<T: EthSpec> Debug for Availability<T> {
impl<T: BeaconChainTypes> DataAvailabilityChecker<T> { impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
pub fn new( pub fn new(
slot_clock: T::SlotClock, slot_clock: T::SlotClock,
kzg: Option<Arc<Kzg<<T::EthSpec as EthSpec>::Kzg>>>, kzg: Option<Arc<Kzg>>,
store: BeaconStore<T>, store: BeaconStore<T>,
log: &Logger, log: &Logger,
spec: ChainSpec, spec: ChainSpec,

View File

@ -970,6 +970,7 @@ mod test {
) -> ( ) -> (
BeaconChainHarness<DiskHarnessType<E>>, BeaconChainHarness<DiskHarnessType<E>>,
Arc<OverflowLRUCache<T>>, Arc<OverflowLRUCache<T>>,
TempDir,
) )
where where
E: EthSpec, E: EthSpec,
@ -984,7 +985,7 @@ mod test {
OverflowLRUCache::<T>::new(capacity, test_store, spec.clone()) OverflowLRUCache::<T>::new(capacity, test_store, spec.clone())
.expect("should create cache"), .expect("should create cache"),
); );
(harness, cache) (harness, cache, chain_db_path)
} }
#[tokio::test] #[tokio::test]
@ -992,7 +993,7 @@ mod test {
type E = MinimalEthSpec; type E = MinimalEthSpec;
type T = DiskHarnessType<E>; type T = DiskHarnessType<E>;
let capacity = 4; let capacity = 4;
let (harness, cache) = setup_harness_and_cache::<E, T>(capacity).await; let (harness, cache, _path) = setup_harness_and_cache::<E, T>(capacity).await;
let (pending_block, blobs) = availability_pending_block(&harness).await; let (pending_block, blobs) = availability_pending_block(&harness).await;
let root = pending_block.import_data.block_root; let root = pending_block.import_data.block_root;
@ -1104,7 +1105,7 @@ mod test {
type E = MinimalEthSpec; type E = MinimalEthSpec;
type T = DiskHarnessType<E>; type T = DiskHarnessType<E>;
let capacity = 4; let capacity = 4;
let (harness, cache) = setup_harness_and_cache::<E, T>(capacity).await; let (harness, cache, _path) = setup_harness_and_cache::<E, T>(capacity).await;
let mut pending_blocks = VecDeque::new(); let mut pending_blocks = VecDeque::new();
let mut pending_blobs = VecDeque::new(); let mut pending_blobs = VecDeque::new();
@ -1255,7 +1256,7 @@ mod test {
type E = MinimalEthSpec; type E = MinimalEthSpec;
type T = DiskHarnessType<E>; type T = DiskHarnessType<E>;
let capacity = E::slots_per_epoch() as usize; let capacity = E::slots_per_epoch() as usize;
let (harness, cache) = setup_harness_and_cache::<E, T>(capacity).await; let (harness, cache, _path) = setup_harness_and_cache::<E, T>(capacity).await;
let n_epochs = 4; let n_epochs = 4;
let mut pending_blocks = VecDeque::new(); let mut pending_blocks = VecDeque::new();
@ -1395,7 +1396,7 @@ mod test {
type E = MinimalEthSpec; type E = MinimalEthSpec;
type T = DiskHarnessType<E>; type T = DiskHarnessType<E>;
let capacity = E::slots_per_epoch() as usize; let capacity = E::slots_per_epoch() as usize;
let (harness, cache) = setup_harness_and_cache::<E, T>(capacity).await; let (harness, cache, _path) = setup_harness_and_cache::<E, T>(capacity).await;
let n_epochs = 4; let n_epochs = 4;
let mut pending_blocks = VecDeque::new(); let mut pending_blocks = VecDeque::new();
@ -1573,7 +1574,7 @@ mod test {
type E = MinimalEthSpec; type E = MinimalEthSpec;
type T = DiskHarnessType<E>; type T = DiskHarnessType<E>;
let capacity = STATE_LRU_CAPACITY * 2; let capacity = STATE_LRU_CAPACITY * 2;
let (harness, cache) = setup_harness_and_cache::<E, T>(capacity).await; let (harness, cache, _path) = setup_harness_and_cache::<E, T>(capacity).await;
let mut pending_blocks = VecDeque::new(); let mut pending_blocks = VecDeque::new();
let mut states = Vec::new(); let mut states = Vec::new();

View File

@ -1,31 +1,26 @@
use kzg::{Error as KzgError, Kzg, KzgPreset}; use kzg::{Blob as KzgBlob, Error as KzgError, Kzg};
use types::{Blob, EthSpec, Hash256, KzgCommitment, KzgProof}; use types::{Blob, EthSpec, Hash256, KzgCommitment, KzgProof};
/// Converts a blob ssz List object to an array to be used with the kzg /// Converts a blob ssz List object to an array to be used with the kzg
/// crypto library. /// crypto library.
fn ssz_blob_to_crypto_blob<T: EthSpec>( fn ssz_blob_to_crypto_blob<T: EthSpec>(blob: &Blob<T>) -> Result<KzgBlob, KzgError> {
blob: &Blob<T>, KzgBlob::from_bytes(blob.as_ref())
) -> Result<<<T as EthSpec>::Kzg as KzgPreset>::Blob, KzgError> {
T::blob_from_bytes(blob.as_ref())
} }
/// Validate a single blob-commitment-proof triplet from a `BlobSidecar`. /// Validate a single blob-commitment-proof triplet from a `BlobSidecar`.
pub fn validate_blob<T: EthSpec>( pub fn validate_blob<T: EthSpec>(
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
blob: &Blob<T>, blob: &Blob<T>,
kzg_commitment: KzgCommitment, kzg_commitment: KzgCommitment,
kzg_proof: KzgProof, kzg_proof: KzgProof,
) -> Result<bool, KzgError> { ) -> Result<bool, KzgError> {
kzg.verify_blob_kzg_proof( let kzg_blob = ssz_blob_to_crypto_blob::<T>(blob)?;
&ssz_blob_to_crypto_blob::<T>(blob)?, kzg.verify_blob_kzg_proof(&kzg_blob, kzg_commitment, kzg_proof)
kzg_commitment,
kzg_proof,
)
} }
/// Validate a batch of blob-commitment-proof triplets from multiple `BlobSidecars`. /// Validate a batch of blob-commitment-proof triplets from multiple `BlobSidecars`.
pub fn validate_blobs<T: EthSpec>( pub fn validate_blobs<T: EthSpec>(
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
expected_kzg_commitments: &[KzgCommitment], expected_kzg_commitments: &[KzgCommitment],
blobs: Vec<&Blob<T>>, blobs: Vec<&Blob<T>>,
kzg_proofs: &[KzgProof], kzg_proofs: &[KzgProof],
@ -40,36 +35,38 @@ pub fn validate_blobs<T: EthSpec>(
/// Compute the kzg proof given an ssz blob and its kzg commitment. /// Compute the kzg proof given an ssz blob and its kzg commitment.
pub fn compute_blob_kzg_proof<T: EthSpec>( pub fn compute_blob_kzg_proof<T: EthSpec>(
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
blob: &Blob<T>, blob: &Blob<T>,
kzg_commitment: KzgCommitment, kzg_commitment: KzgCommitment,
) -> Result<KzgProof, KzgError> { ) -> Result<KzgProof, KzgError> {
// Avoid this blob clone let kzg_blob = ssz_blob_to_crypto_blob::<T>(blob)?;
kzg.compute_blob_kzg_proof(&ssz_blob_to_crypto_blob::<T>(blob)?, kzg_commitment) kzg.compute_blob_kzg_proof(&kzg_blob, kzg_commitment)
} }
/// Compute the kzg commitment for a given blob. /// Compute the kzg commitment for a given blob.
pub fn blob_to_kzg_commitment<T: EthSpec>( pub fn blob_to_kzg_commitment<T: EthSpec>(
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
blob: &Blob<T>, blob: &Blob<T>,
) -> Result<KzgCommitment, KzgError> { ) -> Result<KzgCommitment, KzgError> {
kzg.blob_to_kzg_commitment(&ssz_blob_to_crypto_blob::<T>(blob)?) let kzg_blob = ssz_blob_to_crypto_blob::<T>(blob)?;
kzg.blob_to_kzg_commitment(&kzg_blob)
} }
/// Compute the kzg proof for a given blob and an evaluation point z. /// Compute the kzg proof for a given blob and an evaluation point z.
pub fn compute_kzg_proof<T: EthSpec>( pub fn compute_kzg_proof<T: EthSpec>(
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
blob: &Blob<T>, blob: &Blob<T>,
z: Hash256, z: Hash256,
) -> Result<(KzgProof, Hash256), KzgError> { ) -> Result<(KzgProof, Hash256), KzgError> {
let z = z.0.into(); let z = z.0.into();
kzg.compute_kzg_proof(&ssz_blob_to_crypto_blob::<T>(blob)?, &z) let kzg_blob = ssz_blob_to_crypto_blob::<T>(blob)?;
kzg.compute_kzg_proof(&kzg_blob, &z)
.map(|(proof, z)| (proof, Hash256::from_slice(&z.to_vec()))) .map(|(proof, z)| (proof, Hash256::from_slice(&z.to_vec())))
} }
/// Verify a `kzg_proof` for a `kzg_commitment` that evaluating a polynomial at `z` results in `y` /// Verify a `kzg_proof` for a `kzg_commitment` that evaluating a polynomial at `z` results in `y`
pub fn verify_kzg_proof<T: EthSpec>( pub fn verify_kzg_proof<T: EthSpec>(
kzg: &Kzg<T::Kzg>, kzg: &Kzg,
kzg_commitment: KzgCommitment, kzg_commitment: KzgCommitment,
kzg_proof: KzgProof, kzg_proof: KzgProof,
z: Hash256, z: Hash256,

View File

@ -16,6 +16,7 @@ use crate::{
}; };
use bls::get_withdrawal_credentials; use bls::get_withdrawal_credentials;
use eth2::types::SignedBlockContentsTuple; use eth2::types::SignedBlockContentsTuple;
use eth2_network_config::TRUSTED_SETUP_BYTES;
use execution_layer::test_utils::generate_genesis_header; use execution_layer::test_utils::generate_genesis_header;
use execution_layer::{ use execution_layer::{
auth::JwtKey, auth::JwtKey,
@ -492,10 +493,9 @@ where
.validator_keypairs .validator_keypairs
.expect("cannot build without validator keypairs"); .expect("cannot build without validator keypairs");
let chain_config = self.chain_config.unwrap_or_default(); let chain_config = self.chain_config.unwrap_or_default();
let trusted_setup: TrustedSetup = let trusted_setup: TrustedSetup = serde_json::from_reader(TRUSTED_SETUP_BYTES)
serde_json::from_reader(eth2_network_config::get_trusted_setup::<E::Kzg>()) .map_err(|e| format!("Unable to read trusted setup file: {}", e))
.map_err(|e| format!("Unable to read trusted setup file: {}", e)) .unwrap();
.unwrap();
let mut builder = BeaconChainBuilder::new(self.eth_spec_instance) let mut builder = BeaconChainBuilder::new(self.eth_spec_instance)
.logger(log.clone()) .logger(log.clone())
@ -571,10 +571,9 @@ pub fn mock_execution_layer_from_parts<T: EthSpec>(
HARNESS_GENESIS_TIME + spec.seconds_per_slot * T::slots_per_epoch() * epoch.as_u64() HARNESS_GENESIS_TIME + spec.seconds_per_slot * T::slots_per_epoch() * epoch.as_u64()
}); });
let trusted_setup: TrustedSetup = let trusted_setup: TrustedSetup = serde_json::from_reader(TRUSTED_SETUP_BYTES)
serde_json::from_reader(eth2_network_config::get_trusted_setup::<T::Kzg>()) .map_err(|e| format!("Unable to read trusted setup file: {}", e))
.map_err(|e| format!("Unable to read trusted setup file: {}", e)) .expect("should have trusted setup");
.expect("should have trusted setup");
let kzg = Kzg::new_from_trusted_setup(trusted_setup).expect("should create kzg"); let kzg = Kzg::new_from_trusted_setup(trusted_setup).expect("should create kzg");
MockExecutionLayer::new( MockExecutionLayer::new(

View File

@ -14,7 +14,7 @@ use beacon_chain::{
migrate::MigratorConfig, BeaconChain, BeaconChainError, BeaconChainTypes, BeaconSnapshot, migrate::MigratorConfig, BeaconChain, BeaconChainError, BeaconChainTypes, BeaconSnapshot,
BlockError, ChainConfig, NotifyExecutionLayer, ServerSentEventHandler, WhenSlotSkipped, BlockError, ChainConfig, NotifyExecutionLayer, ServerSentEventHandler, WhenSlotSkipped,
}; };
use eth2_network_config::get_trusted_setup; use eth2_network_config::TRUSTED_SETUP_BYTES;
use kzg::TrustedSetup; use kzg::TrustedSetup;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use logging::test_logger; use logging::test_logger;
@ -2154,10 +2154,9 @@ async fn weak_subjectivity_sync_test(slots: Vec<Slot>, checkpoint_slot: Slot) {
let store = get_store(&temp2); let store = get_store(&temp2);
let spec = test_spec::<E>(); let spec = test_spec::<E>();
let seconds_per_slot = spec.seconds_per_slot; let seconds_per_slot = spec.seconds_per_slot;
let trusted_setup: TrustedSetup = let trusted_setup: TrustedSetup = serde_json::from_reader(TRUSTED_SETUP_BYTES)
serde_json::from_reader(get_trusted_setup::<<E as EthSpec>::Kzg>()) .map_err(|e| println!("Unable to read trusted setup file: {}", e))
.map_err(|e| println!("Unable to read trusted setup file: {}", e)) .unwrap();
.unwrap();
let mock = let mock =
mock_execution_layer_from_parts(&harness.spec, harness.runtime.task_executor.clone(), None); mock_execution_layer_from_parts(&harness.spec, harness.runtime.task_executor.clone(), None);

View File

@ -14,22 +14,21 @@ use kzg::{Kzg, KzgCommitment, KzgProof};
use parking_lot::Mutex; use parking_lot::Mutex;
use rand::{rngs::StdRng, Rng, SeedableRng}; use rand::{rngs::StdRng, Rng, SeedableRng};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ssz::Decode;
use ssz_types::VariableList; use ssz_types::VariableList;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use tree_hash_derive::TreeHash; use tree_hash_derive::TreeHash;
use types::{ use types::{
Blob, ChainSpec, EthSpec, EthSpecId, ExecutionBlockHash, ExecutionPayload, Blob, ChainSpec, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadCapella,
ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadHeader, ExecutionPayloadMerge, ExecutionPayloadDeneb, ExecutionPayloadHeader, ExecutionPayloadMerge, ForkName, Hash256,
ForkName, Hash256, Transaction, Transactions, Uint256, Transaction, Transactions, Uint256,
}; };
use super::DEFAULT_TERMINAL_BLOCK; use super::DEFAULT_TERMINAL_BLOCK;
use ssz::Decode;
const TEST_BLOB_BUNDLE_MAINNET: &[u8] = include_bytes!("fixtures/mainnet/test_blobs_bundle.ssz"); const TEST_BLOB_BUNDLE: &[u8] = include_bytes!("fixtures/mainnet/test_blobs_bundle.ssz");
const TEST_BLOB_BUNDLE_MINIMAL: &[u8] = include_bytes!("fixtures/minimal/test_blobs_bundle.ssz");
const GAS_LIMIT: u64 = 16384; const GAS_LIMIT: u64 = 16384;
const GAS_USED: u64 = GAS_LIMIT - 1; const GAS_USED: u64 = GAS_LIMIT - 1;
@ -137,7 +136,7 @@ pub struct ExecutionBlockGenerator<T: EthSpec> {
* deneb stuff * deneb stuff
*/ */
pub blobs_bundles: HashMap<PayloadId, BlobsBundle<T>>, pub blobs_bundles: HashMap<PayloadId, BlobsBundle<T>>,
pub kzg: Option<Arc<Kzg<T::Kzg>>>, pub kzg: Option<Arc<Kzg>>,
rng: Arc<Mutex<StdRng>>, rng: Arc<Mutex<StdRng>>,
} }
@ -154,7 +153,7 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
terminal_block_hash: ExecutionBlockHash, terminal_block_hash: ExecutionBlockHash,
shanghai_time: Option<u64>, shanghai_time: Option<u64>,
cancun_time: Option<u64>, cancun_time: Option<u64>,
kzg: Option<Kzg<T::Kzg>>, kzg: Option<Kzg>,
) -> Self { ) -> Self {
let mut gen = Self { let mut gen = Self {
head_block: <_>::default(), head_block: <_>::default(),
@ -649,20 +648,12 @@ impl<T: EthSpec> ExecutionBlockGenerator<T> {
} }
pub fn load_test_blobs_bundle<E: EthSpec>() -> Result<(KzgCommitment, KzgProof, Blob<E>), String> { pub fn load_test_blobs_bundle<E: EthSpec>() -> Result<(KzgCommitment, KzgProof, Blob<E>), String> {
let blob_bundle_bytes = match E::spec_name() { let BlobsBundle::<E> {
EthSpecId::Mainnet => TEST_BLOB_BUNDLE_MAINNET,
EthSpecId::Minimal => TEST_BLOB_BUNDLE_MINIMAL,
EthSpecId::Gnosis => {
return Err("Test blobs bundle not available for Gnosis preset".to_string())
}
};
let BlobsBundle {
commitments, commitments,
proofs, proofs,
blobs, blobs,
} = BlobsBundle::<E>::from_ssz_bytes(blob_bundle_bytes) } = BlobsBundle::from_ssz_bytes(TEST_BLOB_BUNDLE)
.map_err(|e| format!("Unable to decode SSZ: {:?}", e))?; .map_err(|e| format!("Unable to decode ssz: {:?}", e))?;
Ok(( Ok((
commitments commitments
@ -821,6 +812,7 @@ pub fn generate_pow_block(
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use eth2_network_config::TRUSTED_SETUP_BYTES;
use kzg::TrustedSetup; use kzg::TrustedSetup;
use types::{MainnetEthSpec, MinimalEthSpec}; use types::{MainnetEthSpec, MinimalEthSpec};
@ -898,18 +890,17 @@ mod test {
} }
fn validate_blob<E: EthSpec>() -> Result<bool, String> { fn validate_blob<E: EthSpec>() -> Result<bool, String> {
let kzg = load_kzg::<E>()?; let kzg = load_kzg()?;
let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle::<E>()?; let (kzg_commitment, kzg_proof, blob) = load_test_blobs_bundle::<E>()?;
let kzg_blob = E::blob_from_bytes(blob.as_ref()) let kzg_blob = kzg::Blob::from_bytes(blob.as_ref())
.map_err(|e| format!("Error converting blob to kzg blob: {e:?}"))?; .map_err(|e| format!("Error converting blob to kzg blob: {e:?}"))?;
kzg.verify_blob_kzg_proof(&kzg_blob, kzg_commitment, kzg_proof) kzg.verify_blob_kzg_proof(&kzg_blob, kzg_commitment, kzg_proof)
.map_err(|e| format!("Invalid blobs bundle: {e:?}")) .map_err(|e| format!("Invalid blobs bundle: {e:?}"))
} }
fn load_kzg<E: EthSpec>() -> Result<Kzg<E::Kzg>, String> { fn load_kzg() -> Result<Kzg, String> {
let trusted_setup: TrustedSetup = let trusted_setup: TrustedSetup = serde_json::from_reader(TRUSTED_SETUP_BYTES)
serde_json::from_reader(eth2_network_config::get_trusted_setup::<E::Kzg>()) .map_err(|e| format!("Unable to read trusted setup file: {e:?}"))?;
.map_err(|e| format!("Unable to read trusted setup file: {e:?}"))?;
Kzg::new_from_trusted_setup(trusted_setup) Kzg::new_from_trusted_setup(trusted_setup)
.map_err(|e| format!("Failed to load trusted setup: {e:?}")) .map_err(|e| format!("Failed to load trusted setup: {e:?}"))
} }

View File

@ -46,7 +46,7 @@ impl<T: EthSpec> MockExecutionLayer<T> {
builder_threshold: Option<u128>, builder_threshold: Option<u128>,
jwt_key: Option<JwtKey>, jwt_key: Option<JwtKey>,
spec: ChainSpec, spec: ChainSpec,
kzg: Option<Kzg<T::Kzg>>, kzg: Option<Kzg>,
) -> Self { ) -> Self {
let handle = executor.handle().unwrap(); let handle = executor.handle().unwrap();

View File

@ -107,7 +107,7 @@ impl<T: EthSpec> MockServer<T> {
pub fn new_with_config( pub fn new_with_config(
handle: &runtime::Handle, handle: &runtime::Handle,
config: MockExecutionConfig, config: MockExecutionConfig,
kzg: Option<Kzg<T::Kzg>>, kzg: Option<Kzg>,
) -> Self { ) -> Self {
let MockExecutionConfig { let MockExecutionConfig {
jwt_key, jwt_key,
@ -188,7 +188,7 @@ impl<T: EthSpec> MockServer<T> {
terminal_block_hash: ExecutionBlockHash, terminal_block_hash: ExecutionBlockHash,
shanghai_time: Option<u64>, shanghai_time: Option<u64>,
cancun_time: Option<u64>, cancun_time: Option<u64>,
kzg: Option<Kzg<T::Kzg>>, kzg: Option<Kzg>,
) -> Self { ) -> Self {
Self::new_with_config( Self::new_with_config(
handle, handle,

View File

@ -389,10 +389,12 @@ pub fn get_config<E: EthSpec>(
client_config.trusted_setup = context client_config.trusted_setup = context
.eth2_network_config .eth2_network_config
.as_ref() .as_ref()
.and_then(|config| config.kzg_trusted_setup.clone()); .and_then(|config| config.kzg_trusted_setup.as_ref())
.map(|trusted_setup_bytes| serde_json::from_slice(trusted_setup_bytes))
.transpose()
.map_err(|e| format!("Unable to read trusted setup file: {}", e))?;
// Override default trusted setup file if required // Override default trusted setup file if required
// TODO: consider removing this when we get closer to launch
if let Some(trusted_setup_file_path) = cli_args.value_of("trusted-setup-file-override") { if let Some(trusted_setup_file_path) = cli_args.value_of("trusted-setup-file-override") {
let file = std::fs::File::open(trusted_setup_file_path) let file = std::fs::File::open(trusted_setup_file_path)
.map_err(|e| format!("Failed to open trusted setup file: {}", e))?; .map_err(|e| format!("Failed to open trusted setup file: {}", e))?;

View File

@ -18,7 +18,6 @@ tokio = { workspace = true }
serde_yaml = { workspace = true } serde_yaml = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
types = { workspace = true } types = { workspace = true }
kzg = { workspace = true }
ethereum_ssz = { workspace = true } ethereum_ssz = { workspace = true }
eth2_config = { workspace = true } eth2_config = { workspace = true }
discv5 = { workspace = true } discv5 = { workspace = true }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,6 @@
use bytes::Bytes; use bytes::Bytes;
use discv5::enr::{CombinedKey, Enr}; use discv5::enr::{CombinedKey, Enr};
use eth2_config::{instantiate_hardcoded_nets, HardcodedNet}; use eth2_config::{instantiate_hardcoded_nets, HardcodedNet};
use kzg::{KzgPreset, KzgPresetId, TrustedSetup};
use pretty_reqwest_error::PrettyReqwestError; use pretty_reqwest_error::PrettyReqwestError;
use reqwest::{Client, Error}; use reqwest::{Client, Error};
use sensitive_url::SensitiveUrl; use sensitive_url::SensitiveUrl;
@ -49,35 +48,19 @@ pub const DEFAULT_HARDCODED_NETWORK: &str = "mainnet";
/// ///
/// This is done to ensure that testnets also inherit the high security and /// This is done to ensure that testnets also inherit the high security and
/// randomness of the mainnet kzg trusted setup ceremony. /// randomness of the mainnet kzg trusted setup ceremony.
const TRUSTED_SETUP: &[u8] = ///
include_bytes!("../built_in_network_configs/testing_trusted_setups.json"); /// Note: The trusted setup for both mainnet and minimal presets are the same.
pub const TRUSTED_SETUP_BYTES: &[u8] =
include_bytes!("../built_in_network_configs/trusted_setup.json");
const TRUSTED_SETUP_MINIMAL: &[u8] = /// Returns `Some(TrustedSetup)` if the deneb fork epoch is set and `None` otherwise.
include_bytes!("../built_in_network_configs/minimal_testing_trusted_setups.json"); ///
/// Returns an error if the trusted setup parsing failed.
pub fn get_trusted_setup<P: KzgPreset>() -> &'static [u8] { fn get_trusted_setup_from_config(config: &Config) -> Option<Vec<u8>> {
get_trusted_setup_from_id(P::spec_name())
}
pub fn get_trusted_setup_from_id(id: KzgPresetId) -> &'static [u8] {
match id {
KzgPresetId::Mainnet => TRUSTED_SETUP,
KzgPresetId::Minimal => TRUSTED_SETUP_MINIMAL,
}
}
fn get_trusted_setup_from_config(config: &Config) -> Result<Option<TrustedSetup>, String> {
config config
.deneb_fork_epoch .deneb_fork_epoch
.filter(|epoch| epoch.value != Epoch::max_value()) .filter(|epoch| epoch.value != Epoch::max_value())
.map(|_| { .map(|_| TRUSTED_SETUP_BYTES.to_vec())
let id = KzgPresetId::from_str(&config.preset_base)
.map_err(|e| format!("Unable to parse preset_base as KZG preset: {:?}", e))?;
let trusted_setup_bytes = get_trusted_setup_from_id(id);
serde_json::from_reader(trusted_setup_bytes)
.map_err(|e| format!("Unable to read trusted setup file: {}", e))
})
.transpose()
} }
/// A simple slice-or-vec enum to avoid cloning the beacon state bytes in the /// A simple slice-or-vec enum to avoid cloning the beacon state bytes in the
@ -121,7 +104,7 @@ pub struct Eth2NetworkConfig {
pub genesis_state_source: GenesisStateSource, pub genesis_state_source: GenesisStateSource,
pub genesis_state_bytes: Option<GenesisStateBytes>, pub genesis_state_bytes: Option<GenesisStateBytes>,
pub config: Config, pub config: Config,
pub kzg_trusted_setup: Option<TrustedSetup>, pub kzg_trusted_setup: Option<Vec<u8>>,
} }
impl Eth2NetworkConfig { impl Eth2NetworkConfig {
@ -139,7 +122,7 @@ impl Eth2NetworkConfig {
fn from_hardcoded_net(net: &HardcodedNet) -> Result<Self, String> { fn from_hardcoded_net(net: &HardcodedNet) -> Result<Self, String> {
let config: Config = serde_yaml::from_reader(net.config) let config: Config = serde_yaml::from_reader(net.config)
.map_err(|e| format!("Unable to parse yaml config: {:?}", e))?; .map_err(|e| format!("Unable to parse yaml config: {:?}", e))?;
let kzg_trusted_setup = get_trusted_setup_from_config(&config)?; let kzg_trusted_setup = get_trusted_setup_from_config(&config);
Ok(Self { Ok(Self {
deposit_contract_deploy_block: serde_yaml::from_reader(net.deploy_block) deposit_contract_deploy_block: serde_yaml::from_reader(net.deploy_block)
.map_err(|e| format!("Unable to parse deploy block: {:?}", e))?, .map_err(|e| format!("Unable to parse deploy block: {:?}", e))?,
@ -376,7 +359,7 @@ impl Eth2NetworkConfig {
(None, GenesisStateSource::Unknown) (None, GenesisStateSource::Unknown)
}; };
let kzg_trusted_setup = get_trusted_setup_from_config(&config)?; let kzg_trusted_setup = get_trusted_setup_from_config(&config);
Ok(Self { Ok(Self {
deposit_contract_deploy_block, deposit_contract_deploy_block,

View File

@ -3,7 +3,7 @@
# Misc # Misc
# --------------------------------------------------------------- # ---------------------------------------------------------------
# [customized] # [customized]
FIELD_ELEMENTS_PER_BLOB: 4 FIELD_ELEMENTS_PER_BLOB: 4096
# [customized] # [customized]
MAX_BLOB_COMMITMENTS_PER_BLOCK: 16 MAX_BLOB_COMMITMENTS_PER_BLOCK: 16
# `uint64(6)` # `uint64(6)`

View File

@ -1,7 +1,10 @@
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::{Blob, EthSpec, Hash256, SignedRoot, Slot}; use crate::{Blob, EthSpec, Hash256, SignedRoot, Slot};
use derivative::Derivative; use derivative::Derivative;
use kzg::{Kzg, KzgCommitment, KzgPreset, KzgProof, BYTES_PER_FIELD_ELEMENT}; use kzg::{
Blob as KzgBlob, Kzg, KzgCommitment, KzgProof, BYTES_PER_BLOB, BYTES_PER_FIELD_ELEMENT,
FIELD_ELEMENTS_PER_BLOB,
};
use rand::Rng; use rand::Rng;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ssz::Encode; use ssz::Encode;
@ -142,12 +145,12 @@ impl<T: EthSpec> BlobSidecar<T> {
} }
} }
pub fn random_valid<R: Rng>(rng: &mut R, kzg: &Kzg<T::Kzg>) -> Result<Self, String> { pub fn random_valid<R: Rng>(rng: &mut R, kzg: &Kzg) -> Result<Self, String> {
let mut blob_bytes = vec![0u8; T::Kzg::BYTES_PER_BLOB]; let mut blob_bytes = vec![0u8; BYTES_PER_BLOB];
rng.fill_bytes(&mut blob_bytes); rng.fill_bytes(&mut blob_bytes);
// Ensure that the blob is canonical by ensuring that // Ensure that the blob is canonical by ensuring that
// each field element contained in the blob is < BLS_MODULUS // each field element contained in the blob is < BLS_MODULUS
for i in 0..T::Kzg::FIELD_ELEMENTS_PER_BLOB { for i in 0..FIELD_ELEMENTS_PER_BLOB {
let Some(byte) = blob_bytes.get_mut( let Some(byte) = blob_bytes.get_mut(
i.checked_mul(BYTES_PER_FIELD_ELEMENT) i.checked_mul(BYTES_PER_FIELD_ELEMENT)
.ok_or("overflow".to_string())?, .ok_or("overflow".to_string())?,
@ -159,7 +162,7 @@ impl<T: EthSpec> BlobSidecar<T> {
let blob = Blob::<T>::new(blob_bytes) let blob = Blob::<T>::new(blob_bytes)
.map_err(|e| format!("error constructing random blob: {:?}", e))?; .map_err(|e| format!("error constructing random blob: {:?}", e))?;
let kzg_blob = T::blob_from_bytes(&blob).unwrap(); let kzg_blob = KzgBlob::from_bytes(&blob).unwrap();
let commitment = kzg let commitment = kzg
.blob_to_kzg_commitment(&kzg_blob) .blob_to_kzg_commitment(&kzg_blob)

View File

@ -1,6 +1,5 @@
use crate::*; use crate::*;
use kzg::{BlobTrait, KzgPreset, MainnetKzgPreset, MinimalKzgPreset};
use safe_arith::SafeArith; use safe_arith::SafeArith;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ssz_types::typenum::{ use ssz_types::typenum::{
@ -52,8 +51,6 @@ impl fmt::Display for EthSpecId {
pub trait EthSpec: pub trait EthSpec:
'static + Default + Sync + Send + Clone + Debug + PartialEq + Eq + for<'a> arbitrary::Arbitrary<'a> 'static + Default + Sync + Send + Clone + Debug + PartialEq + Eq + for<'a> arbitrary::Arbitrary<'a>
{ {
type Kzg: KzgPreset;
/* /*
* Constants * Constants
*/ */
@ -270,10 +267,6 @@ pub trait EthSpec:
Self::FieldElementsPerBlob::to_usize() Self::FieldElementsPerBlob::to_usize()
} }
fn blob_from_bytes(bytes: &[u8]) -> Result<<Self::Kzg as KzgPreset>::Blob, kzg::Error> {
<Self::Kzg as KzgPreset>::Blob::from_bytes(bytes)
}
/// Returns the `BYTES_PER_BLOB` constant for this specification. /// Returns the `BYTES_PER_BLOB` constant for this specification.
fn bytes_per_blob() -> usize { fn bytes_per_blob() -> usize {
Self::BytesPerBlob::to_usize() Self::BytesPerBlob::to_usize()
@ -293,8 +286,6 @@ macro_rules! params_from_eth_spec {
pub struct MainnetEthSpec; pub struct MainnetEthSpec;
impl EthSpec for MainnetEthSpec { impl EthSpec for MainnetEthSpec {
type Kzg = MainnetKzgPreset;
type JustificationBitsLength = U4; type JustificationBitsLength = U4;
type SubnetBitfieldLength = U64; type SubnetBitfieldLength = U64;
type MaxValidatorsPerCommittee = U2048; type MaxValidatorsPerCommittee = U2048;
@ -344,8 +335,6 @@ impl EthSpec for MainnetEthSpec {
pub struct MinimalEthSpec; pub struct MinimalEthSpec;
impl EthSpec for MinimalEthSpec { impl EthSpec for MinimalEthSpec {
type Kzg = MinimalKzgPreset;
type SlotsPerEpoch = U8; type SlotsPerEpoch = U8;
type EpochsPerEth1VotingPeriod = U4; type EpochsPerEth1VotingPeriod = U4;
type SlotsPerHistoricalRoot = U64; type SlotsPerHistoricalRoot = U64;
@ -356,8 +345,8 @@ impl EthSpec for MinimalEthSpec {
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
type SlotsPerEth1VotingPeriod = U32; // 4 epochs * 8 slots per epoch type SlotsPerEth1VotingPeriod = U32; // 4 epochs * 8 slots per epoch
type MaxWithdrawalsPerPayload = U4; type MaxWithdrawalsPerPayload = U4;
type FieldElementsPerBlob = U4; type FieldElementsPerBlob = U4096;
type BytesPerBlob = U128; type BytesPerBlob = U131072;
type MaxBlobCommitmentsPerBlock = U16; type MaxBlobCommitmentsPerBlock = U16;
params_from_eth_spec!(MainnetEthSpec { params_from_eth_spec!(MainnetEthSpec {
@ -398,8 +387,6 @@ impl EthSpec for MinimalEthSpec {
pub struct GnosisEthSpec; pub struct GnosisEthSpec;
impl EthSpec for GnosisEthSpec { impl EthSpec for GnosisEthSpec {
type Kzg = MainnetKzgPreset;
type JustificationBitsLength = U4; type JustificationBitsLength = U4;
type SubnetBitfieldLength = U64; type SubnetBitfieldLength = U64;
type MaxValidatorsPerCommittee = U2048; type MaxValidatorsPerCommittee = U2048;

View File

@ -16,10 +16,4 @@ serde = { workspace = true }
ethereum_serde_utils = { workspace = true } ethereum_serde_utils = { workspace = true }
hex = { workspace = true } hex = { workspace = true }
ethereum_hashing = { workspace = true } ethereum_hashing = { workspace = true }
c-kzg = { git = "https://github.com/ethereum/c-kzg-4844", rev = "f5f6f863d475847876a2bd5ee252058d37c3a15d" , features = ["mainnet-spec", "serde"]} c-kzg = { git = "https://github.com/ethereum/c-kzg-4844", rev = "748283cced543c486145d5f3f38684becdfe3e1b"}
c_kzg_min = { package = "c-kzg", git = "https://github.com/ethereum//c-kzg-4844", rev = "f5f6f863d475847876a2bd5ee252058d37c3a15d", features = ["minimal-spec", "serde"], optional = true }
[features]
# TODO(deneb): enabled by default for convenience, would need more cfg magic to disable
default = ["c_kzg_min"]
minimal-spec = ["c_kzg_min"]

View File

@ -34,12 +34,6 @@ impl From<KzgCommitment> for c_kzg::Bytes48 {
} }
} }
impl From<KzgCommitment> for c_kzg_min::Bytes48 {
fn from(value: KzgCommitment) -> Self {
value.0.into()
}
}
impl Display for KzgCommitment { impl Display for KzgCommitment {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", serde_utils::hex::encode(self.0)) write!(f, "{}", serde_utils::hex::encode(self.0))

View File

@ -17,12 +17,6 @@ impl From<KzgProof> for c_kzg::Bytes48 {
} }
} }
impl From<KzgProof> for c_kzg_min::Bytes48 {
fn from(value: KzgProof) -> Self {
value.0.into()
}
}
impl KzgProof { impl KzgProof {
/// Creates a valid proof using `G1_POINT_AT_INFINITY`. /// Creates a valid proof using `G1_POINT_AT_INFINITY`.
pub fn empty() -> Self { pub fn empty() -> Self {

View File

@ -2,297 +2,54 @@ mod kzg_commitment;
mod kzg_proof; mod kzg_proof;
mod trusted_setup; mod trusted_setup;
use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::Deref;
use std::str::FromStr;
pub use crate::{kzg_commitment::KzgCommitment, kzg_proof::KzgProof, trusted_setup::TrustedSetup}; pub use crate::{kzg_commitment::KzgCommitment, kzg_proof::KzgProof, trusted_setup::TrustedSetup};
pub use c_kzg::{Bytes32, Bytes48, BYTES_PER_COMMITMENT, BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF}; pub use c_kzg::{
Blob, Bytes32, Bytes48, Error, KzgSettings, BYTES_PER_BLOB, BYTES_PER_COMMITMENT,
#[derive(Debug)] BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF, FIELD_ELEMENTS_PER_BLOB,
pub enum Error { };
InvalidTrustedSetup(CryptoError),
InvalidKzgProof(CryptoError),
InvalidBytes(CryptoError),
KzgProofComputationFailed(CryptoError),
InvalidBlob(CryptoError),
InvalidBytesForBlob(CryptoError),
}
#[derive(Debug)]
pub enum CryptoError {
CKzg(c_kzg::Error),
CKzgMin(c_kzg_min::Error),
/// Trusted setup is for the incorrect kzg preset.
InconsistentTrustedSetup,
}
impl From<c_kzg::Error> for CryptoError {
fn from(e: c_kzg::Error) -> Self {
Self::CKzg(e)
}
}
impl From<c_kzg_min::Error> for CryptoError {
fn from(e: c_kzg_min::Error) -> Self {
Self::CKzgMin(e)
}
}
pub trait BlobTrait: Sized + Clone {
fn from_bytes(bytes: &[u8]) -> Result<Self, Error>;
}
pub enum KzgPresetId {
Mainnet,
Minimal,
}
impl FromStr for KzgPresetId {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"mainnet" => Ok(KzgPresetId::Mainnet),
"minimal" => Ok(KzgPresetId::Minimal),
_ => Err(format!("Unknown eth spec: {}", s)),
}
}
}
pub trait KzgPreset:
'static + Default + Sync + Send + Clone + Debug + PartialEq + Eq + for<'a> arbitrary::Arbitrary<'a>
{
type KzgSettings: Debug + Sync + Send;
type Blob: BlobTrait;
type Bytes32: From<[u8; 32]> + Deref<Target = [u8; 32]>;
type Bytes48: From<KzgCommitment> + From<KzgProof>;
type Error: Into<CryptoError>;
const BYTES_PER_BLOB: usize;
const FIELD_ELEMENTS_PER_BLOB: usize;
fn spec_name() -> KzgPresetId;
fn bytes32_in(bytes: Bytes32) -> Self::Bytes32 {
let bytes: [u8; 32] = *bytes;
Self::Bytes32::from(bytes)
}
fn bytes32_out(bytes: Self::Bytes32) -> Bytes32 {
let bytes: [u8; 32] = *bytes;
Bytes32::from(bytes)
}
fn load_trusted_setup(trusted_setup: TrustedSetup) -> Result<Self::KzgSettings, CryptoError>;
fn compute_blob_kzg_proof(
blob: &Self::Blob,
kzg_commitment: KzgCommitment,
trusted_setup: &Self::KzgSettings,
) -> Result<KzgProof, CryptoError>;
fn verify_blob_kzg_proof(
blob: &Self::Blob,
kzg_commitment: KzgCommitment,
kzg_proof: KzgProof,
trusted_setup: &Self::KzgSettings,
) -> Result<bool, CryptoError>;
fn verify_blob_kzg_proof_batch(
blobs: &[Self::Blob],
commitments_bytes: &[Self::Bytes48],
proofs_bytes: &[Self::Bytes48],
trusted_setup: &Self::KzgSettings,
) -> Result<bool, CryptoError>;
fn blob_to_kzg_commitment(
blob: &Self::Blob,
trusted_setup: &Self::KzgSettings,
) -> Result<KzgCommitment, CryptoError>;
fn compute_kzg_proof(
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,
kzg_proof: KzgProof,
trusted_setup: &Self::KzgSettings,
) -> Result<bool, CryptoError>;
}
macro_rules! implement_kzg_preset {
($preset_type:ident, $module_name:ident, $preset_id:ident) => {
impl KzgPreset for $preset_type {
type KzgSettings = $module_name::KzgSettings;
type Blob = $module_name::Blob;
type Bytes32 = $module_name::Bytes32;
type Bytes48 = $module_name::Bytes48;
type Error = $module_name::Error;
const BYTES_PER_BLOB: usize = $module_name::BYTES_PER_BLOB;
const FIELD_ELEMENTS_PER_BLOB: usize = $module_name::FIELD_ELEMENTS_PER_BLOB;
fn spec_name() -> KzgPresetId {
KzgPresetId::$preset_id
}
fn load_trusted_setup(
trusted_setup: TrustedSetup,
) -> Result<Self::KzgSettings, CryptoError> {
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(),
)
.map_err(CryptoError::from)
}
fn compute_blob_kzg_proof(
blob: &Self::Blob,
kzg_commitment: KzgCommitment,
trusted_setup: &Self::KzgSettings,
) -> Result<KzgProof, CryptoError> {
$module_name::KzgProof::compute_blob_kzg_proof(
blob,
&kzg_commitment.into(),
trusted_setup,
)
.map(|proof| KzgProof(proof.to_bytes().into_inner()))
.map_err(CryptoError::from)
}
fn verify_blob_kzg_proof(
blob: &Self::Blob,
kzg_commitment: KzgCommitment,
kzg_proof: KzgProof,
trusted_setup: &Self::KzgSettings,
) -> Result<bool, CryptoError> {
$module_name::KzgProof::verify_blob_kzg_proof(
blob,
&kzg_commitment.into(),
&kzg_proof.into(),
trusted_setup,
)
.map_err(CryptoError::from)
}
fn verify_blob_kzg_proof_batch(
blobs: &[Self::Blob],
commitments_bytes: &[Self::Bytes48],
proofs_bytes: &[Self::Bytes48],
trusted_setup: &Self::KzgSettings,
) -> Result<bool, CryptoError> {
$module_name::KzgProof::verify_blob_kzg_proof_batch(
blobs,
commitments_bytes,
proofs_bytes,
trusted_setup,
)
.map_err(CryptoError::from)
}
fn blob_to_kzg_commitment(
blob: &Self::Blob,
trusted_setup: &Self::KzgSettings,
) -> Result<KzgCommitment, CryptoError> {
$module_name::KzgCommitment::blob_to_kzg_commitment(blob, trusted_setup)
.map(|com| KzgCommitment(com.to_bytes().into_inner()))
.map_err(CryptoError::from)
}
fn compute_kzg_proof(
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)
.map(|(proof, y)| (KzgProof(proof.to_bytes().into_inner()), y))
.map_err(CryptoError::from)
}
fn verify_kzg_proof(
kzg_commitment: KzgCommitment,
z: &Self::Bytes32,
y: &Self::Bytes32,
kzg_proof: KzgProof,
trusted_setup: &Self::KzgSettings,
) -> Result<bool, CryptoError> {
$module_name::KzgProof::verify_kzg_proof(
&kzg_commitment.into(),
z,
y,
&kzg_proof.into(),
trusted_setup,
)
.map_err(CryptoError::from)
}
}
impl BlobTrait for $module_name::Blob {
fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
Self::from_bytes(bytes)
.map_err(CryptoError::from)
.map_err(Error::InvalidBlob)
}
}
};
}
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, arbitrary::Arbitrary)]
pub struct MainnetKzgPreset;
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, arbitrary::Arbitrary)]
pub struct MinimalKzgPreset;
implement_kzg_preset!(MainnetKzgPreset, c_kzg, Mainnet);
implement_kzg_preset!(MinimalKzgPreset, c_kzg_min, Minimal);
/// A wrapper over a kzg library that holds the trusted setup parameters. /// A wrapper over a kzg library that holds the trusted setup parameters.
#[derive(Debug)] #[derive(Debug)]
pub struct Kzg<P: KzgPreset> { pub struct Kzg {
trusted_setup: P::KzgSettings, trusted_setup: KzgSettings,
} }
impl<P: KzgPreset> Kzg<P> { impl Kzg {
/// Load the kzg trusted setup parameters from a vec of G1 and G2 points. /// Load the kzg trusted setup parameters from a vec of G1 and G2 points.
///
/// The number of G1 points should be equal to FIELD_ELEMENTS_PER_BLOB
/// Note: this number changes based on the preset values.
/// The number of G2 points should be equal to 65.
pub fn new_from_trusted_setup(trusted_setup: TrustedSetup) -> Result<Self, Error> { pub fn new_from_trusted_setup(trusted_setup: TrustedSetup) -> Result<Self, Error> {
Ok(Self { Ok(Self {
trusted_setup: P::load_trusted_setup(trusted_setup) trusted_setup: KzgSettings::load_trusted_setup(
.map_err(Error::InvalidTrustedSetup)?, &trusted_setup.g1_points(),
&trusted_setup.g2_points(),
)?,
}) })
} }
/// Compute the kzg proof given a blob and its kzg commitment. /// Compute the kzg proof given a blob and its kzg commitment.
pub fn compute_blob_kzg_proof( pub fn compute_blob_kzg_proof(
&self, &self,
blob: &P::Blob, blob: &Blob,
kzg_commitment: KzgCommitment, kzg_commitment: KzgCommitment,
) -> Result<KzgProof, Error> { ) -> Result<KzgProof, Error> {
P::compute_blob_kzg_proof(blob, kzg_commitment, &self.trusted_setup) c_kzg::KzgProof::compute_blob_kzg_proof(blob, &kzg_commitment.into(), &self.trusted_setup)
.map_err(Error::KzgProofComputationFailed) .map(|proof| KzgProof(proof.to_bytes().into_inner()))
} }
/// Verify a kzg proof given the blob, kzg commitment and kzg proof. /// Verify a kzg proof given the blob, kzg commitment and kzg proof.
pub fn verify_blob_kzg_proof( pub fn verify_blob_kzg_proof(
&self, &self,
blob: &P::Blob, blob: &Blob,
kzg_commitment: KzgCommitment, kzg_commitment: KzgCommitment,
kzg_proof: KzgProof, kzg_proof: KzgProof,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
P::verify_blob_kzg_proof(blob, kzg_commitment, kzg_proof, &self.trusted_setup) c_kzg::KzgProof::verify_blob_kzg_proof(
.map_err(Error::InvalidKzgProof) blob,
&kzg_commitment.into(),
&kzg_proof.into(),
&self.trusted_setup,
)
} }
/// Verify a batch of blob commitment proof triplets. /// Verify a batch of blob commitment proof triplets.
@ -301,43 +58,42 @@ impl<P: KzgPreset> Kzg<P> {
/// TODO(pawan): test performance against a parallelized rayon impl. /// TODO(pawan): test performance against a parallelized rayon impl.
pub fn verify_blob_kzg_proof_batch( pub fn verify_blob_kzg_proof_batch(
&self, &self,
blobs: &[P::Blob], blobs: &[Blob],
kzg_commitments: &[KzgCommitment], kzg_commitments: &[KzgCommitment],
kzg_proofs: &[KzgProof], kzg_proofs: &[KzgProof],
) -> Result<bool, Error> { ) -> Result<bool, Error> {
let commitments_bytes = kzg_commitments let commitments_bytes = kzg_commitments
.iter() .iter()
.map(|comm| P::Bytes48::from(*comm)) .map(|comm| Bytes48::from(*comm))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let proofs_bytes = kzg_proofs let proofs_bytes = kzg_proofs
.iter() .iter()
.map(|proof| P::Bytes48::from(*proof)) .map(|proof| Bytes48::from(*proof))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
P::verify_blob_kzg_proof_batch( c_kzg::KzgProof::verify_blob_kzg_proof_batch(
blobs, blobs,
&commitments_bytes, &commitments_bytes,
&proofs_bytes, &proofs_bytes,
&self.trusted_setup, &self.trusted_setup,
) )
.map_err(Error::InvalidKzgProof)
} }
/// Converts a blob to a kzg commitment. /// Converts a blob to a kzg commitment.
pub fn blob_to_kzg_commitment(&self, blob: &P::Blob) -> Result<KzgCommitment, Error> { pub fn blob_to_kzg_commitment(&self, blob: &Blob) -> Result<KzgCommitment, Error> {
P::blob_to_kzg_commitment(blob, &self.trusted_setup).map_err(Error::InvalidBlob) c_kzg::KzgCommitment::blob_to_kzg_commitment(blob, &self.trusted_setup)
.map(|commitment| KzgCommitment(commitment.to_bytes().into_inner()))
} }
/// Computes the kzg proof for a given `blob` and an evaluation point `z` /// Computes the kzg proof for a given `blob` and an evaluation point `z`
pub fn compute_kzg_proof( pub fn compute_kzg_proof(
&self, &self,
blob: &P::Blob, blob: &Blob,
z: &Bytes32, z: &Bytes32,
) -> Result<(KzgProof, Bytes32), Error> { ) -> Result<(KzgProof, Bytes32), Error> {
P::compute_kzg_proof(blob, &P::bytes32_in(*z), &self.trusted_setup) c_kzg::KzgProof::compute_kzg_proof(blob, z, &self.trusted_setup)
.map_err(Error::KzgProofComputationFailed) .map(|(proof, y)| (KzgProof(proof.to_bytes().into_inner()), y))
.map(|(proof, y)| (proof, P::bytes32_out(y)))
} }
/// Verifies a `kzg_proof` for a `kzg_commitment` that evaluating a polynomial at `z` results in `y` /// Verifies a `kzg_proof` for a `kzg_commitment` that evaluating a polynomial at `z` results in `y`
@ -348,13 +104,12 @@ impl<P: KzgPreset> Kzg<P> {
y: &Bytes32, y: &Bytes32,
kzg_proof: KzgProof, kzg_proof: KzgProof,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
P::verify_kzg_proof( c_kzg::KzgProof::verify_kzg_proof(
kzg_commitment, &kzg_commitment.into(),
&P::bytes32_in(*z), z,
&P::bytes32_in(*y), y,
kzg_proof, &kzg_proof.into(),
&self.trusted_setup, &self.trusted_setup,
) )
.map_err(Error::InvalidKzgProof)
} }
} }

View File

@ -18,12 +18,12 @@ struct G2Point([u8; BYTES_PER_G2_POINT]);
/// The serialize/deserialize implementations are written according to /// The serialize/deserialize implementations are written according to
/// the format specified in the the ethereum consensus specs trusted setup files. /// the format specified in the the ethereum consensus specs trusted setup files.
/// ///
/// See https://github.com/ethereum/consensus-specs/blob/dev/presets/mainnet/trusted_setups/testing_trusted_setups.json /// See https://github.com/ethereum/consensus-specs/blob/dev/presets/mainnet/trusted_setups/trusted_setup_4096.json
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TrustedSetup { pub struct TrustedSetup {
#[serde(rename = "setup_G1_lagrange")] #[serde(rename = "g1_lagrange")]
g1_points: Vec<G1Point>, g1_points: Vec<G1Point>,
#[serde(rename = "setup_G2")] #[serde(rename = "g2_monomial")]
g2_points: Vec<G2Point>, g2_points: Vec<G2Point>,
} }

View File

@ -12,7 +12,6 @@ jemalloc = ["malloc_utils/jemalloc"]
[dependencies] [dependencies]
bls = { workspace = true } bls = { workspace = true }
kzg = { workspace = true }
clap = { workspace = true } clap = { workspace = true }
log = { workspace = true } log = { workspace = true }
serde = { workspace = true } serde = { workspace = true }

View File

@ -1,12 +1,11 @@
use account_utils::eth2_keystore::keypair_from_secret; use account_utils::eth2_keystore::keypair_from_secret;
use clap::ArgMatches; use clap::ArgMatches;
use clap_utils::{parse_optional, parse_required, parse_ssz_optional}; use clap_utils::{parse_optional, parse_required, parse_ssz_optional};
use eth2_network_config::{get_trusted_setup, Eth2NetworkConfig, GenesisStateSource}; use eth2_network_config::{Eth2NetworkConfig, GenesisStateSource, TRUSTED_SETUP_BYTES};
use eth2_wallet::bip39::Seed; use eth2_wallet::bip39::Seed;
use eth2_wallet::bip39::{Language, Mnemonic}; use eth2_wallet::bip39::{Language, Mnemonic};
use eth2_wallet::{recover_validator_secret_from_mnemonic, KeyType}; use eth2_wallet::{recover_validator_secret_from_mnemonic, KeyType};
use ethereum_hashing::hash; use ethereum_hashing::hash;
use kzg::TrustedSetup;
use ssz::Decode; use ssz::Decode;
use ssz::Encode; use ssz::Encode;
use state_processing::process_activations; use state_processing::process_activations;
@ -199,10 +198,7 @@ pub fn run<T: EthSpec>(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Resul
let kzg_trusted_setup = if let Some(epoch) = spec.deneb_fork_epoch { let kzg_trusted_setup = if let Some(epoch) = spec.deneb_fork_epoch {
// Only load the trusted setup if the deneb fork epoch is set // Only load the trusted setup if the deneb fork epoch is set
if epoch != Epoch::max_value() { if epoch != Epoch::max_value() {
let trusted_setup: TrustedSetup = Some(TRUSTED_SETUP_BYTES.to_vec())
serde_json::from_reader(get_trusted_setup::<T::Kzg>())
.map_err(|e| format!("Unable to read trusted setup file: {}", e))?;
Some(trusted_setup)
} else { } else {
None None
} }

View File

@ -1,4 +1,4 @@
TESTS_TAG := v1.4.0-beta.2-hotfix TESTS_TAG := v1.4.0-beta.3
TESTS = general minimal mainnet TESTS = general minimal mainnet
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS)) TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))

View File

@ -32,7 +32,7 @@ impl<E: EthSpec> Case for KZGBlobToKZGCommitment<E> {
} }
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> { fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
let kzg = get_kzg::<E::Kzg>()?; let kzg = get_kzg()?;
let commitment = parse_blob::<E>(&self.input.blob).and_then(|blob| { let commitment = parse_blob::<E>(&self.input.blob).and_then(|blob| {
blob_to_kzg_commitment::<E>(&kzg, &blob).map_err(|e| { blob_to_kzg_commitment::<E>(&kzg, &blob).map_err(|e| {

View File

@ -39,7 +39,7 @@ impl<E: EthSpec> Case for KZGComputeBlobKZGProof<E> {
Ok((blob, commitment)) Ok((blob, commitment))
}; };
let kzg = get_kzg::<E::Kzg>()?; let kzg = get_kzg()?;
let proof = parse_input(&self.input).and_then(|(blob, commitment)| { let proof = parse_input(&self.input).and_then(|(blob, commitment)| {
compute_blob_kzg_proof::<E>(&kzg, &blob, commitment) compute_blob_kzg_proof::<E>(&kzg, &blob, commitment)
.map_err(|e| Error::InternalError(format!("Failed to compute kzg proof: {:?}", e))) .map_err(|e| Error::InternalError(format!("Failed to compute kzg proof: {:?}", e)))

View File

@ -46,7 +46,7 @@ impl<E: EthSpec> Case for KZGComputeKZGProof<E> {
Ok((blob, z)) Ok((blob, z))
}; };
let kzg = get_kzg::<E::Kzg>()?; let kzg = get_kzg()?;
let proof = parse_input(&self.input).and_then(|(blob, z)| { let proof = parse_input(&self.input).and_then(|(blob, z)| {
compute_kzg_proof::<E>(&kzg, &blob, z) compute_kzg_proof::<E>(&kzg, &blob, z)
.map_err(|e| Error::InternalError(format!("Failed to compute kzg proof: {:?}", e))) .map_err(|e| Error::InternalError(format!("Failed to compute kzg proof: {:?}", e)))

View File

@ -1,15 +1,15 @@
use super::*; use super::*;
use crate::case_result::compare_result; use crate::case_result::compare_result;
use beacon_chain::kzg_utils::validate_blob; use beacon_chain::kzg_utils::validate_blob;
use eth2_network_config::get_trusted_setup; use eth2_network_config::TRUSTED_SETUP_BYTES;
use kzg::{Kzg, KzgCommitment, KzgPreset, KzgProof, TrustedSetup}; use kzg::{Kzg, KzgCommitment, KzgProof, TrustedSetup};
use serde::Deserialize; use serde::Deserialize;
use std::convert::TryInto; use std::convert::TryInto;
use std::marker::PhantomData; use std::marker::PhantomData;
use types::Blob; use types::Blob;
pub fn get_kzg<P: KzgPreset>() -> Result<Kzg<P>, Error> { pub fn get_kzg() -> Result<Kzg, Error> {
let trusted_setup: TrustedSetup = serde_json::from_reader(get_trusted_setup::<P>()) let trusted_setup: TrustedSetup = serde_json::from_reader(TRUSTED_SETUP_BYTES)
.map_err(|e| Error::InternalError(format!("Failed to initialize kzg: {:?}", e)))?; .map_err(|e| Error::InternalError(format!("Failed to initialize kzg: {:?}", e)))?;
Kzg::new_from_trusted_setup(trusted_setup) Kzg::new_from_trusted_setup(trusted_setup)
.map_err(|e| Error::InternalError(format!("Failed to initialize kzg: {:?}", e))) .map_err(|e| Error::InternalError(format!("Failed to initialize kzg: {:?}", e)))
@ -89,7 +89,7 @@ impl<E: EthSpec> Case for KZGVerifyBlobKZGProof<E> {
Ok((blob, commitment, proof)) Ok((blob, commitment, proof))
}; };
let kzg = get_kzg::<E::Kzg>()?; let kzg = get_kzg()?;
let result = parse_input(&self.input).and_then(|(blob, commitment, proof)| { let result = parse_input(&self.input).and_then(|(blob, commitment, proof)| {
validate_blob::<E>(&kzg, &blob, commitment, proof) validate_blob::<E>(&kzg, &blob, commitment, proof)
.map_err(|e| Error::InternalError(format!("Failed to validate blob: {:?}", e))) .map_err(|e| Error::InternalError(format!("Failed to validate blob: {:?}", e)))

View File

@ -52,7 +52,7 @@ impl<E: EthSpec> Case for KZGVerifyBlobKZGProofBatch<E> {
Ok((commitments, blobs, proofs)) Ok((commitments, blobs, proofs))
}; };
let kzg = get_kzg::<E::Kzg>()?; let kzg = get_kzg()?;
let result = parse_input(&self.input).and_then(|(commitments, blobs, proofs)| { let result = parse_input(&self.input).and_then(|(commitments, blobs, proofs)| {
validate_blobs::<E>(&kzg, &commitments, blobs.iter().collect(), &proofs) validate_blobs::<E>(&kzg, &commitments, blobs.iter().collect(), &proofs)
.map_err(|e| Error::InternalError(format!("Failed to validate blobs: {:?}", e))) .map_err(|e| Error::InternalError(format!("Failed to validate blobs: {:?}", e)))

View File

@ -42,7 +42,7 @@ impl<E: EthSpec> Case for KZGVerifyKZGProof<E> {
Ok((commitment, z, y, proof)) Ok((commitment, z, y, proof))
}; };
let kzg = get_kzg::<E::Kzg>()?; let kzg = get_kzg()?;
let result = parse_input(&self.input).and_then(|(commitment, z, y, proof)| { let result = parse_input(&self.input).and_then(|(commitment, z, y, proof)| {
verify_kzg_proof::<E>(&kzg, commitment, proof, z, y) verify_kzg_proof::<E>(&kzg, commitment, proof, z, y)
.map_err(|e| Error::InternalError(format!("Failed to validate proof: {:?}", e))) .map_err(|e| Error::InternalError(format!("Failed to validate proof: {:?}", e)))