mirror of
https://github.com/ethereum/consensus-specs.git
synced 2026-02-01 09:45:02 -05:00
Merge branch 'dev' into deneb-crypto-coverage
This commit is contained in:
@@ -72,7 +72,10 @@ Public functions MUST accept raw bytes as input and perform the required cryptog
|
||||
| Name | Value | Notes |
|
||||
| - | - | - |
|
||||
| `BLS_MODULUS` | `52435875175126190479447740508185965837690552500527637822603658699938581184513` | Scalar field modulus of BLS12-381 |
|
||||
| `BYTES_PER_COMMITMENT` | `uint64(48)` | The number of bytes in a KZG commitment |
|
||||
| `BYTES_PER_PROOF` | `uint64(48)` | The number of bytes in a KZG proof |
|
||||
| `BYTES_PER_FIELD_ELEMENT` | `uint64(32)` | Bytes used to encode a BLS scalar field element |
|
||||
| `BYTES_PER_BLOB` | `uint64(BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB)` | The number of bytes in a blob |
|
||||
| `G1_POINT_AT_INFINITY` | `Bytes48(b'\xc0' + b'\x00' * 47)` | Serialized form of the point at infinity on the G1 group |
|
||||
|
||||
|
||||
@@ -303,8 +306,10 @@ def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]:
|
||||
def evaluate_polynomial_in_evaluation_form(polynomial: Polynomial,
|
||||
z: BLSFieldElement) -> BLSFieldElement:
|
||||
"""
|
||||
Evaluate a polynomial (in evaluation form) at an arbitrary point ``z`` that is not in the domain.
|
||||
Uses the barycentric formula:
|
||||
Evaluate a polynomial (in evaluation form) at an arbitrary point ``z``.
|
||||
- When ``z`` is in the domain, the evaluation can be found by indexing the polynomial at the
|
||||
position that ``z`` is in the domain.
|
||||
- When ``z`` is not in the domain, the barycentric formula is used:
|
||||
f(z) = (z**WIDTH - 1) / WIDTH * sum_(i=0)^WIDTH (f(DOMAIN[i]) * DOMAIN[i]) / (z - DOMAIN[i])
|
||||
"""
|
||||
width = len(polynomial)
|
||||
@@ -338,6 +343,7 @@ def blob_to_kzg_commitment(blob: Blob) -> KZGCommitment:
|
||||
"""
|
||||
Public method.
|
||||
"""
|
||||
assert len(blob) == BYTES_PER_BLOB
|
||||
return g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), blob_to_polynomial(blob))
|
||||
```
|
||||
|
||||
@@ -345,17 +351,22 @@ def blob_to_kzg_commitment(blob: Blob) -> KZGCommitment:
|
||||
|
||||
```python
|
||||
def verify_kzg_proof(commitment_bytes: Bytes48,
|
||||
z: Bytes32,
|
||||
y: Bytes32,
|
||||
z_bytes: Bytes32,
|
||||
y_bytes: Bytes32,
|
||||
proof_bytes: Bytes48) -> bool:
|
||||
"""
|
||||
Verify KZG proof that ``p(z) == y`` where ``p(z)`` is the polynomial represented by ``polynomial_kzg``.
|
||||
Receives inputs as bytes.
|
||||
Public method.
|
||||
"""
|
||||
assert len(commitment_bytes) == BYTES_PER_COMMITMENT
|
||||
assert len(z_bytes) == BYTES_PER_FIELD_ELEMENT
|
||||
assert len(y_bytes) == BYTES_PER_FIELD_ELEMENT
|
||||
assert len(proof_bytes) == BYTES_PER_PROOF
|
||||
|
||||
return verify_kzg_proof_impl(bytes_to_kzg_commitment(commitment_bytes),
|
||||
bytes_to_bls_field(z),
|
||||
bytes_to_bls_field(y),
|
||||
bytes_to_bls_field(z_bytes),
|
||||
bytes_to_bls_field(y_bytes),
|
||||
bytes_to_kzg_proof(proof_bytes))
|
||||
```
|
||||
|
||||
@@ -429,14 +440,17 @@ def verify_kzg_proof_batch(commitments: Sequence[KZGCommitment],
|
||||
#### `compute_kzg_proof`
|
||||
|
||||
```python
|
||||
def compute_kzg_proof(blob: Blob, z: Bytes32) -> KZGProof:
|
||||
def compute_kzg_proof(blob: Blob, z_bytes: Bytes32) -> Tuple[KZGProof, Bytes32]:
|
||||
"""
|
||||
Compute KZG proof at point `z` for the polynomial represented by `blob`.
|
||||
Do this by computing the quotient polynomial in evaluation form: q(x) = (p(x) - p(z)) / (x - z).
|
||||
Public method.
|
||||
"""
|
||||
assert len(blob) == BYTES_PER_BLOB
|
||||
assert len(z_bytes) == BYTES_PER_FIELD_ELEMENT
|
||||
polynomial = blob_to_polynomial(blob)
|
||||
return compute_kzg_proof_impl(polynomial, bytes_to_bls_field(z))
|
||||
proof, y = compute_kzg_proof_impl(polynomial, bytes_to_bls_field(z_bytes))
|
||||
return proof, y.to_bytes(BYTES_PER_FIELD_ELEMENT, ENDIANNESS)
|
||||
```
|
||||
|
||||
#### `compute_quotient_eval_within_domain`
|
||||
@@ -470,7 +484,7 @@ def compute_quotient_eval_within_domain(z: BLSFieldElement,
|
||||
#### `compute_kzg_proof_impl`
|
||||
|
||||
```python
|
||||
def compute_kzg_proof_impl(polynomial: Polynomial, z: BLSFieldElement) -> KZGProof:
|
||||
def compute_kzg_proof_impl(polynomial: Polynomial, z: BLSFieldElement) -> Tuple[KZGProof, BLSFieldElement]:
|
||||
"""
|
||||
Helper function for `compute_kzg_proof()` and `compute_blob_kzg_proof()`.
|
||||
"""
|
||||
@@ -494,21 +508,25 @@ def compute_kzg_proof_impl(polynomial: Polynomial, z: BLSFieldElement) -> KZGPro
|
||||
# Compute: q(x_i) = (p(x_i) - p(z)) / (x_i - z).
|
||||
quotient_polynomial[i] = div(a, b)
|
||||
|
||||
return KZGProof(g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), quotient_polynomial))
|
||||
return KZGProof(g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), quotient_polynomial)), y
|
||||
```
|
||||
|
||||
#### `compute_blob_kzg_proof`
|
||||
|
||||
```python
|
||||
def compute_blob_kzg_proof(blob: Blob) -> KZGProof:
|
||||
def compute_blob_kzg_proof(blob: Blob, commitment_bytes: Bytes48) -> KZGProof:
|
||||
"""
|
||||
Given a blob, return the KZG proof that is used to verify it against the commitment.
|
||||
This method does not verify that the commitment is correct with respect to `blob`.
|
||||
Public method.
|
||||
"""
|
||||
commitment = blob_to_kzg_commitment(blob)
|
||||
assert len(blob) == BYTES_PER_BLOB
|
||||
assert len(commitment_bytes) == BYTES_PER_COMMITMENT
|
||||
commitment = bytes_to_kzg_commitment(commitment_bytes)
|
||||
polynomial = blob_to_polynomial(blob)
|
||||
evaluation_challenge = compute_challenge(blob, commitment)
|
||||
return compute_kzg_proof_impl(polynomial, evaluation_challenge)
|
||||
proof, _ = compute_kzg_proof_impl(polynomial, evaluation_challenge)
|
||||
return proof
|
||||
```
|
||||
|
||||
#### `verify_blob_kzg_proof`
|
||||
@@ -522,6 +540,10 @@ def verify_blob_kzg_proof(blob: Blob,
|
||||
|
||||
Public method.
|
||||
"""
|
||||
assert len(blob) == BYTES_PER_BLOB
|
||||
assert len(commitment_bytes) == BYTES_PER_COMMITMENT
|
||||
assert len(proof_bytes) == BYTES_PER_PROOF
|
||||
|
||||
commitment = bytes_to_kzg_commitment(commitment_bytes)
|
||||
|
||||
polynomial = blob_to_polynomial(blob)
|
||||
@@ -551,6 +573,9 @@ def verify_blob_kzg_proof_batch(blobs: Sequence[Blob],
|
||||
|
||||
commitments, evaluation_challenges, ys, proofs = [], [], [], []
|
||||
for blob, commitment_bytes, proof_bytes in zip(blobs, commitments_bytes, proofs_bytes):
|
||||
assert len(blob) == BYTES_PER_BLOB
|
||||
assert len(commitment_bytes) == BYTES_PER_COMMITMENT
|
||||
assert len(proof_bytes) == BYTES_PER_PROOF
|
||||
commitment = bytes_to_kzg_commitment(commitment_bytes)
|
||||
commitments.append(commitment)
|
||||
polynomial = blob_to_polynomial(blob)
|
||||
|
||||
@@ -96,7 +96,7 @@ def get_blob_sidecars(block: BeaconBlock, blobs: Sequence[Blob]) -> Sequence[Blo
|
||||
block_parent_root=block.parent_root,
|
||||
blob=blob,
|
||||
kzg_commitment=block.body.blob_kzg_commitments[index],
|
||||
kzg_proof=compute_blob_kzg_proof(blob),
|
||||
kzg_proof=compute_blob_kzg_proof(blob, block.body.blob_kzg_commitments[index]),
|
||||
)
|
||||
for index, blob in enumerate(blobs)
|
||||
]
|
||||
|
||||
@@ -42,14 +42,12 @@ def test_verify_kzg_proof(spec):
|
||||
"""
|
||||
Test the wrapper functions (taking bytes arguments) for computing and verifying KZG proofs.
|
||||
"""
|
||||
x = 3
|
||||
x = field_element_bytes(3)
|
||||
blob = get_sample_blob(spec)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
polynomial = spec.blob_to_polynomial(blob)
|
||||
proof = spec.compute_kzg_proof(blob, field_element_bytes(x))
|
||||
proof, y = spec.compute_kzg_proof(blob, x)
|
||||
|
||||
y = spec.evaluate_polynomial_in_evaluation_form(polynomial, x)
|
||||
assert spec.verify_kzg_proof(commitment, field_element_bytes(x), field_element_bytes(y), proof)
|
||||
assert spec.verify_kzg_proof(commitment, x, y, proof)
|
||||
|
||||
|
||||
@with_deneb_and_later
|
||||
@@ -59,15 +57,13 @@ def test_verify_kzg_proof_incorrect_proof(spec):
|
||||
"""
|
||||
Test the wrapper function `verify_kzg_proof` fails on an incorrect proof.
|
||||
"""
|
||||
x = 3465
|
||||
x = field_element_bytes(3465)
|
||||
blob = get_sample_blob(spec)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
polynomial = spec.blob_to_polynomial(blob)
|
||||
proof = spec.compute_kzg_proof(blob, field_element_bytes(x))
|
||||
proof, y = spec.compute_kzg_proof(blob, x)
|
||||
proof = bls_add_one(proof)
|
||||
|
||||
y = spec.evaluate_polynomial_in_evaluation_form(polynomial, x)
|
||||
assert not spec.verify_kzg_proof(commitment, field_element_bytes(x), field_element_bytes(y), proof)
|
||||
assert not spec.verify_kzg_proof(commitment, x, y, proof)
|
||||
|
||||
|
||||
@with_deneb_and_later
|
||||
@@ -81,9 +77,8 @@ def test_verify_kzg_proof_impl(spec):
|
||||
blob = get_sample_blob(spec)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
polynomial = spec.blob_to_polynomial(blob)
|
||||
proof = spec.compute_kzg_proof_impl(polynomial, x)
|
||||
proof, y = spec.compute_kzg_proof_impl(polynomial, x)
|
||||
|
||||
y = spec.evaluate_polynomial_in_evaluation_form(polynomial, x)
|
||||
assert spec.verify_kzg_proof_impl(commitment, x, y, proof)
|
||||
|
||||
|
||||
@@ -98,10 +93,9 @@ def test_verify_kzg_proof_impl_incorrect_proof(spec):
|
||||
blob = get_sample_blob(spec)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
polynomial = spec.blob_to_polynomial(blob)
|
||||
proof = spec.compute_kzg_proof_impl(polynomial, x)
|
||||
proof, y = spec.compute_kzg_proof_impl(polynomial, x)
|
||||
proof = bls_add_one(proof)
|
||||
|
||||
y = spec.evaluate_polynomial_in_evaluation_form(polynomial, x)
|
||||
assert not spec.verify_kzg_proof_impl(commitment, x, y, proof)
|
||||
|
||||
|
||||
@@ -187,9 +181,8 @@ def test_compute_kzg_proof_within_domain(spec):
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.ROOTS_OF_UNITY)
|
||||
|
||||
for i, z in enumerate(roots_of_unity_brp):
|
||||
proof = spec.compute_kzg_proof_impl(polynomial, z)
|
||||
proof, y = spec.compute_kzg_proof_impl(polynomial, z)
|
||||
|
||||
y = spec.evaluate_polynomial_in_evaluation_form(polynomial, z)
|
||||
assert spec.verify_kzg_proof_impl(commitment, z, y, proof)
|
||||
|
||||
|
||||
@@ -202,7 +195,7 @@ def test_verify_blob_kzg_proof(spec):
|
||||
"""
|
||||
blob = get_sample_blob(spec)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment)
|
||||
|
||||
assert spec.verify_blob_kzg_proof(blob, commitment, proof)
|
||||
|
||||
@@ -216,7 +209,7 @@ def test_verify_blob_kzg_proof_incorrect_proof(spec):
|
||||
"""
|
||||
blob = get_sample_blob(spec)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment)
|
||||
proof = bls_add_one(proof)
|
||||
|
||||
assert not spec.verify_blob_kzg_proof(blob, commitment, proof)
|
||||
|
||||
@@ -9,10 +9,12 @@ The test data is declared in a `data.yaml` file:
|
||||
```yaml
|
||||
input:
|
||||
blob: Blob -- the data blob
|
||||
commitment: Bytes48 -- the commitment to the blob
|
||||
output: KZGProof -- The blob KZG proof
|
||||
```
|
||||
|
||||
- `blob` here is encoded as a string: hexadecimal encoding of `4096 * 32 = 131072` bytes, prefixed with `0x`.
|
||||
- `commitment` here is encoded as a string: hexadecimal encoding of `48` bytes, prefixed with `0x`.
|
||||
|
||||
All byte(s) fields are encoded as strings, hexadecimal encoding, prefixed with `0x`.
|
||||
|
||||
|
||||
@@ -10,14 +10,15 @@ The test data is declared in a `data.yaml` file:
|
||||
input:
|
||||
blob: Blob -- the data blob representing a polynomial
|
||||
z: Bytes32 -- bytes encoding the BLS field element at which the polynomial should be evaluated
|
||||
output: KZGProof -- The KZG proof
|
||||
output: Tuple[KZGProof, Bytes32] -- The KZG proof and the value y = f(z)
|
||||
```
|
||||
|
||||
- `blob` here is encoded as a string: hexadecimal encoding of `4096 * 32 = 131072` bytes, prefixed with `0x`.
|
||||
- `z` here is encoded as a string: hexadecimal encoding of `32` bytes representing a little endian encoded field element, prefixed with `0x`.
|
||||
- `y` here is encoded as a string: hexadecimal encoding of `32` bytes representing a little endian encoded field element, prefixed with `0x`.
|
||||
|
||||
All byte(s) fields are encoded as strings, hexadecimal encoding, prefixed with `0x`.
|
||||
|
||||
## Condition
|
||||
|
||||
The `compute_kzg_proof` handler should compute the KZG proof for evaluating the polynomial represented by `blob` at `z`, and the result should match the expected `output`. If the blob is invalid (e.g. incorrect length or one of the 32-byte blocks does not represent a BLS field element) or `z` is not a valid BLS field element, it should error, i.e. the output should be `null`.
|
||||
The `compute_kzg_proof` handler should compute the KZG proof as well as the value `y` for evaluating the polynomial represented by `blob` at `z`, and the result should match the expected `output`. If the blob is invalid (e.g. incorrect length or one of the 32-byte blocks does not represent a BLS field element) or `z` is not a valid BLS field element, it should error, i.e. the output should be `null`.
|
||||
|
||||
@@ -27,7 +27,11 @@ def expect_exception(func, *args):
|
||||
|
||||
|
||||
def field_element_bytes(x):
|
||||
return int.to_bytes(x % spec.BLS_MODULUS, 32, "little")
|
||||
return int.to_bytes(x % spec.BLS_MODULUS, 32, spec.ENDIANNESS)
|
||||
|
||||
|
||||
def field_element_bytes_unchecked(x):
|
||||
return int.to_bytes(x, 32, spec.ENDIANNESS)
|
||||
|
||||
|
||||
def encode_hex_list(a):
|
||||
@@ -67,13 +71,30 @@ BLOB_INVALID = spec.Blob(b'\xFF' * 4096 * 32)
|
||||
BLOB_INVALID_CLOSE = spec.Blob(b''.join(
|
||||
[BLS_MODULUS_BYTES if n == 2111 else field_element_bytes(0) for n in range(4096)]
|
||||
))
|
||||
BLOB_INVALID_LENGTH_PLUS_ONE = BLOB_RANDOM_VALID1 + b"\x00"
|
||||
BLOB_INVALID_LENGTH_MINUS_ONE = BLOB_RANDOM_VALID1[:-1]
|
||||
|
||||
VALID_BLOBS = [BLOB_ALL_ZEROS, BLOB_RANDOM_VALID1, BLOB_RANDOM_VALID2,
|
||||
BLOB_RANDOM_VALID3, BLOB_ALL_MODULUS_MINUS_ONE, BLOB_ALMOST_ZERO]
|
||||
INVALID_BLOBS = [BLOB_INVALID, BLOB_INVALID_CLOSE]
|
||||
VALID_ZS = [field_element_bytes(x) for x in [0, 1, 2, pow(5, 1235, spec.BLS_MODULUS),
|
||||
spec.BLS_MODULUS - 1, spec.ROOTS_OF_UNITY[1]]]
|
||||
INVALID_ZS = [x.to_bytes(32, spec.ENDIANNESS) for x in [spec.BLS_MODULUS, 2**256 - 1, 2**256 - 2**128]]
|
||||
INVALID_BLOBS = [BLOB_INVALID, BLOB_INVALID_CLOSE, BLOB_INVALID_LENGTH_PLUS_ONE, BLOB_INVALID_LENGTH_MINUS_ONE]
|
||||
|
||||
FE_VALID1 = field_element_bytes(0)
|
||||
FE_VALID2 = field_element_bytes(1)
|
||||
FE_VALID3 = field_element_bytes(2)
|
||||
FE_VALID4 = field_element_bytes(pow(5, 1235, spec.BLS_MODULUS))
|
||||
FE_VALID5 = field_element_bytes(spec.BLS_MODULUS - 1)
|
||||
FE_VALID6 = field_element_bytes(spec.ROOTS_OF_UNITY[1])
|
||||
VALID_FIELD_ELEMENTS = [FE_VALID1, FE_VALID2, FE_VALID3, FE_VALID4, FE_VALID5, FE_VALID6]
|
||||
|
||||
FE_INVALID_EQUAL_TO_MODULUS = field_element_bytes_unchecked(spec.BLS_MODULUS)
|
||||
FE_INVALID_MODULUS_PLUS_ONE = field_element_bytes_unchecked(spec.BLS_MODULUS + 1)
|
||||
FE_INVALID_UINT256_MAX = field_element_bytes_unchecked(2**256 - 1)
|
||||
FE_INVALID_UINT256_MID = field_element_bytes_unchecked(2**256 - 2**128)
|
||||
FE_INVALID_LENGTH_PLUS_ONE = VALID_FIELD_ELEMENTS[0] + b"\x00"
|
||||
FE_INVALID_LENGTH_MINUS_ONE = VALID_FIELD_ELEMENTS[0][:-1]
|
||||
INVALID_FIELD_ELEMENTS = [FE_INVALID_EQUAL_TO_MODULUS, FE_INVALID_MODULUS_PLUS_ONE,
|
||||
FE_INVALID_UINT256_MAX, FE_INVALID_UINT256_MID,
|
||||
FE_INVALID_LENGTH_PLUS_ONE, FE_INVALID_LENGTH_MINUS_ONE]
|
||||
|
||||
|
||||
def hash(x):
|
||||
@@ -114,20 +135,20 @@ def case01_blob_to_kzg_commitment():
|
||||
def case02_compute_kzg_proof():
|
||||
# Valid cases
|
||||
for blob in VALID_BLOBS:
|
||||
for z in VALID_ZS:
|
||||
proof = spec.compute_kzg_proof(blob, z)
|
||||
for z in VALID_FIELD_ELEMENTS:
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'compute_kzg_proof_case_valid_blob_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'z': encode_hex(z),
|
||||
},
|
||||
'output': encode_hex(proof)
|
||||
'output': (encode_hex(proof), encode_hex(y))
|
||||
}
|
||||
|
||||
# Edge case: Invalid blobs
|
||||
for blob in INVALID_BLOBS:
|
||||
z = VALID_ZS[0]
|
||||
z = VALID_FIELD_ELEMENTS[0]
|
||||
expect_exception(spec.compute_kzg_proof, blob, z)
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'compute_kzg_proof_case_invalid_blob_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
@@ -139,7 +160,7 @@ def case02_compute_kzg_proof():
|
||||
}
|
||||
|
||||
# Edge case: Invalid z
|
||||
for z in INVALID_ZS:
|
||||
for z in INVALID_FIELD_ELEMENTS:
|
||||
blob = VALID_BLOBS[4]
|
||||
expect_exception(spec.compute_kzg_proof, blob, z)
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
@@ -155,10 +176,9 @@ def case02_compute_kzg_proof():
|
||||
def case03_verify_kzg_proof():
|
||||
# Valid cases
|
||||
for blob in VALID_BLOBS:
|
||||
for z in VALID_ZS:
|
||||
proof = spec.compute_kzg_proof(blob, z)
|
||||
for z in VALID_FIELD_ELEMENTS:
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
y = evaluate_blob_at(blob, z)
|
||||
assert spec.verify_kzg_proof(commitment, z, y, proof)
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'verify_kzg_proof_case_correct_proof_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
@@ -173,10 +193,10 @@ def case03_verify_kzg_proof():
|
||||
|
||||
# Incorrect proofs
|
||||
for blob in VALID_BLOBS:
|
||||
for z in VALID_ZS:
|
||||
proof = bls_add_one(spec.compute_kzg_proof(blob, z))
|
||||
for z in VALID_FIELD_ELEMENTS:
|
||||
proof_orig, y = spec.compute_kzg_proof(blob, z)
|
||||
proof = bls_add_one(proof_orig)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
y = evaluate_blob_at(blob, z)
|
||||
assert not spec.verify_kzg_proof(commitment, z, y, proof)
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'verify_kzg_proof_case_incorrect_proof_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
@@ -190,11 +210,10 @@ def case03_verify_kzg_proof():
|
||||
}
|
||||
|
||||
# Edge case: Invalid z
|
||||
for z in INVALID_ZS:
|
||||
blob, validz = VALID_BLOBS[4], VALID_ZS[1]
|
||||
proof = spec.compute_kzg_proof(blob, validz)
|
||||
for z in INVALID_FIELD_ELEMENTS:
|
||||
blob, validz = VALID_BLOBS[4], VALID_FIELD_ELEMENTS[1]
|
||||
proof, y = spec.compute_kzg_proof(blob, validz)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
y = VALID_ZS[3]
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'verify_kzg_proof_case_invalid_z_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
@@ -208,26 +227,27 @@ def case03_verify_kzg_proof():
|
||||
}
|
||||
|
||||
# Edge case: Invalid y
|
||||
blob, z = VALID_BLOBS[1], VALID_ZS[1]
|
||||
proof = spec.compute_kzg_proof(blob, z)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
y = INVALID_ZS[0]
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_invalid_y', {
|
||||
'input': {
|
||||
'commitment': encode_hex(commitment),
|
||||
'z': encode_hex(z),
|
||||
'y': encode_hex(y),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
for y in INVALID_FIELD_ELEMENTS:
|
||||
blob, z = VALID_BLOBS[4], VALID_FIELD_ELEMENTS[1]
|
||||
proof, _ = spec.compute_kzg_proof(blob, z)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(y)}'
|
||||
yield f'verify_kzg_proof_case_invalid_y_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
'input': {
|
||||
'commitment': encode_hex(commitment),
|
||||
'z': encode_hex(z),
|
||||
'y': encode_hex(y),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, not in G1
|
||||
blob, z = VALID_BLOBS[2], VALID_ZS[0]
|
||||
blob, z = VALID_BLOBS[2], VALID_FIELD_ELEMENTS[0]
|
||||
proof = P1_NOT_IN_G1
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
y = VALID_ZS[1]
|
||||
y = VALID_FIELD_ELEMENTS[1]
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_proof_not_in_G1', {
|
||||
'input': {
|
||||
@@ -240,10 +260,10 @@ def case03_verify_kzg_proof():
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, not on curve
|
||||
blob, z = VALID_BLOBS[3], VALID_ZS[1]
|
||||
blob, z = VALID_BLOBS[3], VALID_FIELD_ELEMENTS[1]
|
||||
proof = P1_NOT_ON_CURVE
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
y = VALID_ZS[1]
|
||||
y = VALID_FIELD_ELEMENTS[1]
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_proof_not_on_curve', {
|
||||
'input': {
|
||||
@@ -255,11 +275,44 @@ def case03_verify_kzg_proof():
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, too few bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
z = VALID_FIELD_ELEMENTS[4]
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
proof = proof[:-1]
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_proof_too_few_bytes', {
|
||||
'input': {
|
||||
'commitment': encode_hex(commitment),
|
||||
'z': encode_hex(z),
|
||||
'y': encode_hex(y),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, too many bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
z = VALID_FIELD_ELEMENTS[4]
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
proof = proof + b"\x00"
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_proof_too_many_bytes', {
|
||||
'input': {
|
||||
'commitment': encode_hex(commitment),
|
||||
'z': encode_hex(z),
|
||||
'y': encode_hex(y),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, not in G1
|
||||
blob, z = VALID_BLOBS[4], VALID_ZS[3]
|
||||
proof = spec.compute_kzg_proof(blob, z)
|
||||
blob, z = VALID_BLOBS[4], VALID_FIELD_ELEMENTS[3]
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
commitment = P1_NOT_IN_G1
|
||||
y = VALID_ZS[2]
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_commitment_not_in_G1', {
|
||||
'input': {
|
||||
@@ -272,10 +325,9 @@ def case03_verify_kzg_proof():
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, not on curve
|
||||
blob, z = VALID_BLOBS[1], VALID_ZS[4]
|
||||
proof = spec.compute_kzg_proof(blob, z)
|
||||
blob, z = VALID_BLOBS[1], VALID_FIELD_ELEMENTS[4]
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
commitment = P1_NOT_ON_CURVE
|
||||
y = VALID_ZS[3]
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_commitment_not_on_curve', {
|
||||
'input': {
|
||||
@@ -287,36 +339,98 @@ def case03_verify_kzg_proof():
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, too few bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob)[:-1]
|
||||
z = VALID_FIELD_ELEMENTS[4]
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_commitment_too_few_bytes', {
|
||||
'input': {
|
||||
'commitment': encode_hex(commitment),
|
||||
'z': encode_hex(z),
|
||||
'y': encode_hex(y),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, too many bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob) + b"\x00"
|
||||
z = VALID_FIELD_ELEMENTS[4]
|
||||
proof, y = spec.compute_kzg_proof(blob, z)
|
||||
expect_exception(spec.verify_kzg_proof, commitment, z, y, proof)
|
||||
yield 'verify_kzg_proof_case_commitment_too_many_bytes', {
|
||||
'input': {
|
||||
'commitment': encode_hex(commitment),
|
||||
'z': encode_hex(z),
|
||||
'y': encode_hex(y),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
|
||||
def case04_compute_blob_kzg_proof():
|
||||
# Valid cases
|
||||
for blob in VALID_BLOBS:
|
||||
proof = spec.compute_blob_kzg_proof(blob)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment)
|
||||
identifier = f'{encode_hex(hash(blob))}'
|
||||
yield f'compute_blob_kzg_proof_case_valid_blob_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
},
|
||||
'output': encode_hex(proof)
|
||||
}
|
||||
|
||||
# Edge case: Invalid blob
|
||||
for blob in INVALID_BLOBS:
|
||||
expect_exception(spec.compute_blob_kzg_proof, blob)
|
||||
commitment = G1
|
||||
expect_exception(spec.compute_blob_kzg_proof, blob, commitment)
|
||||
identifier = f'{encode_hex(hash(blob))}'
|
||||
yield f'compute_blob_kzg_proof_case_invalid_blob_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, not in G1
|
||||
commitment = P1_NOT_IN_G1
|
||||
blob = VALID_BLOBS[1]
|
||||
expect_exception(spec.compute_blob_kzg_proof, blob, commitment)
|
||||
identifier = f'{encode_hex(hash(blob))}'
|
||||
yield 'compute_blob_kzg_proof_case_invalid_commitment_not_in_G1', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, not on curve
|
||||
commitment = P1_NOT_ON_CURVE
|
||||
blob = VALID_BLOBS[1]
|
||||
expect_exception(spec.compute_blob_kzg_proof, blob, commitment)
|
||||
identifier = f'{encode_hex(hash(blob))}'
|
||||
yield 'compute_blob_kzg_proof_case_invalid_commitment_not_on_curve', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
|
||||
def case05_verify_blob_kzg_proof():
|
||||
# Valid cases
|
||||
for blob in VALID_BLOBS:
|
||||
proof = spec.compute_blob_kzg_proof(blob)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment)
|
||||
assert spec.verify_blob_kzg_proof(blob, commitment, proof)
|
||||
identifier = f'{encode_hex(hash(blob))}'
|
||||
yield f'verify_blob_kzg_proof_case_correct_proof_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
@@ -330,8 +444,8 @@ def case05_verify_blob_kzg_proof():
|
||||
|
||||
# Incorrect proofs
|
||||
for blob in VALID_BLOBS:
|
||||
proof = bls_add_one(spec.compute_blob_kzg_proof(blob))
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = bls_add_one(spec.compute_blob_kzg_proof(blob, commitment))
|
||||
assert not spec.verify_blob_kzg_proof(blob, commitment, proof)
|
||||
identifier = f'{encode_hex(hash(blob))}'
|
||||
yield f'verify_blob_kzg_proof_case_incorrect_proof_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
@@ -371,6 +485,34 @@ def case05_verify_blob_kzg_proof():
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, too few bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment)[:-1]
|
||||
expect_exception(spec.verify_blob_kzg_proof, blob, commitment, proof)
|
||||
yield 'verify_blob_kzg_proof_case_proof_too_few_bytes', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, too many bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment) + b"\x00"
|
||||
expect_exception(spec.verify_blob_kzg_proof, blob, commitment, proof)
|
||||
yield 'verify_blob_kzg_proof_case_proof_too_many_bytes', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, not in G1
|
||||
blob = VALID_BLOBS[0]
|
||||
proof = G1
|
||||
@@ -399,6 +541,36 @@ def case05_verify_blob_kzg_proof():
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, too few bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment)
|
||||
commitment = commitment[:-1]
|
||||
expect_exception(spec.verify_blob_kzg_proof, blob, commitment, proof)
|
||||
yield 'verify_blob_kzg_proof_case_commitment_too_few_bytes', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, too many bytes
|
||||
blob = VALID_BLOBS[1]
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.compute_blob_kzg_proof(blob, commitment)
|
||||
commitment = commitment + b"\x00"
|
||||
expect_exception(spec.verify_blob_kzg_proof, blob, commitment, proof)
|
||||
yield 'verify_blob_kzg_proof_case_commitment_too_many_bytes', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid blob
|
||||
for blob in INVALID_BLOBS:
|
||||
proof = G1
|
||||
@@ -420,8 +592,8 @@ def case06_verify_blob_kzg_proof_batch():
|
||||
proofs = []
|
||||
commitments = []
|
||||
for blob in VALID_BLOBS:
|
||||
proofs.append(spec.compute_blob_kzg_proof(blob))
|
||||
commitments.append(spec.blob_to_kzg_commitment(blob))
|
||||
proofs.append(spec.compute_blob_kzg_proof(blob, commitments[-1]))
|
||||
|
||||
for i in range(len(proofs)):
|
||||
assert spec.verify_blob_kzg_proof_batch(VALID_BLOBS[:i], commitments[:i], proofs[:i])
|
||||
@@ -447,6 +619,20 @@ def case06_verify_blob_kzg_proof_batch():
|
||||
'output': False
|
||||
}
|
||||
|
||||
# Edge case: Invalid blobs
|
||||
for blob in INVALID_BLOBS:
|
||||
blobs_invalid = VALID_BLOBS[:4] + [blob] + VALID_BLOBS[5:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, blobs_invalid, commitments, proofs)
|
||||
identifier = f'{encode_hex(hash(blob))}'
|
||||
yield f'verify_blob_kzg_proof_batch_case_invalid_blob_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
|
||||
'input': {
|
||||
'blobs': encode_hex_list(blobs_invalid),
|
||||
'commitments': encode_hex_list(commitments),
|
||||
'proofs': encode_hex_list(proofs),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, not in G1
|
||||
proofs_invalid_notG1 = [P1_NOT_IN_G1] + proofs[1:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, VALID_BLOBS, commitments, proofs_invalid_notG1)
|
||||
@@ -471,6 +657,30 @@ def case06_verify_blob_kzg_proof_batch():
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, too few bytes
|
||||
proofs_invalid_tooFewBytes = proofs[:1] + [proofs[1][:-1]] + proofs[2:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, VALID_BLOBS, commitments, proofs_invalid_tooFewBytes)
|
||||
yield 'verify_blob_kzg_proof_batch_case_proof_too_few_bytes', {
|
||||
'input': {
|
||||
'blobs': encode_hex_list(VALID_BLOBS),
|
||||
'commitments': encode_hex_list(commitments),
|
||||
'proofs': encode_hex_list(proofs_invalid_tooFewBytes),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid proof, too many bytes
|
||||
proofs_invalid_tooManyBytes = proofs[:1] + [proofs[1] + b"\x00"] + proofs[2:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, VALID_BLOBS, commitments, proofs_invalid_tooManyBytes)
|
||||
yield 'verify_blob_kzg_proof_batch_case_proof_too_many_bytes', {
|
||||
'input': {
|
||||
'blobs': encode_hex_list(VALID_BLOBS),
|
||||
'commitments': encode_hex_list(commitments),
|
||||
'proofs': encode_hex_list(proofs_invalid_tooManyBytes),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, not in G1
|
||||
commitments_invalid_notG1 = commitments[:2] + [P1_NOT_IN_G1] + commitments[3:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, VALID_BLOBS, commitments, commitments_invalid_notG1)
|
||||
@@ -495,13 +705,25 @@ def case06_verify_blob_kzg_proof_batch():
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid blob
|
||||
blobs_invalid = VALID_BLOBS[:4] + [BLOB_INVALID] + VALID_BLOBS[5:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, blobs_invalid, commitments, proofs)
|
||||
yield 'verify_blob_kzg_proof_batch_case_invalid_blob', {
|
||||
# Edge case: Invalid commitment, too few bytes
|
||||
commitments_invalid_tooFewBytes = commitments[:3] + [commitments[3][:-1]] + commitments[4:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, VALID_BLOBS, commitments, commitments_invalid_tooFewBytes)
|
||||
yield 'verify_blob_kzg_proof_batch_case_too_few_bytes', {
|
||||
'input': {
|
||||
'blobs': encode_hex_list(blobs_invalid),
|
||||
'commitments': encode_hex_list(commitments),
|
||||
'blobs': encode_hex_list(VALID_BLOBS),
|
||||
'commitments': encode_hex_list(commitments_invalid_tooFewBytes),
|
||||
'proofs': encode_hex_list(proofs),
|
||||
},
|
||||
'output': None
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment, too many bytes
|
||||
commitments_invalid_tooManyBytes = commitments[:3] + [commitments[3] + b"\x00"] + commitments[4:]
|
||||
expect_exception(spec.verify_blob_kzg_proof_batch, VALID_BLOBS, commitments, commitments_invalid_tooManyBytes)
|
||||
yield 'verify_blob_kzg_proof_batch_case_too_many_bytes', {
|
||||
'input': {
|
||||
'blobs': encode_hex_list(VALID_BLOBS),
|
||||
'commitments': encode_hex_list(commitments_invalid_tooManyBytes),
|
||||
'proofs': encode_hex_list(proofs),
|
||||
},
|
||||
'output': None
|
||||
|
||||
Reference in New Issue
Block a user