Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Executable EIP-4844 specs #2901

Closed
wants to merge 24 commits into from
Closed

Executable EIP-4844 specs #2901

wants to merge 24 commits into from

Conversation

hwwhww
Copy link
Contributor

@hwwhww hwwhww commented May 24, 2022

In this PR:

TODOs:

  • (Not in this PR) Handle mainnet config FIELD_ELEMENTS_PER_BLOB: 4096
    • Since (i) mainnet trusted setup is not complete (ii), it would really slow to generate trusted setup with large length with py-ecc and (iii) spec builder dependency, right now mainnet KZG_SETUP_G2 and KZG_SETUP_LAGRANGE are actually minimal config values.

@hwwhww hwwhww added the Deneb was called: eip-4844 label May 24, 2022
@hwwhww
Copy link
Contributor Author

hwwhww commented May 31, 2022

@asn-d6 @protolambda
Do you mind reviewing the specs and kzg.py parts?

Copy link
Contributor

@asn-d6 asn-d6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, after an initial review!

I'm gonna be working on integrating ethereum/EIPs#5088 into the consensus-specs this week, so there will be a bunch of new things after that's done. When it's time, I will leave a new comment here with some more information.

Cheers!

@classmethod
def sundry_functions(cls) -> str:
return super().sundry_functions() + '''
# TODO: for mainnet, load pre-generated trusted setup file to reduce building time.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a py_ecc-based insecure trusted setup you might want to use for this purpose: https://github.com/asn-d6/kzgverify/blob/playground/trusted_setup.py (and corresponding json files on same directory)

tests/core/pyspec/eth2spec/utils/kzg.py Outdated Show resolved Hide resolved
@asn-d6
Copy link
Contributor

asn-d6 commented Jun 14, 2022

Hello @hwwhww! I have created the PR for the consensus-side verification logic that uses KZG proofs. Please see #2915

I imagine that this would warrant a bunch of changes to the code of this PR. In particular:

  • Implement the math/polynomial functions introduced by the PR.

  • Introduce the ROOTS_OF_UNITY constant list of BLS field elements. You can generate them with code that looks like this https://github.com/ethereum/consensus-specs/blob/danksharding/specs/sharding/polynomial-commitments.md#roots_of_unity

  • Finally, to make an end-to-end test that goes from block creation all the way to verification, we would need to create a valid kzg_aggregated_proof that can be verified. To do that, we need to create a bunch of blobs and commitments and then basically faithfully reproduce the steps performed in verify_blobs_sidecar() to compute:

    • r_powers from the various blobs and commitments
    • aggregated_poly from the individual blobs
    • aggregated_poly_commitment from the corresponding commitments
    • x from the aggregated_poly and aggregated_poly_commitment

    finally, we use those objects to create a valid KZG proof for that aggregated poly at x That proof is the one that the tests will verify.


Please let me know if the above did not make any sense!

@hwwhww
Copy link
Contributor Author

hwwhww commented Jun 29, 2022

Hey @asn-d6

Updated some quick fixes after the #2915 patch in 60fdcac.

  1. Moved vector_lincomb to polynomial-commitments.md
  2. Fixed function signatures: replace List with Sequence
  3. To use hash_to_bls_field properly, created BlobsAndCommmitments and PolynomialAndCommitment SSZ containers.
  4. Add custom type Polynomial
  5. To exclude the snippet sample code in p2p spec & v-guide, remove “python” from the code block for now.

@hwwhww
Copy link
Contributor Author

hwwhww commented Jul 1, 2022

Found more bugs: 33829dd

  1. Fixed offset calculation in tx_peek_blob_versioned_hashes
  2. Fixed lincomb return value type: in Pyspec, r is an optimized_bls12_381_FQ object so we need serialization. G1_to_bytes48 is the function that we used in BLS pubkey serialization.
  3. Fixed BlobsSidecar sample code: / -> Python //

@hwwhww
Copy link
Contributor Author

hwwhww commented Jul 1, 2022

@asn-d6

In validator guide, it described how to pack the blobs into a BlobsSidecar object. However, BlobsSidecar.kzg_aggregated_proof value is missing here.

Should we add notes on how to generate proof to the validator guide?

@asn-d6
Copy link
Contributor

asn-d6 commented Jul 2, 2022

@asn-d6

In validator guide, it described how to pack the blobs into a BlobsSidecar object. However, BlobsSidecar.kzg_aggregated_proof value is missing here.

Should we add notes on how to generate proof to the validator guide?

Yep! I think that's needed!

The notes in the last point of #2901 (comment) could serve as a decent guide here I think.

@asn-d6
Copy link
Contributor

asn-d6 commented Jul 2, 2022

Found more bugs: 33829dd

Good catches!

2. Fixed `lincomb` return value type: in Pyspec, `r` is an `optimized_bls12_381_FQ` object so we need serialization. `G1_to_bytes48` is the function that we used in BLS pubkey serialization.

I'm a bit sad that we have to do this ugly cast KZGCommitment(kzg.G1_to_bytes48(r)) in the spec. I understand why it's there and I don't have a solution atm, but I'm just mentioning this because I don't remember similar casts in the BLS parts of the spec.

@hwwhww
Copy link
Contributor Author

hwwhww commented Jul 5, 2022

Updates:

  1. Add compute_proof_from_blobs and its sub helpers. (Thank @asn-d6 for helping debug!)
  2. Add tests to verify the validator guide.
  3. Add @protolambda explainer on blob_versioned_hashes offset calculation
  4. Renames
    1. quotient_kzg -> kzg_proof
    2. Parameters. Use fewer abbreviations.
  5. Fix is_data_available
  6. Add int() casting during polynomial computation to avoid SSZ object overflow/underflow.
  7. Add G1_to_bytes48/bytes48_to_G1/G2_to_bytes96/bytes96_to_G2 in some KZG functions.
    • Re: Executable EIP-4844 specs #2901 (comment)
      • The BLS API wrappers (IETF BLS signature draft standard v4 implementation) handled it internally so I didn't have to do the conversion in specs. But now we are dealing with low-level computation in specs so things are exposed. These conversions only happen in polynomial-commitments.md currently. Hope that it will be standardized soon and then CL implementors don't have to implement the conversions.

@hwwhww hwwhww marked this pull request as ready for review July 5, 2022 09:22
@hwwhww hwwhww changed the title Trying to include EIP-4844 specs to pyspec Executable EIP-4844 specs Jul 5, 2022
@hwwhww
Copy link
Contributor Author

hwwhww commented Jul 6, 2022

Update: ec7f607

As discussed, rename most KZGCommitment object kzg -> commitment

  1. blob_kzgs -> blob_commitments
    • note: there is also "KZGProof"
  2. blob_to_kzg -> blob_to_commitment
  3. BLOB_COMMITMENT_VERSION_KZG -> BLOB_COMMITMENT_VERSION
  4. kzg_to_versioned_hash -> commitment_to_versioned_hash
  5. [New] verify_kzgs_against_transactions -> verify_commitments_against_transactions

Notes:

  • I use "commitment" in most function signatures where it is obvious a commitment of blob.
  • Use full name blob_commitments in BeaconBlockBody field.

@hwwhww
Copy link
Contributor Author

hwwhww commented Jul 6, 2022

So after discussing with @vbuterin @asn-d6 @GottfriedHerold, we realized that "blob commitment" could be confused with versioned hash.

247850a update:

  • use full name "blob_kzg_commitments".
  • BLOB_COMMITMENT_VERSION_KZG -> VERSIONED_HASH_VERSION_KZG.

#### `compute_kzg_proof`

```python
def compute_kzg_proof(polynomial: Sequence[BLSFieldElement], x: BLSFieldElement) -> KZGProof:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be a good idea to document here that the polynomial is in evaluation form

polynomial = [int(i) for i in polynomial]

# Convert `polynomial` to coefficient form
assert pow(ROOTS_OF_UNITY[1], len(polynomial), BLS_MODULUS) == 1
Copy link
Contributor

@asn-d6 asn-d6 Jul 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that FFT has penetrated into the core of the spec, it might be worth modding our FFT function to do the inverse FFT inside of it, instead of doing it at the caller.

For example see the wrapper fft() function here https://github.com/ethereum/research/blob/master/mimc_stark/fft.py#L31 that internally calls _fft() which is what we have here (we don't need the simple_ft() thing).

Also, since FFT is not exactly polynomial specific it might be worth introducing an FFT section in this file just for FFT stuff.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discussion, we don't actually need FFT to make KZG proofs from polynomials in evaluation form.
Please see this branch: https://github.com/asn-d6/consensus-specs/tree/eip4844-exe (pending review)

return pow(PRIMITIVE_ROOT_OF_UNITY, (BLS_MODULUS - 1) // length, BLS_MODULUS)


def compute_roots_of_unity(field_elements_per_blob):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better to replace field_elements_per_blob with order here and make this function less-application-specific.

asn-d6 and others added 3 commits July 13, 2022 12:26
We were using `x` as the evaluation point variable in polynomial functions. That can be confused with the
indeterminate variable `x` of the polynomial.

Hence the convention now is:
- `x` for the indeterminate variable of a polynomial
- `z` for the point we evaluate it at
- `y` for the evaluation result
Previously we were using IFFT to go from evaluation form to coefficient form before computing the KZG proof in the
traditional way.

We can instead do the KZG proof division directly in evaluation form by using point-by-point division:
   https://dankradfeist.de/ethereum/2021/06/18/pcs-multiproofs.html#dividing-when-one-of-the-points-is-zero

Two fine points:
- We need to check that the denominator of the division is not zero. It's very unlikely because `z` comes out of
Fiat-Shamir, but we still add an assert to make sure.

- We need to shift our main polynomial by `p(z)` as in the traditional KZG proof formula. We can avoid this
in coefficient form because with long division we can extract the quotient polynomial and ignore the remainder.
However that's not possible when doing point-by-point division in evaluation form and hence we need to ensure
that there is no remainder by shifting by `p(z)`.
asn-d6 referenced this pull request in asn-d6/consensus-specs Jul 13, 2022
Previously we were using IFFT to go from evaluation form to coefficient form before computing the KZG proof in the
traditional way.

We can instead do the KZG proof division directly in evaluation form by using point-by-point division:
   https://dankradfeist.de/ethereum/2021/06/18/pcs-multiproofs.html#dividing-when-one-of-the-points-is-zero

Two fine points:
- We need to check that the denominator of the division is not zero. It's very unlikely because `z` comes out of
Fiat-Shamir, but we still add an assert to make sure.

- We need to shift our main polynomial by `p(z)` as in the traditional KZG proof formula. We can avoid this
in coefficient form because with long division we can extract the quotient polynomial and ignore the remainder.
However that's not possible when doing point-by-point division in evaluation form and hence we need to ensure
that there is no remainder by shifting by `p(z)`.
@asn-d6
Copy link
Contributor

asn-d6 commented Jul 13, 2022

Made an attempt at squashing and rebasing this PR: #2937
Pending review.

@hwwhww
Copy link
Contributor Author

hwwhww commented Jul 13, 2022

closing in favor of #2937

@hwwhww hwwhww closed this Jul 13, 2022
asn-d6 added a commit that referenced this pull request Jul 16, 2022
 Executable EIP-4844 specs (PR #2901 squashed and rebased)
@hwwhww hwwhww deleted the eip4844-exe branch December 1, 2022 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Deneb was called: eip-4844
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants