From 0adaea9c3085716df62388c1bc2687a78eefef56 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Mon, 10 Oct 2022 11:51:05 -0500 Subject: [PATCH 1/3] modify hash_to_bls_field --- specs/eip4844/validator.md | 90 +++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 50 deletions(-) diff --git a/specs/eip4844/validator.md b/specs/eip4844/validator.md index c29a7c414b..5c63af965a 100644 --- a/specs/eip4844/validator.md +++ b/specs/eip4844/validator.md @@ -8,25 +8,24 @@ -- [Introduction](#introduction) -- [Prerequisites](#prerequisites) -- [Custom types](#custom-types) -- [Containers](#containers) - - [`BlobsAndCommitments`](#blobsandcommitments) - - [`PolynomialAndCommitment`](#polynomialandcommitment) -- [Helpers](#helpers) - - [`is_data_available`](#is_data_available) - - [`hash_to_bls_field`](#hash_to_bls_field) - - [`compute_powers`](#compute_powers) - - [`compute_aggregated_poly_and_commitment`](#compute_aggregated_poly_and_commitment) - - [`validate_blobs_sidecar`](#validate_blobs_sidecar) - - [`compute_proof_from_blobs`](#compute_proof_from_blobs) - - [`get_blobs_and_kzg_commitments`](#get_blobs_and_kzg_commitments) -- [Beacon chain responsibilities](#beacon-chain-responsibilities) - - [Block proposal](#block-proposal) - - [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody) - - [Blob KZG commitments](#blob-kzg-commitments) - - [Beacon Block publishing time](#beacon-block-publishing-time) +- [EIP-4844 -- Honest Validator](#eip-4844----honest-validator) + - [Table of contents](#table-of-contents) + - [Introduction](#introduction) + - [Prerequisites](#prerequisites) + - [Custom types](#custom-types) + - [Helpers](#helpers) + - [`is_data_available`](#is_data_available) + - [`hash_to_bls_field`](#hash_to_bls_field) + - [`compute_powers`](#compute_powers) + - [`compute_aggregated_poly_and_commitment`](#compute_aggregated_poly_and_commitment) + - [`validate_blobs_sidecar`](#validate_blobs_sidecar) + - [`compute_proof_from_blobs`](#compute_proof_from_blobs) + - [`get_blobs_and_kzg_commitments`](#get_blobs_and_kzg_commitments) + - [Beacon chain responsibilities](#beacon-chain-responsibilities) + - [Block proposal](#block-proposal) + - [Constructing the `BeaconBlockBody`](#constructing-the-beaconblockbody) + - [Blob KZG commitments](#blob-kzg-commitments) + - [Beacon Block publishing time](#beacon-block-publishing-time) @@ -49,23 +48,6 @@ Please see related Beacon Chain doc before continuing and use them as a referenc | - | - | - | | `Polynomial` | `List[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB]` | a polynomial in evaluation form | -## Containers - -### `BlobsAndCommitments` - -```python -class BlobsAndCommitments(Container): - blobs: List[Blob, MAX_BLOBS_PER_BLOCK] - kzg_commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK] -``` - -### `PolynomialAndCommitment` - -```python -class PolynomialAndCommitment(Container): - polynomial: Polynomial - kzg_commitment: KZGCommitment -``` ## Helpers @@ -91,12 +73,25 @@ def is_data_available(slot: Slot, beacon_block_root: Root, blob_kzg_commitments: ### `hash_to_bls_field` ```python -def hash_to_bls_field(x: Container) -> BLSFieldElement: - """ - Compute 32-byte hash of serialized container and convert it to BLS field. - The output is not uniform over the BLS field. - """ - return bytes_to_bls_field(hash(ssz_serialize(x))) +def hash_to_bls_field(polys: List[Tuple[Polynomial | Blob]], comms: List[KZGCommitment]) -> BLSFieldElement: + """ + Compute 32-byte hash of serialised polynomials and commitments concatenated + This hash is then converted to a BLS field. + The output is not uniform over the BLS field. + """ + + bytes = [] + + # Append each polynomial + for poly in polys: + for serialised_evaluation in poly: + bytes.extend(serialised_evaluation) + + # Append serialised g1 points + for serialised_comm in comms: + bytes.extend(serialised_comm) + + return bytes_to_bls_field(hash(bytes)) ``` ### `compute_powers` @@ -123,7 +118,7 @@ def compute_aggregated_poly_and_commitment( Return the aggregated polynomial and aggregated KZG commitment. """ # Generate random linear combination challenges - r = hash_to_bls_field(BlobsAndCommitments(blobs=blobs, kzg_commitments=kzg_commitments)) + r = hash_to_bls_field(blobs, kzg_commitments) r_powers = compute_powers(r, len(kzg_commitments)) # Create aggregated polynomial in evaluation form @@ -154,9 +149,7 @@ def validate_blobs_sidecar(slot: Slot, ) # Generate challenge `x` and evaluate the aggregated polynomial at `x` - x = hash_to_bls_field( - PolynomialAndCommitment(polynomial=aggregated_poly, kzg_commitment=aggregated_poly_commitment) - ) + x = hash_to_bls_field([aggregated_poly], [aggregated_poly_commitment]) # Evaluate aggregated polynomial at `x` (evaluation function checks for div-by-zero) y = evaluate_polynomial_in_evaluation_form(aggregated_poly, x) @@ -170,10 +163,7 @@ def validate_blobs_sidecar(slot: Slot, def compute_proof_from_blobs(blobs: Sequence[BLSFieldElement]) -> KZGProof: commitments = [blob_to_kzg_commitment(blob) for blob in blobs] aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment(blobs, commitments) - x = hash_to_bls_field(PolynomialAndCommitment( - polynomial=aggregated_poly, - kzg_commitment=aggregated_poly_commitment, - )) + x = hash_to_bls_field([aggregated_poly],[aggregated_poly_commitment]) return compute_kzg_proof(aggregated_poly, x) ``` From 3e26558f20688f0a63a56c0f11c9c92595138891 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Mon, 10 Oct 2022 13:18:17 -0500 Subject: [PATCH 2/3] add higher level kzg functions --- specs/eip4844/validator.md | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/specs/eip4844/validator.md b/specs/eip4844/validator.md index 5c63af965a..03e5a8ff45 100644 --- a/specs/eip4844/validator.md +++ b/specs/eip4844/validator.md @@ -20,6 +20,8 @@ - [`compute_aggregated_poly_and_commitment`](#compute_aggregated_poly_and_commitment) - [`validate_blobs_sidecar`](#validate_blobs_sidecar) - [`compute_proof_from_blobs`](#compute_proof_from_blobs) + - [`compute_aggregrate_kzg_proof`](#compute_aggregrate_kzg_proof) + - [`verify_aggregrate_kzg_proof`](#verify_aggregrate_kzg_proof) - [`get_blobs_and_kzg_commitments`](#get_blobs_and_kzg_commitments) - [Beacon chain responsibilities](#beacon-chain-responsibilities) - [Block proposal](#block-proposal) @@ -143,6 +145,32 @@ def validate_blobs_sidecar(slot: Slot, kzg_aggregated_proof = blobs_sidecar.kzg_aggregated_proof assert len(expected_kzg_commitments) == len(blobs) + verify_aggregrate_kzg_proof(blobs, expected_kzg_commitments, kzg_aggregated_proof) +``` + +### `compute_proof_from_blobs` + +```python +def compute_proof_from_blobs(blobs: Sequence[BLSFieldElement]) -> KZGProof: + return compute_aggregrate_kzg_proof(blobs) +``` + + +### `compute_aggregrate_kzg_proof` + +```python +def compute_aggregrate_kzg_proof(blobs: Sequence[BLSFieldElement]) -> KZGProof: + commitments = [blob_to_kzg_commitment(blob) for blob in blobs] + aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment(blobs, commitments) + x = hash_to_bls_field([aggregated_poly],[aggregated_poly_commitment]) + return compute_kzg_proof(aggregated_poly, x) +``` + +### `verify_aggregrate_kzg_proof` + +```python +def verify_aggregrate_kzg_proof(blobs: Sequence[BLSFieldElement],expected_kzg_commitments: Sequence[KZGCommitment], kzg_aggregated_proof : KZGCommitment): + aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment( blobs, expected_kzg_commitments, @@ -157,16 +185,6 @@ def validate_blobs_sidecar(slot: Slot, assert verify_kzg_proof(aggregated_poly_commitment, x, y, kzg_aggregated_proof) ``` -### `compute_proof_from_blobs` - -```python -def compute_proof_from_blobs(blobs: Sequence[BLSFieldElement]) -> KZGProof: - commitments = [blob_to_kzg_commitment(blob) for blob in blobs] - aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment(blobs, commitments) - x = hash_to_bls_field([aggregated_poly],[aggregated_poly_commitment]) - return compute_kzg_proof(aggregated_poly, x) -``` - ### `get_blobs_and_kzg_commitments` The interface to retrieve blobs and corresponding kzg commitments. From 89c3788b72b6aa45c1543635089a287abbe12d1f Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Mon, 10 Oct 2022 13:36:10 -0500 Subject: [PATCH 3/3] move all cryptography methods out of validator --- specs/eip4844/polynomial-commitments.md | 142 ++++++++++++++++++++---- specs/eip4844/validator.md | 89 --------------- 2 files changed, 120 insertions(+), 111 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 69cb5e0e6a..2fa7f98dbe 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -6,28 +6,35 @@ -- [Introduction](#introduction) -- [Custom types](#custom-types) -- [Constants](#constants) -- [Preset](#preset) - - [Trusted setup](#trusted-setup) -- [Helper functions](#helper-functions) - - [Bit-reversal permutation](#bit-reversal-permutation) - - [`is_power_of_two`](#is_power_of_two) - - [`reverse_bits`](#reverse_bits) - - [`bit_reversal_permutation`](#bit_reversal_permutation) - - [BLS12-381 helpers](#bls12-381-helpers) - - [`bytes_to_bls_field`](#bytes_to_bls_field) - - [`bls_modular_inverse`](#bls_modular_inverse) - - [`div`](#div) - - [`g1_lincomb`](#g1_lincomb) - - [`vector_lincomb`](#vector_lincomb) - - [KZG](#kzg) - - [`blob_to_kzg_commitment`](#blob_to_kzg_commitment) - - [`verify_kzg_proof`](#verify_kzg_proof) - - [`compute_kzg_proof`](#compute_kzg_proof) - - [Polynomials](#polynomials) - - [`evaluate_polynomial_in_evaluation_form`](#evaluate_polynomial_in_evaluation_form) +- [EIP-4844 -- Polynomial Commitments](#eip-4844----polynomial-commitments) + - [Table of contents](#table-of-contents) + - [Introduction](#introduction) + - [Custom types](#custom-types) + - [Constants](#constants) + - [Preset](#preset) + - [Trusted setup](#trusted-setup) + - [Helper functions](#helper-functions) + - [Bit-reversal permutation](#bit-reversal-permutation) + - [`is_power_of_two`](#is_power_of_two) + - [`reverse_bits`](#reverse_bits) + - [`bit_reversal_permutation`](#bit_reversal_permutation) + - [BLS12-381 helpers](#bls12-381-helpers) + - [`bytes_to_bls_field`](#bytes_to_bls_field) + - [`hash_to_bls_field`](#hash_to_bls_field) + - [`bls_modular_inverse`](#bls_modular_inverse) + - [`div`](#div) + - [`g1_lincomb`](#g1_lincomb) + - [`vector_lincomb`](#vector_lincomb) + - [`compute_powers`](#compute_powers) + - [KZG](#kzg) + - [`blob_to_kzg_commitment`](#blob_to_kzg_commitment) + - [`verify_kzg_proof`](#verify_kzg_proof) + - [`compute_kzg_proof`](#compute_kzg_proof) + - [Polynomials](#polynomials) + - [`evaluate_polynomial_in_evaluation_form`](#evaluate_polynomial_in_evaluation_form) + - [`compute_aggregated_poly_and_commitment`](#compute_aggregated_poly_and_commitment) + - [`compute_aggregrate_kzg_proof`](#compute_aggregrate_kzg_proof) + - [`verify_aggregrate_kzg_proof`](#verify_aggregrate_kzg_proof) @@ -122,6 +129,30 @@ def bytes_to_bls_field(b: Bytes32) -> BLSFieldElement: return int.from_bytes(b, "little") % BLS_MODULUS ``` +### `hash_to_bls_field` + +```python +def hash_to_bls_field(polys: List[Polynomial], comms: List[KZGCommitment]) -> BLSFieldElement: + """ + Compute 32-byte hash of serialised polynomials and commitments concatenated + This hash is then converted to a BLS field. + The output is not uniform over the BLS field. + """ + + bytes = [] + + # Append each polynomial + for poly in polys: + for serialised_evaluation in poly: + bytes.extend(serialised_evaluation) + + # Append serialised g1 points + for serialised_comm in comms: + bytes.extend(serialised_comm) + + return bytes_to_bls_field(hash(bytes)) +``` + #### `bls_modular_inverse` ```python @@ -171,6 +202,21 @@ def vector_lincomb(vectors: Sequence[Sequence[BLSFieldElement]], return [BLSFieldElement(x) for x in result] ``` +### `compute_powers` + +```python +def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]: + """ + Return ``x`` to power of [0, n-1]. + """ + current_power = 1 + powers = [] + for _ in range(n): + powers.append(BLSFieldElement(current_power)) + current_power = current_power * int(x) % BLS_MODULUS + return powers +``` + ### KZG KZG core functions. These are also defined in EIP-4844 execution specs. @@ -226,6 +272,7 @@ def compute_kzg_proof(polynomial: Sequence[BLSFieldElement], z: BLSFieldElement) return KZGProof(g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), quotient_polynomial)) ``` + ### Polynomials #### `evaluate_polynomial_in_evaluation_form` @@ -254,3 +301,54 @@ def evaluate_polynomial_in_evaluation_form(polynomial: Sequence[BLSFieldElement] return result ``` +### `compute_aggregated_poly_and_commitment` + +```python +def compute_aggregated_poly_and_commitment( + blobs: Sequence[Sequence[BLSFieldElement]], + kzg_commitments: Sequence[KZGCommitment]) -> Tuple[Polynomial, KZGCommitment]: + """ + Return the aggregated polynomial and aggregated KZG commitment. + """ + # Generate random linear combination challenges + r = hash_to_bls_field(blobs, kzg_commitments) + r_powers = compute_powers(r, len(kzg_commitments)) + + # Create aggregated polynomial in evaluation form + aggregated_poly = Polynomial(vector_lincomb(blobs, r_powers)) + + # Compute commitment to aggregated polynomial + aggregated_poly_commitment = KZGCommitment(g1_lincomb(kzg_commitments, r_powers)) + + return aggregated_poly, aggregated_poly_commitment +``` + +### `compute_aggregrate_kzg_proof` + +```python +def compute_aggregrate_kzg_proof(blobs: Sequence[BLSFieldElement]) -> KZGProof: + commitments = [blob_to_kzg_commitment(blob) for blob in blobs] + aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment(blobs, commitments) + x = hash_to_bls_field([aggregated_poly],[aggregated_poly_commitment]) + return compute_kzg_proof(aggregated_poly, x) +``` + +### `verify_aggregrate_kzg_proof` + +```python +def verify_aggregrate_kzg_proof(blobs: Sequence[BLSFieldElement],expected_kzg_commitments: Sequence[KZGCommitment], kzg_aggregated_proof : KZGCommitment): + + aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment( + blobs, + expected_kzg_commitments, + ) + + # Generate challenge `x` and evaluate the aggregated polynomial at `x` + x = hash_to_bls_field([aggregated_poly], [aggregated_poly_commitment]) + # Evaluate aggregated polynomial at `x` (evaluation function checks for div-by-zero) + y = evaluate_polynomial_in_evaluation_form(aggregated_poly, x) + + # Verify aggregated proof + assert verify_kzg_proof(aggregated_poly_commitment, x, y, kzg_aggregated_proof) +``` + diff --git a/specs/eip4844/validator.md b/specs/eip4844/validator.md index 03e5a8ff45..aee70ff070 100644 --- a/specs/eip4844/validator.md +++ b/specs/eip4844/validator.md @@ -15,13 +15,8 @@ - [Custom types](#custom-types) - [Helpers](#helpers) - [`is_data_available`](#is_data_available) - - [`hash_to_bls_field`](#hash_to_bls_field) - - [`compute_powers`](#compute_powers) - - [`compute_aggregated_poly_and_commitment`](#compute_aggregated_poly_and_commitment) - [`validate_blobs_sidecar`](#validate_blobs_sidecar) - [`compute_proof_from_blobs`](#compute_proof_from_blobs) - - [`compute_aggregrate_kzg_proof`](#compute_aggregrate_kzg_proof) - - [`verify_aggregrate_kzg_proof`](#verify_aggregrate_kzg_proof) - [`get_blobs_and_kzg_commitments`](#get_blobs_and_kzg_commitments) - [Beacon chain responsibilities](#beacon-chain-responsibilities) - [Block proposal](#block-proposal) @@ -72,65 +67,8 @@ def is_data_available(slot: Slot, beacon_block_root: Root, blob_kzg_commitments: return True ``` -### `hash_to_bls_field` -```python -def hash_to_bls_field(polys: List[Tuple[Polynomial | Blob]], comms: List[KZGCommitment]) -> BLSFieldElement: - """ - Compute 32-byte hash of serialised polynomials and commitments concatenated - This hash is then converted to a BLS field. - The output is not uniform over the BLS field. - """ - - bytes = [] - - # Append each polynomial - for poly in polys: - for serialised_evaluation in poly: - bytes.extend(serialised_evaluation) - - # Append serialised g1 points - for serialised_comm in comms: - bytes.extend(serialised_comm) - - return bytes_to_bls_field(hash(bytes)) -``` - -### `compute_powers` -```python -def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]: - """ - Return ``x`` to power of [0, n-1]. - """ - current_power = 1 - powers = [] - for _ in range(n): - powers.append(BLSFieldElement(current_power)) - current_power = current_power * int(x) % BLS_MODULUS - return powers -``` -### `compute_aggregated_poly_and_commitment` - -```python -def compute_aggregated_poly_and_commitment( - blobs: Sequence[Sequence[BLSFieldElement]], - kzg_commitments: Sequence[KZGCommitment]) -> Tuple[Polynomial, KZGCommitment]: - """ - Return the aggregated polynomial and aggregated KZG commitment. - """ - # Generate random linear combination challenges - r = hash_to_bls_field(blobs, kzg_commitments) - r_powers = compute_powers(r, len(kzg_commitments)) - - # Create aggregated polynomial in evaluation form - aggregated_poly = Polynomial(vector_lincomb(blobs, r_powers)) - - # Compute commitment to aggregated polynomial - aggregated_poly_commitment = KZGCommitment(g1_lincomb(kzg_commitments, r_powers)) - - return aggregated_poly, aggregated_poly_commitment -``` ### `validate_blobs_sidecar` @@ -156,34 +94,7 @@ def compute_proof_from_blobs(blobs: Sequence[BLSFieldElement]) -> KZGProof: ``` -### `compute_aggregrate_kzg_proof` - -```python -def compute_aggregrate_kzg_proof(blobs: Sequence[BLSFieldElement]) -> KZGProof: - commitments = [blob_to_kzg_commitment(blob) for blob in blobs] - aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment(blobs, commitments) - x = hash_to_bls_field([aggregated_poly],[aggregated_poly_commitment]) - return compute_kzg_proof(aggregated_poly, x) -``` - -### `verify_aggregrate_kzg_proof` - -```python -def verify_aggregrate_kzg_proof(blobs: Sequence[BLSFieldElement],expected_kzg_commitments: Sequence[KZGCommitment], kzg_aggregated_proof : KZGCommitment): - aggregated_poly, aggregated_poly_commitment = compute_aggregated_poly_and_commitment( - blobs, - expected_kzg_commitments, - ) - - # Generate challenge `x` and evaluate the aggregated polynomial at `x` - x = hash_to_bls_field([aggregated_poly], [aggregated_poly_commitment]) - # Evaluate aggregated polynomial at `x` (evaluation function checks for div-by-zero) - y = evaluate_polynomial_in_evaluation_form(aggregated_poly, x) - - # Verify aggregated proof - assert verify_kzg_proof(aggregated_poly_commitment, x, y, kzg_aggregated_proof) -``` ### `get_blobs_and_kzg_commitments`