From 4a4be2e03930c0414d6bac3b5fc715bbbedb7306 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Fri, 11 Nov 2022 12:23:16 +0000 Subject: [PATCH 01/15] allow empty blobs: - Put the code related to computing challenges in another method - remove panic on poly_lincomb() when `polys` is empty --- specs/eip4844/polynomial-commitments.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 2c142c04b8..f7b2b3de30 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -27,6 +27,7 @@ - [`g1_lincomb`](#g1_lincomb) - [`poly_lincomb`](#poly_lincomb) - [`compute_powers`](#compute_powers) + - [`compute_challenges`](#compute_challenges) - [Polynomials](#polynomials) - [`evaluate_polynomial_in_evaluation_form`](#evaluate_polynomial_in_evaluation_form) - [KZG](#kzg) @@ -231,7 +232,7 @@ def poly_lincomb(polys: Sequence[Polynomial], Given a list of ``polynomials``, interpret it as a 2D matrix and compute the linear combination of each column with `scalars`: return the resulting polynomials. """ - result = [0] * len(polys[0]) + result = [0] * FIELD_ELEMENTS_PER_BLOB for v, s in zip(polys, scalars): for i, x in enumerate(v): result[i] = (result[i] + int(s) * int(x)) % BLS_MODULUS @@ -252,6 +253,24 @@ def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]: current_power = current_power * int(x) % BLS_MODULUS return powers ``` +#### `compute_challenges` + +```python +def compute_challenges(x: BLSFieldElement, n: uint64) -> Tuple[Sequence[BLSFieldElement], BLSFieldElement]: + """ + Return the random linear combination challenges and the evaluation challenge + """ + powers = compute_powers(x, n) + evaluation_challenge = 0 + + # When n == 0, this means that the blobs are empty + # in that case, we define the evaluation challenge to be 0 + if len(powers) != 0: + evaluation_challenge = int(r_powers[-1]) * r % BLS_MODULUS + + return powers, evaluation_challenge + +``` ### Polynomials @@ -351,8 +370,7 @@ def compute_aggregated_poly_and_commitment( # Generate random linear combination challenges r = hash_to_bls_field(polynomials, kzg_commitments) - r_powers = compute_powers(r, len(kzg_commitments)) - evaluation_challenge = int(r_powers[-1]) * r % BLS_MODULUS + r_powers, evaluation_challenge = compute_challenges(r, len(kzg_commitments)) # Create aggregated polynomial in evaluation form aggregated_poly = Polynomial(poly_lincomb(polynomials, r_powers)) From 88dfcc44c0da581e4c2af1647b20a58248592c69 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Fri, 11 Nov 2022 15:21:56 +0000 Subject: [PATCH 02/15] use correct variable names --- specs/eip4844/polynomial-commitments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index f7b2b3de30..cb55685121 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -266,7 +266,7 @@ def compute_challenges(x: BLSFieldElement, n: uint64) -> Tuple[Sequence[BLSField # When n == 0, this means that the blobs are empty # in that case, we define the evaluation challenge to be 0 if len(powers) != 0: - evaluation_challenge = int(r_powers[-1]) * r % BLS_MODULUS + evaluation_challenge = int(powers[-1]) * x % BLS_MODULUS return powers, evaluation_challenge From a6f3a79cacc34b9e5f7104601b10afd7174d35c7 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Fri, 11 Nov 2022 15:33:59 +0000 Subject: [PATCH 03/15] asn review --- specs/eip4844/polynomial-commitments.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index cb55685121..cddfa941d2 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -258,14 +258,14 @@ def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]: ```python def compute_challenges(x: BLSFieldElement, n: uint64) -> Tuple[Sequence[BLSFieldElement], BLSFieldElement]: """ - Return the random linear combination challenges and the evaluation challenge + Return the random linear combination challenges and the evaluation challenge. ``x`` is the initial challenge to which we will generate ``n + 1`` challenges from. """ powers = compute_powers(x, n) evaluation_challenge = 0 # When n == 0, this means that the blobs are empty # in that case, we define the evaluation challenge to be 0 - if len(powers) != 0: + if n != 0: evaluation_challenge = int(powers[-1]) * x % BLS_MODULUS return powers, evaluation_challenge @@ -364,6 +364,7 @@ def compute_aggregated_poly_and_commitment( """ Return (1) the aggregated polynomial, (2) the aggregated KZG commitment, and (3) the polynomial evaluation random challenge. + This function should be able to work with blobs == [] and kzg_commitments == [] """ # Convert blobs to polynomials polynomials = [blob_to_polynomial(blob) for blob in blobs] From c78670803062ecc91b742b899032acc113a5d396 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Fri, 11 Nov 2022 15:44:33 +0000 Subject: [PATCH 04/15] add test for zero blobs --- .../test/eip4844/unittests/validator/test_validator.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py index 634daca2d5..8355ba38fc 100644 --- a/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py @@ -25,6 +25,11 @@ def _run_validate_blobs_sidecar_test(spec, state, blob_count): spec.validate_blobs_sidecar(block.slot, block.hash_tree_root(), expected_commitments, blobs_sidecar) +@with_eip4844_and_later +@spec_state_test +def test_validate_blobs_sidecar_zero_blobs(spec, state): + _run_validate_blobs_sidecar_test(spec, state, blob_count=0) + @with_eip4844_and_later @spec_state_test def test_validate_blobs_sidecar_one_blob(spec, state): From 3327c0bc19aafb393aa5a4b4a421f867f588059e Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 11 Nov 2022 18:25:26 +0200 Subject: [PATCH 05/15] Fix linter errors --- specs/eip4844/polynomial-commitments.md | 8 ++++---- .../test/eip4844/unittests/validator/test_validator.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index cddfa941d2..6c15cce8f9 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -258,18 +258,18 @@ def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]: ```python def compute_challenges(x: BLSFieldElement, n: uint64) -> Tuple[Sequence[BLSFieldElement], BLSFieldElement]: """ - Return the random linear combination challenges and the evaluation challenge. ``x`` is the initial challenge to which we will generate ``n + 1`` challenges from. + Return the random linear combination challenges and the evaluation challenge. + ``x`` is the initial challenge to which we will generate ``n + 1`` challenges from. """ powers = compute_powers(x, n) evaluation_challenge = 0 - + # When n == 0, this means that the blobs are empty # in that case, we define the evaluation challenge to be 0 if n != 0: evaluation_challenge = int(powers[-1]) * x % BLS_MODULUS - - return powers, evaluation_challenge + return powers, evaluation_challenge ``` ### Polynomials diff --git a/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py index 8355ba38fc..d9e3877c3c 100644 --- a/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/eip4844/unittests/validator/test_validator.py @@ -30,6 +30,7 @@ def _run_validate_blobs_sidecar_test(spec, state, blob_count): def test_validate_blobs_sidecar_zero_blobs(spec, state): _run_validate_blobs_sidecar_test(spec, state, blob_count=0) + @with_eip4844_and_later @spec_state_test def test_validate_blobs_sidecar_one_blob(spec, state): From b7515f734901f7861ad79b48b846cb5a5b7ca83b Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 11 Nov 2022 18:36:18 +0200 Subject: [PATCH 06/15] Add defensive assert to make sure that input length is consistent --- specs/eip4844/polynomial-commitments.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 6c15cce8f9..80c11b9a5d 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -366,6 +366,8 @@ def compute_aggregated_poly_and_commitment( and (3) the polynomial evaluation random challenge. This function should be able to work with blobs == [] and kzg_commitments == [] """ + assert len(blobs) == len(kzg_commitments) + # Convert blobs to polynomials polynomials = [blob_to_polynomial(blob) for blob in blobs] From 470347156fb94a7c15366a38d3b3a2062c693a28 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Fri, 11 Nov 2022 22:48:39 +0000 Subject: [PATCH 07/15] dankrad review --- specs/eip4844/polynomial-commitments.md | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 80c11b9a5d..c19dbc84d1 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -27,7 +27,6 @@ - [`g1_lincomb`](#g1_lincomb) - [`poly_lincomb`](#poly_lincomb) - [`compute_powers`](#compute_powers) - - [`compute_challenges`](#compute_challenges) - [Polynomials](#polynomials) - [`evaluate_polynomial_in_evaluation_form`](#evaluate_polynomial_in_evaluation_form) - [KZG](#kzg) @@ -38,9 +37,6 @@ - [`compute_aggregate_kzg_proof`](#compute_aggregate_kzg_proof) - [`verify_aggregate_kzg_proof`](#verify_aggregate_kzg_proof) - - - ## Introduction @@ -253,24 +249,7 @@ def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]: current_power = current_power * int(x) % BLS_MODULUS return powers ``` -#### `compute_challenges` -```python -def compute_challenges(x: BLSFieldElement, n: uint64) -> Tuple[Sequence[BLSFieldElement], BLSFieldElement]: - """ - Return the random linear combination challenges and the evaluation challenge. - ``x`` is the initial challenge to which we will generate ``n + 1`` challenges from. - """ - powers = compute_powers(x, n) - evaluation_challenge = 0 - - # When n == 0, this means that the blobs are empty - # in that case, we define the evaluation challenge to be 0 - if n != 0: - evaluation_challenge = int(powers[-1]) * x % BLS_MODULUS - - return powers, evaluation_challenge -``` ### Polynomials @@ -373,7 +352,9 @@ def compute_aggregated_poly_and_commitment( # Generate random linear combination challenges r = hash_to_bls_field(polynomials, kzg_commitments) - r_powers, evaluation_challenge = compute_challenges(r, len(kzg_commitments)) + all_r_powers = compute_powers(r, len(kzg_commitments) + 1) + evaluation_challenge = all_r_powers[-1] + r_powers = all_r_powers[:-1] # Create aggregated polynomial in evaluation form aggregated_poly = Polynomial(poly_lincomb(polynomials, r_powers)) From d4c6a691d0ed5be29acfa5d50d25fed802b7e53d Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 17 Nov 2022 13:17:37 +0000 Subject: [PATCH 08/15] use challenge index to generate linear combination challenges and evaluation challenge --- specs/eip4844/polynomial-commitments.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index c19dbc84d1..20d499165f 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -161,7 +161,7 @@ def blob_to_polynomial(blob: Blob) -> Polynomial: ```python def hash_to_bls_field(polys: Sequence[Polynomial], - comms: Sequence[KZGCommitment]) -> BLSFieldElement: + comms: Sequence[KZGCommitment], challenge_index : uint8) -> BLSFieldElement: """ Compute 32-byte hash of serialized polynomials and commitments concatenated. This hash is then converted to a BLS field element, where the result is not uniform over the BLS field. @@ -181,6 +181,10 @@ def hash_to_bls_field(polys: Sequence[Polynomial], for commitment in comms: data += commitment + # Append challenge index last so we can cache the data buffer + # in the case of multiple challenges + data += challenge_index + return bytes_to_bls_field(hash(data)) ``` @@ -350,11 +354,10 @@ def compute_aggregated_poly_and_commitment( # Convert blobs to polynomials polynomials = [blob_to_polynomial(blob) for blob in blobs] - # Generate random linear combination challenges - r = hash_to_bls_field(polynomials, kzg_commitments) - all_r_powers = compute_powers(r, len(kzg_commitments) + 1) - evaluation_challenge = all_r_powers[-1] - r_powers = all_r_powers[:-1] + # Generate random linear combination and evaluation challenges + r = hash_to_bls_field(polynomials, kzg_commitments, 0) + r_powers = compute_powers(r, len(kzg_commitments)) + evaluation_challenge = hash_to_bls_field(polynomials, kzg_commitments, 1) # Create aggregated polynomial in evaluation form aggregated_poly = Polynomial(poly_lincomb(polynomials, r_powers)) From 73adfa5e5125d47d003610a9c1ddec3772cd408b Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Thu, 17 Nov 2022 13:35:14 +0000 Subject: [PATCH 09/15] use an integer and convert challenge_index to bytes --- specs/eip4844/polynomial-commitments.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 20d499165f..4e97199909 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -161,7 +161,7 @@ def blob_to_polynomial(blob: Blob) -> Polynomial: ```python def hash_to_bls_field(polys: Sequence[Polynomial], - comms: Sequence[KZGCommitment], challenge_index : uint8) -> BLSFieldElement: + comms: Sequence[KZGCommitment], challenge_index : int) -> BLSFieldElement: """ Compute 32-byte hash of serialized polynomials and commitments concatenated. This hash is then converted to a BLS field element, where the result is not uniform over the BLS field. @@ -183,7 +183,7 @@ def hash_to_bls_field(polys: Sequence[Polynomial], # Append challenge index last so we can cache the data buffer # in the case of multiple challenges - data += challenge_index + data += int.to_bytes(challenge_index, 1, ENDIANNESS) return bytes_to_bls_field(hash(data)) ``` From d0489bc844f55dceba39e8730cd3d78184a1e1ae Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 18 Nov 2022 19:36:52 +0200 Subject: [PATCH 10/15] Satisfy linter --- specs/eip4844/polynomial-commitments.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 4e97199909..088375e64d 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -37,6 +37,8 @@ - [`compute_aggregate_kzg_proof`](#compute_aggregate_kzg_proof) - [`verify_aggregate_kzg_proof`](#verify_aggregate_kzg_proof) + + ## Introduction @@ -161,7 +163,8 @@ def blob_to_polynomial(blob: Blob) -> Polynomial: ```python def hash_to_bls_field(polys: Sequence[Polynomial], - comms: Sequence[KZGCommitment], challenge_index : int) -> BLSFieldElement: + comms: Sequence[KZGCommitment], + challenge_index: int) -> BLSFieldElement: """ Compute 32-byte hash of serialized polynomials and commitments concatenated. This hash is then converted to a BLS field element, where the result is not uniform over the BLS field. From 7a411075f78243acc9f09340db5efd20a353e681 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Mon, 21 Nov 2022 12:51:36 +0200 Subject: [PATCH 11/15] Add defensive assert in poly_lincomb() and some comments --- specs/eip4844/polynomial-commitments.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 088375e64d..c3d0240b19 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -235,6 +235,7 @@ def poly_lincomb(polys: Sequence[Polynomial], Given a list of ``polynomials``, interpret it as a 2D matrix and compute the linear combination of each column with `scalars`: return the resulting polynomials. """ + assert len(polys) == len(scalars) result = [0] * FIELD_ELEMENTS_PER_BLOB for v, s in zip(polys, scalars): for i, x in enumerate(v): @@ -350,7 +351,7 @@ def compute_aggregated_poly_and_commitment( """ Return (1) the aggregated polynomial, (2) the aggregated KZG commitment, and (3) the polynomial evaluation random challenge. - This function should be able to work with blobs == [] and kzg_commitments == [] + This function should also work with blobs == [] and kzg_commitments == [] """ assert len(blobs) == len(kzg_commitments) @@ -375,6 +376,9 @@ def compute_aggregated_poly_and_commitment( ```python def compute_aggregate_kzg_proof(blobs: Sequence[Blob]) -> KZGProof: + """ + Given a list of blobs, return the aggregated KZG proof that is used to verify them against their commitments. + """ commitments = [blob_to_kzg_commitment(blob) for blob in blobs] aggregated_poly, aggregated_poly_commitment, evaluation_challenge = compute_aggregated_poly_and_commitment( blobs, @@ -389,6 +393,9 @@ def compute_aggregate_kzg_proof(blobs: Sequence[Blob]) -> KZGProof: def verify_aggregate_kzg_proof(blobs: Sequence[Blob], expected_kzg_commitments: Sequence[KZGCommitment], kzg_aggregated_proof: KZGCommitment) -> bool: + """ + Given a list of blobs and an aggregated KZG proof, verify that they correspond to the provided commitments. + """ aggregated_poly, aggregated_poly_commitment, evaluation_challenge = compute_aggregated_poly_and_commitment( blobs, expected_kzg_commitments, From 80dd7be0cda323d7d4e931decaf9a06988938992 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Tue, 22 Nov 2022 16:08:47 +0000 Subject: [PATCH 12/15] Update specs/eip4844/polynomial-commitments.md Co-authored-by: dankrad --- specs/eip4844/polynomial-commitments.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 721b0ec84b..c705ab4ea1 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -189,7 +189,8 @@ def hash_to_bls_field(polys: Sequence[Polynomial], # Append challenge index last so we can cache the data buffer # in the case of multiple challenges - data += int.to_bytes(challenge_index, 1, ENDIANNESS) + hashed_data = hash(data) + return bytes_to_bls_field(hash(hashed_data, int.to_bytes(challenge_index, 1, ENDIANNESS))) return bytes_to_bls_field(hash(data)) ``` From 946fd5f5929a4dd37c3ae0f63341f9e3402bcb21 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Tue, 22 Nov 2022 16:39:25 +0000 Subject: [PATCH 13/15] cleanup comments and extra return --- specs/eip4844/polynomial-commitments.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index c705ab4ea1..fcc90e4bfe 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -187,12 +187,8 @@ def hash_to_bls_field(polys: Sequence[Polynomial], for commitment in comms: data += commitment - # Append challenge index last so we can cache the data buffer - # in the case of multiple challenges hashed_data = hash(data) - return bytes_to_bls_field(hash(hashed_data, int.to_bytes(challenge_index, 1, ENDIANNESS))) - - return bytes_to_bls_field(hash(data)) + return bytes_to_bls_field(hash(hashed_data + int.to_bytes(challenge_index, 1, ENDIANNESS))) ``` #### `bls_modular_inverse` From 7ea0f9ccf156cd0b6d413c3c21736fcda27ade00 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Tue, 22 Nov 2022 16:52:58 +0000 Subject: [PATCH 14/15] Do bytes conversion of challenge_index on a separate line for readability --- specs/eip4844/polynomial-commitments.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index fcc90e4bfe..7a974ffe4f 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -188,7 +188,9 @@ def hash_to_bls_field(polys: Sequence[Polynomial], data += commitment hashed_data = hash(data) - return bytes_to_bls_field(hash(hashed_data + int.to_bytes(challenge_index, 1, ENDIANNESS))) + challenge_index_bytes = int.to_bytes(challenge_index, 1, ENDIANNESS) + + return bytes_to_bls_field(hash(hashed_data + challenge_index_bytes)) ``` #### `bls_modular_inverse` From eacf448d2e70a4ee899a093ccb08362ba3c0101e Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Wed, 23 Nov 2022 15:24:56 +0200 Subject: [PATCH 15/15] Move entire FS logic into compute_challenges() --- specs/eip4844/polynomial-commitments.md | 41 +++++++++++++++---------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/specs/eip4844/polynomial-commitments.md b/specs/eip4844/polynomial-commitments.md index 7a974ffe4f..b18122b037 100644 --- a/specs/eip4844/polynomial-commitments.md +++ b/specs/eip4844/polynomial-commitments.md @@ -21,7 +21,7 @@ - [BLS12-381 helpers](#bls12-381-helpers) - [`bytes_to_bls_field`](#bytes_to_bls_field) - [`blob_to_polynomial`](#blob_to_polynomial) - - [`hash_to_bls_field`](#hash_to_bls_field) + - [`compute_challenges`](#compute_challenges) - [`bls_modular_inverse`](#bls_modular_inverse) - [`div`](#div) - [`g1_lincomb`](#g1_lincomb) @@ -162,35 +162,44 @@ def blob_to_polynomial(blob: Blob) -> Polynomial: return polynomial ``` -#### `hash_to_bls_field` +#### `compute_challenges` ```python -def hash_to_bls_field(polys: Sequence[Polynomial], - comms: Sequence[KZGCommitment], - challenge_index: int) -> BLSFieldElement: +def compute_challenges(polynomials: Sequence[Polynomial], + commitments: Sequence[KZGCommitment]) -> BLSFieldElement: """ - Compute 32-byte hash of serialized polynomials and commitments concatenated. - This hash is then converted to a BLS field element, where the result is not uniform over the BLS field. - Return the BLS field element. + Return the Fiat-Shamir challenges required by the rest of the protocol. + The Fiat-Shamir logic works as per the following pseudocode: + + hashed_data = hash(DOMAIN_SEPARATOR, polynomials, commitments) + r = hash(hashed_data, 0) + r_powers = [r, r**2, r**3, ...] + eval_challenge = hash(hashed_data, 1) + + Then return `r_powers` and `eval_challenge` after converting them to BLS field elements. + The resulting field elements are not uniform over the BLS field. """ # Append the number of polynomials and the degree of each polynomial as a domain separator - num_polys = int.to_bytes(len(polys), 8, ENDIANNESS) + num_polynomials = int.to_bytes(len(polynomials), 8, ENDIANNESS) degree_poly = int.to_bytes(FIELD_ELEMENTS_PER_BLOB, 8, ENDIANNESS) - data = FIAT_SHAMIR_PROTOCOL_DOMAIN + degree_poly + num_polys + data = FIAT_SHAMIR_PROTOCOL_DOMAIN + degree_poly + num_polynomials # Append each polynomial which is composed by field elements - for poly in polys: + for poly in polynomials: for field_element in poly: data += int.to_bytes(field_element, BYTES_PER_FIELD_ELEMENT, ENDIANNESS) # Append serialized G1 points - for commitment in comms: + for commitment in commitments: data += commitment + # Transcript has been prepared: time to create the challenges hashed_data = hash(data) - challenge_index_bytes = int.to_bytes(challenge_index, 1, ENDIANNESS) + r = hash(hashed_data + b'\x00') + r_powers = compute_powers(bytes_to_bls_field(r), len(commitments)) + eval_challenge = hash(hashed_data + b'\x01') - return bytes_to_bls_field(hash(hashed_data + challenge_index_bytes)) + return r_powers, bytes_to_bls_field(eval_challenge) ``` #### `bls_modular_inverse` @@ -380,9 +389,7 @@ def compute_aggregated_poly_and_commitment( polynomials = [blob_to_polynomial(blob) for blob in blobs] # Generate random linear combination and evaluation challenges - r = hash_to_bls_field(polynomials, kzg_commitments, 0) - r_powers = compute_powers(r, len(kzg_commitments)) - evaluation_challenge = hash_to_bls_field(polynomials, kzg_commitments, 1) + r_powers, evaluation_challenge = compute_challenges(polynomials, kzg_commitments) # Create aggregated polynomial in evaluation form aggregated_poly = Polynomial(poly_lincomb(polynomials, r_powers))