Merge branch 'dev' into lc-transitionacrossforks

This commit is contained in:
Etan Kissling
2024-01-15 13:34:04 +01:00
35 changed files with 17595 additions and 8504 deletions

View File

@@ -10,17 +10,17 @@ from eth2spec.test.context import (
@spec_state_test
def test_current_sync_committee_merkle_proof(spec, state):
yield "object", state
current_sync_committee_branch = spec.compute_merkle_proof(state, spec.CURRENT_SYNC_COMMITTEE_INDEX)
current_sync_committee_branch = spec.compute_merkle_proof(state, spec.CURRENT_SYNC_COMMITTEE_GINDEX)
yield "proof", {
"leaf": "0x" + state.current_sync_committee.hash_tree_root().hex(),
"leaf_index": spec.CURRENT_SYNC_COMMITTEE_INDEX,
"leaf_index": spec.CURRENT_SYNC_COMMITTEE_GINDEX,
"branch": ['0x' + root.hex() for root in current_sync_committee_branch]
}
assert spec.is_valid_merkle_branch(
leaf=state.current_sync_committee.hash_tree_root(),
branch=current_sync_committee_branch,
depth=spec.floorlog2(spec.CURRENT_SYNC_COMMITTEE_INDEX),
index=spec.get_subtree_index(spec.CURRENT_SYNC_COMMITTEE_INDEX),
depth=spec.floorlog2(spec.CURRENT_SYNC_COMMITTEE_GINDEX),
index=spec.get_subtree_index(spec.CURRENT_SYNC_COMMITTEE_GINDEX),
root=state.hash_tree_root(),
)
@@ -30,17 +30,17 @@ def test_current_sync_committee_merkle_proof(spec, state):
@spec_state_test
def test_next_sync_committee_merkle_proof(spec, state):
yield "object", state
next_sync_committee_branch = spec.compute_merkle_proof(state, spec.NEXT_SYNC_COMMITTEE_INDEX)
next_sync_committee_branch = spec.compute_merkle_proof(state, spec.NEXT_SYNC_COMMITTEE_GINDEX)
yield "proof", {
"leaf": "0x" + state.next_sync_committee.hash_tree_root().hex(),
"leaf_index": spec.NEXT_SYNC_COMMITTEE_INDEX,
"leaf_index": spec.NEXT_SYNC_COMMITTEE_GINDEX,
"branch": ['0x' + root.hex() for root in next_sync_committee_branch]
}
assert spec.is_valid_merkle_branch(
leaf=state.next_sync_committee.hash_tree_root(),
branch=next_sync_committee_branch,
depth=spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX),
index=spec.get_subtree_index(spec.NEXT_SYNC_COMMITTEE_INDEX),
depth=spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_GINDEX),
index=spec.get_subtree_index(spec.NEXT_SYNC_COMMITTEE_GINDEX),
root=state.hash_tree_root(),
)
@@ -50,17 +50,17 @@ def test_next_sync_committee_merkle_proof(spec, state):
@spec_state_test
def test_finality_root_merkle_proof(spec, state):
yield "object", state
finality_branch = spec.compute_merkle_proof(state, spec.FINALIZED_ROOT_INDEX)
finality_branch = spec.compute_merkle_proof(state, spec.FINALIZED_ROOT_GINDEX)
yield "proof", {
"leaf": "0x" + state.finalized_checkpoint.root.hex(),
"leaf_index": spec.FINALIZED_ROOT_INDEX,
"leaf_index": spec.FINALIZED_ROOT_GINDEX,
"branch": ['0x' + root.hex() for root in finality_branch]
}
assert spec.is_valid_merkle_branch(
leaf=state.finalized_checkpoint.root,
branch=finality_branch,
depth=spec.floorlog2(spec.FINALIZED_ROOT_INDEX),
index=spec.get_subtree_index(spec.FINALIZED_ROOT_INDEX),
depth=spec.floorlog2(spec.FINALIZED_ROOT_GINDEX),
index=spec.get_subtree_index(spec.FINALIZED_ROOT_GINDEX),
root=state.hash_tree_root(),
)

