Merge branch 'dev' into kzg_multi_verify

This commit is contained in:
dankrad 2023-02-15 18:10:39 +00:00 committed by GitHub
commit adb5134266
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 68 additions and 12 deletions

View File

@ -1169,7 +1169,7 @@ setup(
"pycryptodome==3.15.0",
"py_ecc==6.0.0",
"milagro_bls_binding==1.9.0",
"remerkleable==0.1.25",
"remerkleable==0.1.27",
"trie==2.0.2",
RUAMEL_YAML_VERSION,
"lru-dict==1.1.8",

View File

@ -242,7 +242,7 @@ class BeaconState(Container):
current_sync_committee: SyncCommittee
next_sync_committee: SyncCommittee
# Execution
latest_execution_payload_header: ExecutionPayloadHeader
latest_execution_payload_header: ExecutionPayloadHeader # [Modified in Capella]
# Withdrawals
next_withdrawal_index: WithdrawalIndex # [New in Capella]
next_withdrawal_validator_index: ValidatorIndex # [New in Capella]

View File

@ -108,11 +108,11 @@ class ExecutionPayload(Container):
timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256
excess_data_gas: uint256 # [New in Deneb]
# Extra payload fields
block_hash: Hash32 # Hash of execution block
transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
excess_data_gas: uint256 # [New in Deneb]
```
#### `ExecutionPayloadHeader`
@ -132,11 +132,11 @@ class ExecutionPayloadHeader(Container):
timestamp: uint64
extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
base_fee_per_gas: uint256
excess_data_gas: uint256 # [New in Deneb]
# Extra payload fields
block_hash: Hash32 # Hash of execution block
transactions_root: Root
withdrawals_root: Root
excess_data_gas: uint256 # [New in Deneb]
```
## Helper functions
@ -230,10 +230,10 @@ def process_execution_payload(state: BeaconState, payload: ExecutionPayload, exe
timestamp=payload.timestamp,
extra_data=payload.extra_data,
base_fee_per_gas=payload.base_fee_per_gas,
excess_data_gas=payload.excess_data_gas, # [New in Deneb]
block_hash=payload.block_hash,
transactions_root=hash_tree_root(payload.transactions),
withdrawals_root=hash_tree_root(payload.withdrawals),
excess_data_gas=payload.excess_data_gas, # [New in Deneb]
)
```

View File

@ -440,6 +440,34 @@ def compute_kzg_proof(blob: Blob, z: Bytes32) -> KZGProof:
return compute_kzg_proof_impl(polynomial, bytes_to_bls_field(z))
```
#### `compute_quotient_eval_within_domain`
```python
def compute_quotient_eval_within_domain(z: BLSFieldElement,
polynomial: Polynomial,
y: BLSFieldElement
) -> BLSFieldElement:
"""
Given `y == p(z)` for a polynomial `p(x)`, compute `q(z)`: the KZG quotient polynomial evaluated at `z` for the
special case where `z` is in `ROOTS_OF_UNITY`.
For more details, read https://dankradfeist.de/ethereum/2021/06/18/pcs-multiproofs.html section "Dividing
when one of the points is zero". The code below computes q(x_m) for the roots of unity special case.
"""
roots_of_unity_brp = bit_reversal_permutation(ROOTS_OF_UNITY)
result = 0
for i, omega_i in enumerate(roots_of_unity_brp):
if omega_i == z: # skip the evaluation point in the sum
continue
f_i = int(BLS_MODULUS) + int(polynomial[i]) - int(y) % BLS_MODULUS
numerator = f_i * int(omega_i) % BLS_MODULUS
denominator = int(z) * (int(BLS_MODULUS) + int(z) - int(omega_i)) % BLS_MODULUS
result += div(BLSFieldElement(numerator), BLSFieldElement(denominator))
return BLSFieldElement(result % BLS_MODULUS)
```
#### `compute_kzg_proof_impl`
```python
@ -447,16 +475,26 @@ def compute_kzg_proof_impl(polynomial: Polynomial, z: BLSFieldElement) -> KZGPro
"""
Helper function for compute_kzg_proof() and compute_aggregate_kzg_proof().
"""
roots_of_unity_brp = bit_reversal_permutation(ROOTS_OF_UNITY)
# For all x_i, compute p(x_i) - p(z)
y = evaluate_polynomial_in_evaluation_form(polynomial, z)
polynomial_shifted = [BLSFieldElement((int(p) - int(y)) % BLS_MODULUS) for p in polynomial]
# Make sure we won't divide by zero during division
assert z not in ROOTS_OF_UNITY
# For all x_i, compute (x_i - z)
denominator_poly = [BLSFieldElement((int(x) - int(z)) % BLS_MODULUS)
for x in bit_reversal_permutation(ROOTS_OF_UNITY)]
# Calculate quotient polynomial by doing point-by-point division
quotient_polynomial = [div(a, b) for a, b in zip(polynomial_shifted, denominator_poly)]
# Compute the quotient polynomial directly in evaluation form
quotient_polynomial = [BLSFieldElement(0)] * FIELD_ELEMENTS_PER_BLOB
for i, (a, b) in enumerate(zip(polynomial_shifted, denominator_poly)):
if b == 0:
# The denominator is zero hence `z` is a root of unity: we must handle it as a special case
quotient_polynomial[i] = compute_quotient_eval_within_domain(roots_of_unity_brp[i], polynomial, y)
else:
# 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))
```

View File

@ -87,3 +87,23 @@ def test_barycentric_within_domain(spec, state):
# The two evaluations should be agree and p(z) should also be the i-th "coefficient" of the polynomial in
# evaluation form
assert p_z_coeff == p_z_eval == poly_eval[i]
@with_deneb_and_later
@spec_state_test
def test_compute_kzg_proof_within_domain(spec, state):
"""
Create and verify KZG proof that p(z) == y
where z is in the domain of our KZG scheme (i.e. a relevant root of unity).
"""
blob = get_sample_blob(spec)
commitment = spec.blob_to_kzg_commitment(blob)
polynomial = spec.blob_to_polynomial(blob)
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)
y = spec.evaluate_polynomial_in_evaluation_form(polynomial, z)
assert spec.verify_kzg_proof_impl(commitment, z, y, proof)

View File

@ -29,14 +29,12 @@ def run_fork_test(post_spec, pre_state):
'inactivity_scores',
# Sync
'current_sync_committee', 'next_sync_committee',
# Execution
'latest_execution_payload_header',
]
for field in stable_fields:
assert getattr(pre_state, field) == getattr(post_state, field)
# Modified fields
modified_fields = ['fork']
modified_fields = ['fork', 'latest_execution_payload_header']
for field in modified_fields:
assert getattr(pre_state, field) != getattr(post_state, field)