diff --git a/specs/eip4844/beacon-chain.md b/specs/eip4844/beacon-chain.md index 8c84a2862..6011e5832 100644 --- a/specs/eip4844/beacon-chain.md +++ b/specs/eip4844/beacon-chain.md @@ -45,6 +45,7 @@ This upgrade adds blobs to the beacon chain as part of EIP-4844. | `Blob` | `Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB]` | | | `VersionedHash` | `Bytes32` | | | `KZGCommitment` | `Bytes48` | Same as BLS standard "is valid pubkey" check but also allows `0x00..00` for point-at-infinity | +| `KZGProof` | Bytes48 | Same as for `KZGCommitment` | ## Constants diff --git a/specs/eip4844/p2p-interface.md b/specs/eip4844/p2p-interface.md index 68c984950..7a447dbd4 100644 --- a/specs/eip4844/p2p-interface.md +++ b/specs/eip4844/p2p-interface.md @@ -57,6 +57,7 @@ class BlobsSidecar(Container): beacon_block_root: Root beacon_block_slot: Slot blobs: List[Blob, MAX_BLOBS_PER_BLOCK] + kzg_aggregated_proof: KZGProof ``` ### `SignedBlobsSidecar` @@ -114,6 +115,7 @@ The following validations MUST pass before forwarding the `signed_blobs_sidecar` Alias `sidecar = signed_blobs_sidecar.message`. - _[IGNORE]_ the `sidecar.beacon_block_slot` is for the current slot (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. `blobs_sidecar.beacon_block_slot == current_slot`. - _[REJECT]_ the `sidecar.blobs` are all well formatted, i.e. the `BLSFieldElement` in valid range (`x < BLS_MODULUS`). +- _[REJECT]_ The KZG proof is a correctly encoded compressed BLS G1 Point -- i.e. `bls.KeyValidate(blobs_sidecar.kzg_aggregated_proof) - _[REJECT]_ the beacon proposer signature, `signed_blobs_sidecar.signature`, is valid -- i.e. ```python domain = get_domain(state, DOMAIN_BLOBS_SIDECAR, blobs_sidecar.beacon_block_slot // SLOTS_PER_EPOCH) diff --git a/specs/eip4844/validator.md b/specs/eip4844/validator.md index 2083934c5..aed38639f 100644 --- a/specs/eip4844/validator.md +++ b/specs/eip4844/validator.md @@ -59,9 +59,25 @@ def verify_blobs_sidecar(slot: Slot, beacon_block_root: Root, assert slot == blobs_sidecar.beacon_block_slot assert beacon_block_root == blobs_sidecar.beacon_block_root blobs = blobs_sidecar.blobs + kzg_aggregated_proof = blobs_sidecar.kzg_aggregated_proof assert len(expected_kzgs) == len(blobs) - for kzg, blob in zip(expected_kzgs, blobs): - assert blob_to_kzg(blob) == kzg + + # Generate random linear combination challenges + r = hash_to_bls_field([blobs, expected_kzgs]) + r_powers = compute_powers(r, len(expected_kzgs)) + + # Compute commitment to aggregated polynomial + aggregated_poly_commitment = lincomb(expected_kzgs, r_powers) + + # Create aggregated polynomial in evaluation form + aggregated_poly = vector_lincomb(blobs, r_powers) + + # Generate challenge `x` and evaluate the aggregated polynomial at `x` + x = hash_to_bls_field([aggregated_poly, aggregated_poly_commitment]) + y = evaluate_polynomial_in_evaluation_form(aggregated_poly, x) + + # Verify aggregated proof + assert verify_kzg_proof(aggregated_poly_commitment, x, y, kzg_aggregated_proof) ```