View File

@@ -27,7 +27,11 @@ from eth2spec.test.helpers.forks import (
is_post_capella, is_post_deneb,
)
from eth2spec.test.helpers.light_client import (
compute_start_slot_at_next_sync_committee_period,
get_sync_aggregate,
upgrade_lc_bootstrap_to_new_spec,
upgrade_lc_update_to_new_spec,
upgrade_lc_store_to_new_spec,
)
from eth2spec.test.helpers.state import (
next_slots,
@@ -35,94 +39,6 @@ from eth2spec.test.helpers.state import (
)
def needs_upgrade_to_capella(d_spec, s_spec):
return is_post_capella(s_spec) and not is_post_capella(d_spec)
def needs_upgrade_to_deneb(d_spec, s_spec):
return is_post_deneb(s_spec) and not is_post_deneb(d_spec)
def check_lc_header_equal(d_spec, s_spec, data, upgraded):
assert upgraded.beacon.slot == data.beacon.slot
assert upgraded.beacon.hash_tree_root() == data.beacon.hash_tree_root()
if is_post_capella(s_spec):
if is_post_capella(d_spec):
assert s_spec.get_lc_execution_root(upgraded) == d_spec.get_lc_execution_root(data)
else:
assert s_spec.get_lc_execution_root(upgraded) == s_spec.Root()
def check_lc_bootstrap_equal(d_spec, s_spec, data, upgraded):
check_lc_header_equal(d_spec, s_spec, data.header, upgraded.header)
assert upgraded.current_sync_committee == data.current_sync_committee
assert upgraded.current_sync_committee_branch == data.current_sync_committee_branch
def upgrade_lc_bootstrap_to_store(d_spec, s_spec, data):
upgraded = data
if needs_upgrade_to_capella(d_spec, s_spec):
upgraded = s_spec.upgrade_lc_bootstrap_to_capella(upgraded)
check_lc_bootstrap_equal(d_spec, s_spec, data, upgraded)
if needs_upgrade_to_deneb(d_spec, s_spec):
upgraded = s_spec.upgrade_lc_bootstrap_to_deneb(upgraded)
check_lc_bootstrap_equal(d_spec, s_spec, data, upgraded)
return upgraded
def check_lc_update_equal(d_spec, s_spec, data, upgraded):
check_lc_header_equal(d_spec, s_spec, data.attested_header, upgraded.attested_header)
assert upgraded.next_sync_committee == data.next_sync_committee
assert upgraded.next_sync_committee_branch == data.next_sync_committee_branch
check_lc_header_equal(d_spec, s_spec, data.finalized_header, upgraded.finalized_header)
assert upgraded.sync_aggregate == data.sync_aggregate
assert upgraded.signature_slot == data.signature_slot
def upgrade_lc_update_to_store(d_spec, s_spec, data):
upgraded = data
if needs_upgrade_to_capella(d_spec, s_spec):
upgraded = s_spec.upgrade_lc_update_to_capella(upgraded)
check_lc_update_equal(d_spec, s_spec, data, upgraded)
if needs_upgrade_to_deneb(d_spec, s_spec):
upgraded = s_spec.upgrade_lc_update_to_deneb(upgraded)
check_lc_update_equal(d_spec, s_spec, data, upgraded)
return upgraded
def check_lc_store_equal(d_spec, s_spec, data, upgraded):
check_lc_header_equal(d_spec, s_spec, data.finalized_header, upgraded.finalized_header)
assert upgraded.current_sync_committee == data.current_sync_committee
assert upgraded.next_sync_committee == data.next_sync_committee
if upgraded.best_valid_update is None:
assert data.best_valid_update is None
else:
check_lc_update_equal(d_spec, s_spec, data.best_valid_update, upgraded.best_valid_update)
check_lc_header_equal(d_spec, s_spec, data.optimistic_header, upgraded.optimistic_header)
assert upgraded.previous_max_active_participants == data.previous_max_active_participants
assert upgraded.current_max_active_participants == data.current_max_active_participants
def upgrade_lc_store_to_new_spec(d_spec, s_spec, data):
upgraded = data
if needs_upgrade_to_capella(d_spec, s_spec):
upgraded = s_spec.upgrade_lc_store_to_capella(upgraded)
check_lc_store_equal(d_spec, s_spec, data, upgraded)
if needs_upgrade_to_deneb(d_spec, s_spec):
upgraded = s_spec.upgrade_lc_store_to_deneb(upgraded)
check_lc_store_equal(d_spec, s_spec, data, upgraded)
return upgraded
class LightClientSyncTest(object):
steps: List[Dict[str, Any]]
genesis_validators_root: Any
@@ -161,7 +77,7 @@ def setup_test(spec, state, s_spec=None, phases=None):
yield "bootstrap_fork_digest", "meta", encode_hex(data_fork_digest)
yield "bootstrap", data
upgraded = upgrade_lc_bootstrap_to_store(d_spec, test.s_spec, data)
upgraded = upgrade_lc_bootstrap_to_new_spec(d_spec, test.s_spec, data)
test.store = test.s_spec.initialize_light_client_store(trusted_block_root, upgraded)
store_fork_version = get_store_fork_version(test.s_spec)
store_fork_digest = test.s_spec.compute_fork_digest(store_fork_version, test.genesis_validators_root)
@@ -234,10 +150,10 @@ def emit_update(test, spec, state, block, attested_state, attested_block, finali
if not with_next:
data.next_sync_committee = spec.SyncCommittee()
data.next_sync_committee_branch = \
[spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))]
[spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_GINDEX))]
current_slot = state.slot
upgraded = upgrade_lc_update_to_store(d_spec, test.s_spec, data)
upgraded = upgrade_lc_update_to_new_spec(d_spec, test.s_spec, data)
test.s_spec.process_light_client_update(test.store, upgraded, current_slot, test.genesis_validators_root)
yield get_update_file_name(d_spec, data), data
@@ -267,15 +183,6 @@ def emit_upgrade_store(test, new_s_spec, phases=None):
})
def compute_start_slot_at_sync_committee_period(spec, sync_committee_period):
return spec.compute_start_slot_at_epoch(sync_committee_period * spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
def compute_start_slot_at_next_sync_committee_period(spec, state):
sync_committee_period = spec.compute_sync_committee_period_at_slot(state.slot)
return compute_start_slot_at_sync_committee_period(spec, sync_committee_period + 1)
@with_light_client
@spec_state_test_with_matching_config
@with_presets([MINIMAL], reason="too slow")

View File

@@ -44,7 +44,7 @@ def pytest_addoption(parser):
help="bls-default: make tests that are not dependent on BLS run without BLS"
)
parser.addoption(
"--bls-type", action="store", type=str, default="py_ecc", choices=["py_ecc", "milagro", "arkworks", "fastest"],
"--bls-type", action="store", type=str, default="fastest", choices=["py_ecc", "milagro", "arkworks", "fastest"],
help=(
"bls-type: use specified BLS implementation;"
"fastest: use milagro for signatures and arkworks for everything else (e.g. KZG)"

View File

@@ -8,7 +8,7 @@ from eth2spec.utils import bls
from .exceptions import SkippedTest
from .helpers.constants import (
PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB,
EIP6110, EIP7002,
EIP6110, EIP7002, EIP7594,
WHISK,
MINIMAL,
ALL_PHASES,
@@ -510,6 +510,7 @@ with_deneb_and_later = with_all_phases_from(DENEB)
with_eip6110_and_later = with_all_phases_from(EIP6110)
with_eip7002_and_later = with_all_phases_from(EIP7002)
with_whisk_and_later = with_all_phases_from(WHISK, all_phases=ALLOWED_TEST_RUNNER_FORKS)
with_eip7594_and_later = with_all_phases_from(EIP7594, all_phases=ALLOWED_TEST_RUNNER_FORKS)
class quoted_str(str):

View File

@@ -0,0 +1,97 @@
import random
from eth2spec.test.context import (
spec_test,
single_phase,
with_eip7594_and_later,
)
from eth2spec.test.helpers.sharding import (
get_sample_blob,
)
from eth2spec.utils.bls import BLS_MODULUS
@with_eip7594_and_later
@spec_test
@single_phase
def test_fft(spec):
rng = random.Random(5566)
roots_of_unity = spec.compute_roots_of_unity(spec.FIELD_ELEMENTS_PER_BLOB)
poly_coeff = [rng.randint(0, BLS_MODULUS - 1) for _ in range(spec.FIELD_ELEMENTS_PER_BLOB)]
poly_eval = spec.fft_field(poly_coeff, roots_of_unity)
poly_coeff_inversed = spec.fft_field(poly_eval, roots_of_unity, inv=True)
assert len(poly_eval) == len(poly_coeff) == len(poly_coeff_inversed)
assert poly_coeff_inversed == poly_coeff
@with_eip7594_and_later
@spec_test
@single_phase
def test_verify_cell_proof(spec):
blob = get_sample_blob(spec)
commitment = spec.blob_to_kzg_commitment(blob)
cells, proofs = spec.compute_cells_and_proofs(blob)
cell_id = 0
assert spec.verify_cell_proof(commitment, cell_id, cells[cell_id], proofs[cell_id])
cell_id = 1
assert spec.verify_cell_proof(commitment, cell_id, cells[cell_id], proofs[cell_id])
@with_eip7594_and_later
@spec_test
@single_phase
def test_verify_cell_proof_batch(spec):
blob = get_sample_blob(spec)
commitment = spec.blob_to_kzg_commitment(blob)
cells, proofs = spec.compute_cells_and_proofs(blob)
assert spec.verify_cell_proof_batch(
row_commitments=[commitment],
row_ids=[0],
column_ids=[0, 1],
cells=cells[0:1],
proofs=proofs,
)
@with_eip7594_and_later
@spec_test
@single_phase
def test_recover_polynomial(spec):
rng = random.Random(5566)
# Number of samples we will be recovering from
N_SAMPLES = spec.CELLS_PER_BLOB // 2
# Get the data we will be working with
blob = get_sample_blob(spec)
# Get the data in evaluation form
original_polynomial = spec.blob_to_polynomial(blob)
# Extend data with Reed-Solomon and split the extended data in cells
cells = spec.compute_cells(blob)
# Compute the cells we will be recovering from
cell_ids = []
known_cells = []
# First figure out just the indices of the cells
for i in range(N_SAMPLES):
j = rng.randint(0, spec.CELLS_PER_BLOB)
while j in cell_ids:
j = rng.randint(0, spec.CELLS_PER_BLOB)
cell_ids.append(j)
# Now the cells themselves
known_cells = [cells[cell_id] for cell_id in cell_ids]
# Recover the data
recovered_data = spec.recover_polynomial(cell_ids, known_cells)
# Check that the original data match the non-extended portion of the recovered data
assert original_polynomial == recovered_data[:len(recovered_data) // 2]
# Now flatten the cells and check that they match the entirety of the recovered data
flattened_cells = [x for xs in cells for x in xs]
assert flattened_cells == recovered_data

View File

@@ -19,6 +19,7 @@ DAS = SpecForkName('das')
EIP6110 = SpecForkName('eip6110')
EIP7002 = SpecForkName('eip7002')
WHISK = SpecForkName('whisk')
EIP7594 = SpecForkName('eip7594')
#
# SpecFork settings
@@ -37,6 +38,7 @@ ALL_PHASES = (
# Experimental patches
EIP6110,
EIP7002,
EIP7594,
)
# The forks that have light client specs
LIGHT_CLIENT_TESTING_FORKS = (*[item for item in MAINNET_FORKS if item != PHASE0], DENEB)
@@ -57,6 +59,7 @@ PREVIOUS_FORK_OF = {
EIP6110: DENEB,
WHISK: CAPELLA,
EIP7002: CAPELLA,
EIP7594: DENEB,
}
# For fork transition tests

View File

@@ -1,6 +1,9 @@
from eth2spec.test.helpers.fork_transition import (
transition_across_forks,
)
from eth2spec.test.helpers.forks import (
is_post_capella, is_post_deneb,
)
from eth2spec.test.helpers.sync_committee import (
compute_aggregate_sync_committee_signature,
compute_committee_indices,
@@ -8,6 +11,15 @@ from eth2spec.test.helpers.sync_committee import (
from math import floor
def compute_start_slot_at_sync_committee_period(spec, sync_committee_period):
return spec.compute_start_slot_at_epoch(sync_committee_period * spec.EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
def compute_start_slot_at_next_sync_committee_period(spec, state):
sync_committee_period = spec.compute_sync_committee_period_at_slot(state.slot)
return compute_start_slot_at_sync_committee_period(spec, sync_committee_period + 1)
def get_sync_aggregate(spec, state, num_participants=None, signature_slot=None, phases=None):
# By default, the sync committee signs the previous slot
if signature_slot is None:
@@ -56,13 +68,136 @@ def create_update(spec,
if with_next:
update.next_sync_committee = attested_state.next_sync_committee
update.next_sync_committee_branch = spec.compute_merkle_proof(attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX)
update.next_sync_committee_branch = spec.compute_merkle_proof(attested_state, spec.NEXT_SYNC_COMMITTEE_GINDEX)
if with_finality:
update.finalized_header = spec.block_to_light_client_header(finalized_block)
update.finality_branch = spec.compute_merkle_proof(attested_state, spec.FINALIZED_ROOT_INDEX)
update.finality_branch = spec.compute_merkle_proof(attested_state, spec.FINALIZED_ROOT_GINDEX)
update.sync_aggregate, update.signature_slot = get_sync_aggregate(
spec, attested_state, num_participants)
return update
def needs_upgrade_to_capella(spec, new_spec):
return is_post_capella(new_spec) and not is_post_capella(spec)
def needs_upgrade_to_deneb(spec, new_spec):
return is_post_deneb(new_spec) and not is_post_deneb(spec)
def check_lc_header_equal(spec, new_spec, data, upgraded):
assert upgraded.beacon.slot == data.beacon.slot
assert upgraded.beacon.hash_tree_root() == data.beacon.hash_tree_root()
if is_post_capella(new_spec):
if is_post_capella(spec):
assert new_spec.get_lc_execution_root(upgraded) == spec.get_lc_execution_root(data)
else:
assert new_spec.get_lc_execution_root(upgraded) == new_spec.Root()
def upgrade_lc_header_to_new_spec(spec, new_spec, data):
upgraded = data
if needs_upgrade_to_capella(spec, new_spec):
upgraded = new_spec.upgrade_lc_header_to_capella(upgraded)
check_lc_header_equal(spec, new_spec, data, upgraded)
if needs_upgrade_to_deneb(spec, new_spec):
upgraded = new_spec.upgrade_lc_header_to_deneb(upgraded)
check_lc_header_equal(spec, new_spec, data, upgraded)
return upgraded
def check_lc_bootstrap_equal(spec, new_spec, data, upgraded):
check_lc_header_equal(spec, new_spec, data.header, upgraded.header)
assert upgraded.current_sync_committee == data.current_sync_committee
assert upgraded.current_sync_committee_branch == data.current_sync_committee_branch
def upgrade_lc_bootstrap_to_new_spec(spec, new_spec, data):
upgraded = data
if needs_upgrade_to_capella(spec, new_spec):
upgraded = new_spec.upgrade_lc_bootstrap_to_capella(upgraded)
check_lc_bootstrap_equal(spec, new_spec, data, upgraded)
if needs_upgrade_to_deneb(spec, new_spec):
upgraded = new_spec.upgrade_lc_bootstrap_to_deneb(upgraded)
check_lc_bootstrap_equal(spec, new_spec, data, upgraded)
return upgraded
def check_lc_update_equal(spec, new_spec, data, upgraded):
check_lc_header_equal(spec, new_spec, data.attested_header, upgraded.attested_header)
assert upgraded.next_sync_committee == data.next_sync_committee
assert upgraded.next_sync_committee_branch == data.next_sync_committee_branch
check_lc_header_equal(spec, new_spec, data.finalized_header, upgraded.finalized_header)
assert upgraded.sync_aggregate == data.sync_aggregate
assert upgraded.signature_slot == data.signature_slot
def upgrade_lc_update_to_new_spec(spec, new_spec, data):
upgraded = data
if needs_upgrade_to_capella(spec, new_spec):
upgraded = new_spec.upgrade_lc_update_to_capella(upgraded)
check_lc_update_equal(spec, new_spec, data, upgraded)
if needs_upgrade_to_deneb(spec, new_spec):
upgraded = new_spec.upgrade_lc_update_to_deneb(upgraded)
check_lc_update_equal(spec, new_spec, data, upgraded)
return upgraded
def check_lc_finality_update_equal(spec, new_spec, data, upgraded):
check_lc_header_equal(spec, new_spec, data.attested_header, upgraded.attested_header)
check_lc_header_equal(spec, new_spec, data.finalized_header, upgraded.finalized_header)
assert upgraded.sync_aggregate == data.sync_aggregate
assert upgraded.signature_slot == data.signature_slot
def upgrade_lc_finality_update_to_new_spec(spec, new_spec, data):
upgraded = data
if needs_upgrade_to_capella(spec, new_spec):
upgraded = new_spec.upgrade_lc_finality_update_to_capella(upgraded)
check_lc_finality_update_equal(spec, new_spec, data, upgraded)
if needs_upgrade_to_deneb(spec, new_spec):
upgraded = new_spec.upgrade_lc_finality_update_to_deneb(upgraded)
check_lc_finality_update_equal(spec, new_spec, data, upgraded)
return upgraded
def check_lc_store_equal(spec, new_spec, data, upgraded):
check_lc_header_equal(spec, new_spec, data.finalized_header, upgraded.finalized_header)
assert upgraded.current_sync_committee == data.current_sync_committee
assert upgraded.next_sync_committee == data.next_sync_committee
if upgraded.best_valid_update is None:
assert data.best_valid_update is None
else:
check_lc_update_equal(spec, new_spec, data.best_valid_update, upgraded.best_valid_update)
check_lc_header_equal(spec, new_spec, data.optimistic_header, upgraded.optimistic_header)
assert upgraded.previous_max_active_participants == data.previous_max_active_participants
assert upgraded.current_max_active_participants == data.current_max_active_participants
def upgrade_lc_store_to_new_spec(spec, new_spec, data):
upgraded = data
if needs_upgrade_to_capella(spec, new_spec):
upgraded = new_spec.upgrade_lc_store_to_capella(upgraded)
check_lc_store_equal(spec, new_spec, data, upgraded)
if needs_upgrade_to_deneb(spec, new_spec):
upgraded = new_spec.upgrade_lc_store_to_deneb(upgraded)
check_lc_store_equal(spec, new_spec, data, upgraded)
return upgraded

View File

@@ -4,6 +4,7 @@ from py_ecc.optimized_bls12_381 import ( # noqa: F401
G1 as py_ecc_G1,
G2 as py_ecc_G2,
Z1 as py_ecc_Z1,
Z2 as py_ecc_Z2,
add as py_ecc_add,
multiply as py_ecc_mul,
neg as py_ecc_neg,
@@ -243,6 +244,15 @@ def Z1():
return py_ecc_Z1
def Z2():
"""
Returns the identity point in G2
"""
if bls == arkworks_bls or bls == fastest_bls:
return arkworks_G2.identity()
return py_ecc_Z2
def G1():
"""
Returns the chosen generator point in G1