mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-03 06:13:31 +00:00
EIP4844: Implement reverse bit ordering in KZG commitments
Co-authored-by: Dankrad Feist <mail@dankradfeist.de> Co-authored-by: Hsiao-Wei Wang <hsiaowei.eth@gmail.com>
This commit is contained in:
parent
189d61e386
commit
f4ba8b55ee
9
setup.py
9
setup.py
@ -589,9 +589,16 @@ from eth2spec.bellatrix import {preset_name} as bellatrix
|
||||
from eth2spec.utils.ssz.ssz_impl import serialize as ssz_serialize
|
||||
'''
|
||||
|
||||
|
||||
@classmethod
|
||||
def preparations(cls):
|
||||
return super().preparations() + '\n' + '''
|
||||
T = TypeVar('T') # For generic function
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def sundry_functions(cls) -> str:
|
||||
return super().sundry_functions() + '''
|
||||
return super().sundry_functions() + '\n\n' + '''
|
||||
# TODO: for mainnet, load pre-generated trusted setup file to reduce building time.
|
||||
# TESTING_FIELD_ELEMENTS_PER_BLOB is hardcoded copy from minimal presets
|
||||
TESTING_FIELD_ELEMENTS_PER_BLOB = 4
|
||||
|
@ -12,6 +12,10 @@
|
||||
- [Preset](#preset)
|
||||
- [Trusted setup](#trusted-setup)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Bit-reversal permutation](#bit-reversal-permutation)
|
||||
- [`is_power_of_two`](#is_power_of_two)
|
||||
- [`reverse_bits`](#reverse_bits)
|
||||
- [`bit_reversal_permutation`](#bit_reversal_permutation)
|
||||
- [BLS12-381 helpers](#bls12-381-helpers)
|
||||
- [`bls_modular_inverse`](#bls_modular_inverse)
|
||||
- [`div`](#div)
|
||||
@ -64,6 +68,47 @@ but reusing the `mainnet` settings in public networks is a critical security req
|
||||
|
||||
## Helper functions
|
||||
|
||||
### Bit-reversal permutation
|
||||
|
||||
All polynomials (which are always given in Lagrange form) should be interpreted as being in
|
||||
bit-reversal permutation. In practice, clients can implement this by storing the lists
|
||||
`KZG_SETUP_LAGRANGE` and `ROOTS_OF_UNITY` in bit-reversal permutation, so these functions only
|
||||
have to be called once at startup.
|
||||
|
||||
#### `is_power_of_two`
|
||||
|
||||
```python
|
||||
def is_power_of_two(value: int) -> bool:
|
||||
"""
|
||||
Check if ``value`` is a power of two integer.
|
||||
"""
|
||||
return (value > 0) and (value & (value - 1) == 0)
|
||||
```
|
||||
|
||||
#### `reverse_bits`
|
||||
|
||||
```python
|
||||
def reverse_bits(n: int, order: int) -> int:
|
||||
"""
|
||||
Reverse the bit order of an integer n
|
||||
"""
|
||||
assert is_power_of_two(order)
|
||||
# Convert n to binary with the same number of bits as "order" - 1, then reverse its bit order
|
||||
return int(('{:0' + str(order.bit_length() - 1) + 'b}').format(n)[::-1], 2)
|
||||
```
|
||||
|
||||
#### `bit_reversal_permutation`
|
||||
|
||||
```python
|
||||
def bit_reversal_permutation(l: Sequence[T]) -> Sequence[T]:
|
||||
"""
|
||||
Return a copy with bit-reversed permutation. This operation is idempotent.
|
||||
|
||||
The input and output are a sequence of generic type ``T`` objects.
|
||||
"""
|
||||
return [l[reverse_bits(i, len(l))] for i in range(len(l))]
|
||||
```
|
||||
|
||||
### BLS12-381 helpers
|
||||
|
||||
#### `bls_modular_inverse`
|
||||
@ -123,7 +168,7 @@ KZG core functions. These are also defined in EIP-4844 execution specs.
|
||||
|
||||
```python
|
||||
def blob_to_kzg_commitment(blob: Blob) -> KZGCommitment:
|
||||
return g1_lincomb(KZG_SETUP_LAGRANGE, blob)
|
||||
return g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), blob)
|
||||
```
|
||||
|
||||
#### `verify_kzg_proof`
|
||||
@ -149,7 +194,9 @@ def verify_kzg_proof(polynomial_kzg: KZGCommitment,
|
||||
|
||||
```python
|
||||
def compute_kzg_proof(polynomial: Sequence[BLSFieldElement], z: BLSFieldElement) -> KZGProof:
|
||||
"""Compute KZG proof at point `z` with `polynomial` being in evaluation form"""
|
||||
"""
|
||||
Compute KZG proof at point `z` with `polynomial` being in evaluation form
|
||||
"""
|
||||
|
||||
# To avoid SSZ overflow/underflow, convert element into int
|
||||
polynomial = [int(i) for i in polynomial]
|
||||
@ -161,11 +208,11 @@ def compute_kzg_proof(polynomial: Sequence[BLSFieldElement], z: BLSFieldElement)
|
||||
|
||||
# Make sure we won't divide by zero during division
|
||||
assert z not in ROOTS_OF_UNITY
|
||||
denominator_poly = [(x - z) % BLS_MODULUS for x in ROOTS_OF_UNITY]
|
||||
denominator_poly = [(x - 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)]
|
||||
return KZGProof(g1_lincomb(KZG_SETUP_LAGRANGE, quotient_polynomial))
|
||||
return KZGProof(g1_lincomb(bit_reversal_permutation(KZG_SETUP_LAGRANGE), quotient_polynomial))
|
||||
```
|
||||
|
||||
### Polynomials
|
||||
@ -187,9 +234,11 @@ def evaluate_polynomial_in_evaluation_form(polynomial: Sequence[BLSFieldElement]
|
||||
# Make sure we won't divide by zero during division
|
||||
assert z not in ROOTS_OF_UNITY
|
||||
|
||||
roots_of_unity_brp = bit_reversal_permutation(ROOTS_OF_UNITY)
|
||||
|
||||
result = 0
|
||||
for i in range(width):
|
||||
result += div(int(polynomial[i]) * int(ROOTS_OF_UNITY[i]), (z - ROOTS_OF_UNITY[i]))
|
||||
result += div(int(polynomial[i]) * int(roots_of_unity_brp[i]), (z - roots_of_unity_brp[i]))
|
||||
result = result * (pow(z, width, BLS_MODULUS) - 1) * inverse_width % BLS_MODULUS
|
||||
return result
|
||||
```
|
||||
|
Loading…
x
Reference in New Issue
Block a user