Merge pull request #3523 from ethereum/dev
[DO NOT MERGE] release v1.4.0-beta.3
This commit is contained in:
commit
820f62d481
2
Makefile
2
Makefile
|
@ -212,7 +212,7 @@ gen_kzg_setups:
|
|||
if ! test -d venv; then python3 -m venv venv; fi; \
|
||||
. venv/bin/activate; \
|
||||
pip3 install -r requirements.txt; \
|
||||
python3 ./gen_kzg_trusted_setups.py --secret=1337 --g1-length=4 --g2-length=65 --output-dir ${CURRENT_DIR}/presets/minimal/trusted_setups; \
|
||||
python3 ./gen_kzg_trusted_setups.py --secret=1337 --g1-length=4096 --g2-length=65 --output-dir ${CURRENT_DIR}/presets/minimal/trusted_setups; \
|
||||
python3 ./gen_kzg_trusted_setups.py --secret=1337 --g1-length=4096 --g2-length=65 --output-dir ${CURRENT_DIR}/presets/mainnet/trusted_setups
|
||||
|
||||
# For any generator, build it using the run_generator function.
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -2,8 +2,8 @@
|
|||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
FIELD_ELEMENTS_PER_BLOB: 4
|
||||
# `uint64(4096)`
|
||||
FIELD_ELEMENTS_PER_BLOB: 4096
|
||||
# [customized]
|
||||
MAX_BLOB_COMMITMENTS_PER_BLOCK: 16
|
||||
# `uint64(6)`
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
23
setup.py
23
setup.py
|
@ -108,21 +108,14 @@ def _is_constant_id(name: str) -> bool:
|
|||
|
||||
|
||||
def _load_kzg_trusted_setups(preset_name):
|
||||
"""
|
||||
[TODO] it's not the final mainnet trusted setup.
|
||||
We will update it after the KZG ceremony.
|
||||
"""
|
||||
file_path = str(Path(__file__).parent) + '/presets/' + preset_name + '/trusted_setups/testing_trusted_setups.json'
|
||||
trusted_setups_file_path = str(Path(__file__).parent) + '/presets/' + preset_name + '/trusted_setups/trusted_setup_4096.json'
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
with open(trusted_setups_file_path, 'r') as f:
|
||||
json_data = json.load(f)
|
||||
trusted_setup_G1_lagrange = json_data['g1_lagrange']
|
||||
trusted_setup_G2_monomial = json_data['g2_monomial']
|
||||
|
||||
trusted_setup_G1 = json_data['setup_G1']
|
||||
trusted_setup_G2 = json_data['setup_G2']
|
||||
trusted_setup_G1_lagrange = json_data['setup_G1_lagrange']
|
||||
roots_of_unity = json_data['roots_of_unity']
|
||||
|
||||
return trusted_setup_G1, trusted_setup_G2, trusted_setup_G1_lagrange, roots_of_unity
|
||||
return trusted_setup_G2_monomial, trusted_setup_G1_lagrange
|
||||
|
||||
|
||||
ALL_KZG_SETUPS = {
|
||||
|
@ -158,10 +151,8 @@ def _parse_value(name: str, typed_value: str, type_hint: Optional[str] = None) -
|
|||
def _update_constant_vars_with_kzg_setups(constant_vars, preset_name):
|
||||
comment = "noqa: E501"
|
||||
kzg_setups = ALL_KZG_SETUPS[preset_name]
|
||||
constant_vars['KZG_SETUP_G1'] = VariableDefinition(constant_vars['KZG_SETUP_G1'].value, str(kzg_setups[0]), comment, None)
|
||||
constant_vars['KZG_SETUP_G2'] = VariableDefinition(constant_vars['KZG_SETUP_G2'].value, str(kzg_setups[1]), comment, None)
|
||||
constant_vars['KZG_SETUP_LAGRANGE'] = VariableDefinition(constant_vars['KZG_SETUP_LAGRANGE'].value, str(kzg_setups[2]), comment, None)
|
||||
constant_vars['ROOTS_OF_UNITY'] = VariableDefinition(constant_vars['ROOTS_OF_UNITY'].value, str(kzg_setups[3]), comment, None)
|
||||
constant_vars['KZG_SETUP_G2_MONOMIAL'] = VariableDefinition(constant_vars['KZG_SETUP_G2_MONOMIAL'].value, str(kzg_setups[0]), comment, None)
|
||||
constant_vars['KZG_SETUP_G1_LAGRANGE'] = VariableDefinition(constant_vars['KZG_SETUP_G1_LAGRANGE'].value, str(kzg_setups[1]), comment, None)
|
||||
|
||||
|
||||
def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str], preset_name=str) -> SpecObject:
|
||||
|
|
|
@ -52,7 +52,7 @@ Up to `MAX_CUSTODY_KEY_REVEALS`, [`CustodyKeyReveal`](./beacon-chain.md#custodyk
|
|||
|
||||
##### Early derived secret reveals
|
||||
|
||||
Up to `MAX_EARLY_DERIVED_SECRET_REVEALS`, [`EarlyDerivedSecretReveal`](./beacon-chain.md#earlyderivedsecretreveal) objects can be included in the `block`. The early derived secret reveals must satisfy the verification conditions found in [early derived secret reveal processing](beacon-chain.md#custody-key-reveals). The validator receives a small "whistleblower" reward for each early derived secrete reveal included.
|
||||
Up to `MAX_EARLY_DERIVED_SECRET_REVEALS`, [`EarlyDerivedSecretReveal`](./beacon-chain.md#earlyderivedsecretreveal) objects can be included in the `block`. The early derived secret reveals must satisfy the verification conditions found in [early derived secret reveal processing](beacon-chain.md#custody-key-reveals). The validator receives a small "whistleblower" reward for each early derived secret reveal included.
|
||||
|
||||
#### Construct attestation
|
||||
|
||||
|
|
|
@ -415,38 +415,21 @@ def get_initial_tracker(k: BLSFieldElement) -> WhiskTracker:
|
|||
```
|
||||
|
||||
```python
|
||||
def apply_deposit(state: BeaconState,
|
||||
pubkey: BLSPubkey,
|
||||
withdrawal_credentials: Bytes32,
|
||||
amount: uint64,
|
||||
signature: BLSSignature) -> None:
|
||||
validator_pubkeys = [validator.pubkey for validator in state.validators]
|
||||
if pubkey not in validator_pubkeys:
|
||||
# Verify the deposit signature (proof of possession) which is not checked by the deposit contract
|
||||
deposit_message = DepositMessage(
|
||||
pubkey=pubkey,
|
||||
withdrawal_credentials=withdrawal_credentials,
|
||||
amount=amount,
|
||||
)
|
||||
domain = compute_domain(DOMAIN_DEPOSIT) # Fork-agnostic domain since deposits are valid across forks
|
||||
signing_root = compute_signing_root(deposit_message, domain)
|
||||
# Initialize validator if the deposit signature is valid
|
||||
if bls.Verify(pubkey, signing_root, signature):
|
||||
index = get_index_for_new_validator(state)
|
||||
validator = get_validator_from_deposit(pubkey, withdrawal_credentials, amount)
|
||||
set_or_append_list(state.validators, index, validator)
|
||||
set_or_append_list(state.balances, index, amount)
|
||||
set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
||||
set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
||||
set_or_append_list(state.inactivity_scores, index, uint64(0))
|
||||
# [New in Whisk]
|
||||
k = get_unique_whisk_k(state, ValidatorIndex(len(state.validators) - 1))
|
||||
state.whisk_trackers.append(get_initial_tracker(k))
|
||||
state.whisk_k_commitments.append(get_k_commitment(k))
|
||||
else:
|
||||
# Increase balance by deposit amount
|
||||
index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
||||
increase_balance(state, index, amount)
|
||||
def add_validator_to_registry(state: BeaconState,
|
||||
pubkey: BLSPubkey,
|
||||
withdrawal_credentials: Bytes32,
|
||||
amount: uint64) -> None:
|
||||
index = get_index_for_new_validator(state)
|
||||
validator = get_validator_from_deposit(pubkey, withdrawal_credentials, amount)
|
||||
set_or_append_list(state.validators, index, validator)
|
||||
set_or_append_list(state.balances, index, amount)
|
||||
set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
||||
set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
||||
set_or_append_list(state.inactivity_scores, index, uint64(0))
|
||||
# [New in Whisk]
|
||||
k = get_unique_whisk_k(state, ValidatorIndex(len(state.validators) - 1))
|
||||
state.whisk_trackers.append(get_initial_tracker(k))
|
||||
state.whisk_k_commitments.append(get_k_commitment(k))
|
||||
```
|
||||
|
||||
### `get_beacon_proposer_index`
|
||||
|
|
|
@ -76,7 +76,7 @@ Alias `block = signed_beacon_block.message`, `execution_payload = block.body.exe
|
|||
then validate the following:
|
||||
- _[REJECT]_ The block's execution payload timestamp is correct with respect to the slot
|
||||
-- i.e. `execution_payload.timestamp == compute_timestamp_at_slot(state, block.slot)`.
|
||||
- If `exection_payload` verification of block's parent by an execution node is *not* complete:
|
||||
- If `execution_payload` verification of block's parent by an execution node is *not* complete:
|
||||
- [REJECT] The block's parent (defined by `block.parent_root`) passes all
|
||||
validation (excluding execution node verification of the `block.body.execution_payload`).
|
||||
- otherwise:
|
||||
|
|
|
@ -148,6 +148,7 @@ This topic is used to propagate signed blob sidecars, where each blob index maps
|
|||
|
||||
The following validations MUST pass before forwarding the `signed_blob_sidecar` on the network, assuming the alias `sidecar = signed_blob_sidecar.message`:
|
||||
|
||||
- _[REJECT]_ The sidecar's index is consistent with `MAX_BLOBS_PER_BLOCK` -- i.e. `sidecar.index < MAX_BLOBS_PER_BLOCK`.
|
||||
- _[REJECT]_ The sidecar is for the correct subnet -- i.e. `compute_subnet_for_blob_sidecar(sidecar.index) == subnet_id`.
|
||||
- _[IGNORE]_ The sidecar is not from a future slot (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. validate that `sidecar.slot <= current_slot` (a client MAY queue future sidecars for processing at the appropriate slot).
|
||||
- _[IGNORE]_ The sidecar is from a slot greater than the latest finalized slot -- i.e. validate that `sidecar.slot > compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)`
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
- [Constants](#constants)
|
||||
- [Preset](#preset)
|
||||
- [Blob](#blob)
|
||||
- [Crypto](#crypto)
|
||||
- [Trusted setup](#trusted-setup)
|
||||
- [Helper functions](#helper-functions)
|
||||
- [Bit-reversal permutation](#bit-reversal-permutation)
|
||||
|
@ -30,6 +29,7 @@
|
|||
- [`div`](#div)
|
||||
- [`g1_lincomb`](#g1_lincomb)
|
||||
- [`compute_powers`](#compute_powers)
|
||||
- [`compute_roots_of_unity`](#compute_roots_of_unity)
|
||||
- [Polynomials](#polynomials)
|
||||
- [`evaluate_polynomial_in_evaluation_form`](#evaluate_polynomial_in_evaluation_form)
|
||||
- [KZG](#kzg)
|
||||
|
@ -78,7 +78,7 @@ Public functions MUST accept raw bytes as input and perform the required cryptog
|
|||
| `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 |
|
||||
| `KZG_ENDIANNESS` | `'big'` | The endianness of the field elements including blobs |
|
||||
|
||||
| `PRIMITIVE_ROOT_OF_UNITY` | `7` | Primitive root of unity of the BLS12_381 (inner) BLS_MODULUS |
|
||||
|
||||
## Preset
|
||||
|
||||
|
@ -90,23 +90,13 @@ Public functions MUST accept raw bytes as input and perform the required cryptog
|
|||
| `FIAT_SHAMIR_PROTOCOL_DOMAIN` | `b'FSBLOBVERIFY_V1_'` |
|
||||
| `RANDOM_CHALLENGE_KZG_BATCH_DOMAIN` | `b'RCKZGBATCH___V1_'` |
|
||||
|
||||
### Crypto
|
||||
|
||||
| Name | Value | Notes |
|
||||
| - | - | - |
|
||||
| `ROOTS_OF_UNITY` | `Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB]` | Roots of unity of order FIELD_ELEMENTS_PER_BLOB over the BLS12-381 field |
|
||||
|
||||
### Trusted setup
|
||||
|
||||
The trusted setup is part of the preset: during testing a `minimal` insecure variant may be used,
|
||||
but reusing the `mainnet` settings in public networks is a critical security requirement.
|
||||
|
||||
| Name | Value |
|
||||
| - | - |
|
||||
| `KZG_SETUP_G2_LENGTH` | `65` |
|
||||
| `KZG_SETUP_G1` | `Vector[G1Point, FIELD_ELEMENTS_PER_BLOB]`, contents TBD |
|
||||
| `KZG_SETUP_G2` | `Vector[G2Point, KZG_SETUP_G2_LENGTH]`, contents TBD |
|
||||
| `KZG_SETUP_LAGRANGE` | `Vector[G1Point, FIELD_ELEMENTS_PER_BLOB]`, contents TBD |
|
||||
| `KZG_SETUP_G2_MONOMIAL` | `Vector[G2Point, KZG_SETUP_G2_LENGTH]` |
|
||||
| `KZG_SETUP_G1_LAGRANGE` | `Vector[G1Point, FIELD_ELEMENTS_PER_BLOB]` |
|
||||
|
||||
## Helper functions
|
||||
|
||||
|
@ -114,7 +104,7 @@ but reusing the `mainnet` settings in public networks is a critical security req
|
|||
|
||||
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
|
||||
`KZG_SETUP_G1_LAGRANGE` and roots of unity in bit-reversal permutation, so these functions only
|
||||
have to be called once at startup.
|
||||
|
||||
#### `is_power_of_two`
|
||||
|
@ -299,6 +289,17 @@ def compute_powers(x: BLSFieldElement, n: uint64) -> Sequence[BLSFieldElement]:
|
|||
return powers
|
||||
```
|
||||
|
||||
#### `compute_roots_of_unity`
|
||||
|
||||
```python
|
||||
def compute_roots_of_unity(order: uint64) -> Sequence[BLSFieldElement]:
|
||||
"""
|
||||
Return roots of unity of ``order``.
|
||||
"""
|
||||
assert (BLS_MODULUS - 1) % int(order) == 0
|
||||
root_of_unity = BLSFieldElement(pow(PRIMITIVE_ROOT_OF_UNITY, (BLS_MODULUS - 1) // int(order), BLS_MODULUS))
|
||||
return compute_powers(root_of_unity, order)
|
||||
```
|
||||
|
||||
### Polynomials
|
||||
|
||||
|
@ -318,7 +319,7 @@ def evaluate_polynomial_in_evaluation_form(polynomial: Polynomial,
|
|||
assert width == FIELD_ELEMENTS_PER_BLOB
|
||||
inverse_width = bls_modular_inverse(BLSFieldElement(width))
|
||||
|
||||
roots_of_unity_brp = bit_reversal_permutation(ROOTS_OF_UNITY)
|
||||
roots_of_unity_brp = bit_reversal_permutation(compute_roots_of_unity(FIELD_ELEMENTS_PER_BLOB))
|
||||
|
||||
# If we are asked to evaluate within the domain, we already know the answer
|
||||
if z in roots_of_unity_brp:
|
||||
|
@ -346,7 +347,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))
|
||||
return g1_lincomb(bit_reversal_permutation(KZG_SETUP_G1_LAGRANGE), blob_to_polynomial(blob))
|
||||
```
|
||||
|
||||
#### `verify_kzg_proof`
|
||||
|
@ -384,7 +385,10 @@ def verify_kzg_proof_impl(commitment: KZGCommitment,
|
|||
Verify KZG proof that ``p(z) == y`` where ``p(z)`` is the polynomial represented by ``polynomial_kzg``.
|
||||
"""
|
||||
# Verify: P - y = Q * (X - z)
|
||||
X_minus_z = bls.add(bls.bytes96_to_G2(KZG_SETUP_G2[1]), bls.multiply(bls.G2(), (BLS_MODULUS - z) % BLS_MODULUS))
|
||||
X_minus_z = bls.add(
|
||||
bls.bytes96_to_G2(KZG_SETUP_G2_MONOMIAL[1]),
|
||||
bls.multiply(bls.G2(), (BLS_MODULUS - z) % BLS_MODULUS),
|
||||
)
|
||||
P_minus_y = bls.add(bls.bytes48_to_G1(commitment), bls.multiply(bls.G1(), (BLS_MODULUS - y) % BLS_MODULUS))
|
||||
return bls.pairing_check([
|
||||
[P_minus_y, bls.neg(bls.G2())],
|
||||
|
@ -434,7 +438,7 @@ def verify_kzg_proof_batch(commitments: Sequence[KZGCommitment],
|
|||
C_minus_y_lincomb = g1_lincomb(C_minus_y_as_KZGCommitments, r_powers)
|
||||
|
||||
return bls.pairing_check([
|
||||
[bls.bytes48_to_G1(proof_lincomb), bls.neg(bls.bytes96_to_G2(KZG_SETUP_G2[1]))],
|
||||
[bls.bytes48_to_G1(proof_lincomb), bls.neg(bls.bytes96_to_G2(KZG_SETUP_G2_MONOMIAL[1]))],
|
||||
[bls.add(bls.bytes48_to_G1(C_minus_y_lincomb), bls.bytes48_to_G1(proof_z_lincomb)), bls.G2()]
|
||||
])
|
||||
```
|
||||
|
@ -464,12 +468,12 @@ def compute_quotient_eval_within_domain(z: 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`.
|
||||
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)
|
||||
roots_of_unity_brp = bit_reversal_permutation(compute_roots_of_unity(FIELD_ELEMENTS_PER_BLOB))
|
||||
result = 0
|
||||
for i, omega_i in enumerate(roots_of_unity_brp):
|
||||
if omega_i == z: # skip the evaluation point in the sum
|
||||
|
@ -490,7 +494,7 @@ def compute_kzg_proof_impl(polynomial: Polynomial, z: BLSFieldElement) -> Tuple[
|
|||
"""
|
||||
Helper function for `compute_kzg_proof()` and `compute_blob_kzg_proof()`.
|
||||
"""
|
||||
roots_of_unity_brp = bit_reversal_permutation(ROOTS_OF_UNITY)
|
||||
roots_of_unity_brp = bit_reversal_permutation(compute_roots_of_unity(FIELD_ELEMENTS_PER_BLOB))
|
||||
|
||||
# For all x_i, compute p(x_i) - p(z)
|
||||
y = evaluate_polynomial_in_evaluation_form(polynomial, z)
|
||||
|
@ -510,7 +514,7 @@ def compute_kzg_proof_impl(polynomial: Polynomial, z: BLSFieldElement) -> Tuple[
|
|||
# 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)), y
|
||||
return KZGProof(g1_lincomb(bit_reversal_permutation(KZG_SETUP_G1_LAGRANGE), quotient_polynomial)), y
|
||||
```
|
||||
|
||||
#### `compute_blob_kzg_proof`
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.4.0-beta.2
|
||||
1.4.0-beta.3
|
||||
|
|
|
@ -373,8 +373,8 @@ def test_invalid_signature_previous_committee(spec, state):
|
|||
current_epoch = spec.get_current_epoch(state)
|
||||
old_sync_committee = state.next_sync_committee
|
||||
|
||||
epoch_in_future_sync_commitee_period = current_epoch + 2 * spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD
|
||||
slot_in_future_sync_committee_period = epoch_in_future_sync_commitee_period * spec.SLOTS_PER_EPOCH
|
||||
epoch_in_future_sync_committee_period = current_epoch + 2 * spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD
|
||||
slot_in_future_sync_committee_period = epoch_in_future_sync_committee_period * spec.SLOTS_PER_EPOCH
|
||||
transition_to(spec, state, slot_in_future_sync_committee_period)
|
||||
|
||||
# Use the previous sync committee to produce the signature.
|
||||
|
|
|
@ -58,7 +58,6 @@ def test_simple_blob_data(spec, state):
|
|||
assert spec.get_head(store) == signed_block.message.hash_tree_root()
|
||||
|
||||
# On receiving a block of next epoch
|
||||
store.time = current_time + spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH
|
||||
block, blobs, blob_kzg_proofs = get_block_with_blob(spec, state, rng=rng)
|
||||
signed_block = state_transition_and_sign_block(spec, state, block)
|
||||
blob_data = BlobData(blobs, blob_kzg_proofs)
|
||||
|
|
|
@ -113,7 +113,7 @@ def test_barycentric_outside_domain(spec):
|
|||
"""
|
||||
rng = random.Random(5566)
|
||||
poly_coeff, poly_eval = get_poly_in_both_forms(spec)
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.ROOTS_OF_UNITY)
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.compute_roots_of_unity(spec.FIELD_ELEMENTS_PER_BLOB))
|
||||
|
||||
assert len(poly_coeff) == len(poly_eval) == len(roots_of_unity_brp)
|
||||
n_samples = 12
|
||||
|
@ -139,20 +139,22 @@ def test_barycentric_outside_domain(spec):
|
|||
@single_phase
|
||||
def test_barycentric_within_domain(spec):
|
||||
"""
|
||||
Test barycentric formula correctness by using it to evaluate a polynomial at all the points of its domain
|
||||
Test barycentric formula correctness by using it to evaluate a polynomial at various points inside its domain
|
||||
(the roots of unity).
|
||||
|
||||
Then make sure that we would get the same result if we evaluated it from coefficient form without using the
|
||||
barycentric formula
|
||||
"""
|
||||
rng = random.Random(5566)
|
||||
poly_coeff, poly_eval = get_poly_in_both_forms(spec)
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.ROOTS_OF_UNITY)
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.compute_roots_of_unity(spec.FIELD_ELEMENTS_PER_BLOB))
|
||||
|
||||
assert len(poly_coeff) == len(poly_eval) == len(roots_of_unity_brp)
|
||||
n = len(poly_coeff)
|
||||
|
||||
# Iterate over the entire domain
|
||||
for i in range(n):
|
||||
# Iterate over some roots of unity
|
||||
for i in range(12):
|
||||
i = rng.randint(0, n - 1)
|
||||
# Grab a root of unity and use it as the evaluation point
|
||||
z = int(roots_of_unity_brp[i])
|
||||
|
||||
|
@ -175,15 +177,17 @@ def test_compute_kzg_proof_within_domain(spec):
|
|||
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).
|
||||
"""
|
||||
rng = random.Random(5566)
|
||||
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)
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.compute_roots_of_unity(spec.FIELD_ELEMENTS_PER_BLOB))
|
||||
|
||||
for i, z in enumerate(roots_of_unity_brp):
|
||||
# Let's test some roots of unity
|
||||
for _ in range(6):
|
||||
z = rng.choice(roots_of_unity_brp)
|
||||
proof, y = spec.compute_kzg_proof_impl(polynomial, z)
|
||||
|
||||
assert spec.verify_kzg_proof_impl(commitment, z, y, proof)
|
||||
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ def get_poly_in_both_forms(spec, rng=None):
|
|||
if rng is None:
|
||||
rng = random.Random(5566)
|
||||
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.ROOTS_OF_UNITY)
|
||||
roots_of_unity_brp = spec.bit_reversal_permutation(spec.compute_roots_of_unity(spec.FIELD_ELEMENTS_PER_BLOB))
|
||||
|
||||
coeffs = [
|
||||
rng.randint(0, spec.BLS_MODULUS - 1)
|
||||
|
|
|
@ -48,8 +48,8 @@ class fastest_bls:
|
|||
# Flag to make BLS active or not. Used for testing, do not ignore BLS in production unless you know what you are doing.
|
||||
bls_active = True
|
||||
|
||||
# To change bls implementation, default to PyECC for correctness. Milagro is a good faster alternative.
|
||||
bls = py_ecc_bls
|
||||
# Default to fastest_bls
|
||||
bls = fastest_bls
|
||||
|
||||
STUB_SIGNATURE = b'\x11' * 96
|
||||
STUB_PUBKEY = b'\x22' * 48
|
||||
|
|
|
@ -67,6 +67,7 @@ INVALID_G1_POINTS = [G1_INVALID_TOO_FEW_BYTES, G1_INVALID_TOO_MANY_BYTES,
|
|||
G1_INVALID_P1_NOT_IN_G1, G1_INVALID_P1_NOT_ON_CURVE]
|
||||
|
||||
BLOB_ALL_ZEROS = spec.Blob()
|
||||
BLOB_ALL_TWOS = spec.Blob(b''.join([field_element_bytes(2) for n in range(4096)]))
|
||||
BLOB_RANDOM_VALID1 = spec.Blob(b''.join([field_element_bytes(pow(2, n + 256, spec.BLS_MODULUS)) for n in range(4096)]))
|
||||
BLOB_RANDOM_VALID2 = spec.Blob(b''.join([field_element_bytes(pow(3, n + 256, spec.BLS_MODULUS)) for n in range(4096)]))
|
||||
BLOB_RANDOM_VALID3 = spec.Blob(b''.join([field_element_bytes(pow(5, n + 256, spec.BLS_MODULUS)) for n in range(4096)]))
|
||||
|
@ -79,7 +80,7 @@ BLOB_INVALID_CLOSE = spec.Blob(b''.join(
|
|||
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,
|
||||
VALID_BLOBS = [BLOB_ALL_ZEROS, BLOB_ALL_TWOS, BLOB_RANDOM_VALID1, BLOB_RANDOM_VALID2,
|
||||
BLOB_RANDOM_VALID3, BLOB_ALL_MODULUS_MINUS_ONE, BLOB_ALMOST_ZERO]
|
||||
INVALID_BLOBS = [BLOB_INVALID, BLOB_INVALID_CLOSE, BLOB_INVALID_LENGTH_PLUS_ONE, BLOB_INVALID_LENGTH_MINUS_ONE]
|
||||
|
||||
|
@ -88,7 +89,7 @@ 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])
|
||||
FE_VALID6 = field_element_bytes(spec.compute_roots_of_unity(spec.FIELD_ELEMENTS_PER_BLOB)[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)
|
||||
|
@ -214,6 +215,64 @@ def case03_verify_kzg_proof():
|
|||
'output': False
|
||||
}
|
||||
|
||||
# Incorrect `G1_POINT_AT_INFINITY` proof
|
||||
blob = BLOB_RANDOM_VALID1
|
||||
for z in VALID_FIELD_ELEMENTS:
|
||||
_, y = spec.compute_kzg_proof(blob, z)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.G1_POINT_AT_INFINITY
|
||||
assert not spec.verify_kzg_proof(commitment, z, y, proof)
|
||||
prefix = 'verify_kzg_proof_case_incorrect_proof_point_at_infinity'
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'{prefix}_{(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': False
|
||||
}
|
||||
|
||||
# Correct `G1_POINT_AT_INFINITY` proof for zero poly
|
||||
blob = BLOB_ALL_ZEROS
|
||||
for z in VALID_FIELD_ELEMENTS:
|
||||
_, y = spec.compute_kzg_proof(blob, z)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.G1_POINT_AT_INFINITY
|
||||
assert spec.verify_kzg_proof(commitment, z, y, proof)
|
||||
prefix = 'verify_kzg_proof_case_correct_proof_point_at_infinity_for_zero_poly'
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'{prefix}_{(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': True
|
||||
}
|
||||
|
||||
# Correct `G1_POINT_AT_INFINITY` proof for poly of all twos
|
||||
blob = BLOB_ALL_TWOS
|
||||
for z in VALID_FIELD_ELEMENTS:
|
||||
_, y = spec.compute_kzg_proof(blob, z)
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.G1_POINT_AT_INFINITY
|
||||
assert spec.verify_kzg_proof(commitment, z, y, proof)
|
||||
assert y == field_element_bytes(2)
|
||||
prefix = 'verify_kzg_proof_case_correct_proof_point_at_infinity_for_twos_poly'
|
||||
identifier = f'{encode_hex(hash(blob))}_{encode_hex(z)}'
|
||||
yield f'{prefix}_{(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': True
|
||||
}
|
||||
|
||||
# Edge case: Invalid commitment
|
||||
for commitment in INVALID_G1_POINTS:
|
||||
blob, z = VALID_BLOBS[2], VALID_FIELD_ELEMENTS[1]
|
||||
|
@ -354,6 +413,50 @@ def case05_verify_blob_kzg_proof():
|
|||
'output': False
|
||||
}
|
||||
|
||||
# Incorrect `G1_POINT_AT_INFINITY` proof
|
||||
blob = BLOB_RANDOM_VALID1
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.G1_POINT_AT_INFINITY
|
||||
assert not spec.verify_blob_kzg_proof(blob, commitment, proof)
|
||||
yield 'verify_blob_kzg_proof_case_incorrect_proof_point_at_infinity', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': False
|
||||
}
|
||||
|
||||
# Correct `G1_POINT_AT_INFINITY` proof and commitment for zero poly
|
||||
blob = BLOB_ALL_ZEROS
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.G1_POINT_AT_INFINITY
|
||||
assert commitment == spec.G1_POINT_AT_INFINITY
|
||||
assert spec.verify_blob_kzg_proof(blob, commitment, proof)
|
||||
yield 'verify_blob_kzg_proof_case_correct_proof_point_at_infinity_for_zero_poly', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': True
|
||||
}
|
||||
|
||||
# Correct `G1_POINT_AT_INFINITY` proof for all twos poly
|
||||
blob = BLOB_ALL_TWOS
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.G1_POINT_AT_INFINITY
|
||||
assert commitment != spec.G1_POINT_AT_INFINITY
|
||||
assert spec.verify_blob_kzg_proof(blob, commitment, proof)
|
||||
yield 'verify_blob_kzg_proof_case_correct_proof_point_at_infinity_for_twos_poly', {
|
||||
'input': {
|
||||
'blob': encode_hex(blob),
|
||||
'commitment': encode_hex(commitment),
|
||||
'proof': encode_hex(proof),
|
||||
},
|
||||
'output': True
|
||||
}
|
||||
|
||||
# Edge case: Invalid blob
|
||||
for blob in INVALID_BLOBS:
|
||||
proof = G1
|
||||
|
@ -423,7 +526,7 @@ def case06_verify_blob_kzg_proof_batch():
|
|||
# Incorrect proof
|
||||
proofs_incorrect = [bls_add_one(proofs[0])] + proofs[1:]
|
||||
assert not spec.verify_blob_kzg_proof_batch(VALID_BLOBS, commitments, proofs_incorrect)
|
||||
yield 'verify_blob_kzg_proof_batch_case_invalid_proof', {
|
||||
yield 'verify_blob_kzg_proof_batch_case_incorrect_proof_add_one', {
|
||||
'input': {
|
||||
'blobs': encode_hex_list(VALID_BLOBS),
|
||||
'commitments': encode_hex_list(commitments),
|
||||
|
@ -432,6 +535,20 @@ def case06_verify_blob_kzg_proof_batch():
|
|||
'output': False
|
||||
}
|
||||
|
||||
# Incorrect `G1_POINT_AT_INFINITY` proof
|
||||
blob = BLOB_RANDOM_VALID1
|
||||
commitment = spec.blob_to_kzg_commitment(blob)
|
||||
proof = spec.G1_POINT_AT_INFINITY
|
||||
assert not spec.verify_blob_kzg_proof_batch([blob], [commitment], [proof])
|
||||
yield 'verify_blob_kzg_proof_batch_case_incorrect_proof_point_at_infinity', {
|
||||
'input': {
|
||||
'blobs': encode_hex_list([blob]),
|
||||
'commitments': encode_hex_list([commitment]),
|
||||
'proofs': encode_hex_list([proof]),
|
||||
},
|
||||
'output': False
|
||||
}
|
||||
|
||||
# Edge case: Invalid blobs
|
||||
for blob in INVALID_BLOBS:
|
||||
blobs_invalid = VALID_BLOBS[:4] + [blob] + VALID_BLOBS[5:]
|
||||
|
|
Loading…
Reference in New Issue