Repository: ethereum/consensus-specs

Issue:
Use custom types for container definitions
This is the "successor" to #695 which was recently closed for staleness. I'm intending to address this alongside a rewrite of #917.


Discussion:

Resolving patch:
diff --git a/scripts/build_spec.py b/scripts/build_spec.py
--- a/scripts/build_spec.py
+++ b/scripts/build_spec.py
@@ -130,9 +130,10 @@ def objects_to_spec(functions: Dict[str, str],
     """
     Given all the objects that constitute a spec, combine them into a single pyfile.
     """
-    new_type_definitions = \
-        '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])
-    new_type_definitions += '\n' + '\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])
+    new_type_definitions = '\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])
+    new_type_definitions += '\n' + '\n'.join(['Hash = Bytes32', 'BLSPubkey = Bytes48', 'BLSSignature = Bytes96'])
+    new_type_definitions += \
+        '\n' + '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])
     functions_spec = '\n\n'.join(functions.values())
     constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))
     ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values())
@@ -177,7 +178,7 @@ def dependency_order_ssz_objects(objects: Dict[str, str]) -> None:
     items = list(objects.items())
     for key, value in items:
         dependencies = re.findall(r'(: [A-Z][\w[]*)', value)
-        dependencies = map(lambda x: re.sub(r'\W|Vector|List|Container|uint\d+|Bytes\d+|bytes', '', x), dependencies)
+        dependencies = map(lambda x: re.sub(r'\W|Vector|List|Container|Hash|BLSPubkey|BLSSignature|uint\d+|Bytes\d+|bytes', '', x), dependencies)
         for dep in dependencies:
             if dep in NEW_TYPES or len(dep) == 0:
                 continue


Test patch:
diff --git a/specs/test_formats/operations/README.md b/specs/test_formats/operations/README.md
--- a/specs/test_formats/operations/README.md
+++ b/specs/test_formats/operations/README.md
@@ -14,7 +14,7 @@ post: BeaconState                      -- state after applying the operation. No
 
 ## Condition
 
-A handler of the `operations` test-runner should process these cases, 
+A handler of the `operations` test-runner should process these cases,
  calling the corresponding processing implementation.
 
 Operations:
@@ -29,7 +29,7 @@ Operations:
 | `transfer`              | `Transfer`           | `transfer`           | `process_transfer(state, transfer)`                    |
 | `voluntary_exit`        | `VoluntaryExit`      | `voluntary_exit`     | `process_voluntary_exit(state, voluntary_exit)`        |
 
-Note that `block_header` is not strictly an operation (and is a full `Block`), but processed in the same manner, and hence included here. 
+Note that `block_header` is not strictly an operation (and is a full `Block`), but processed in the same manner, and hence included here.
 
 The resulting state should match the expected `post` state, or if the `post` state is left blank,
  the handler should reject the input operation as invalid.
diff --git a/test_libs/pyspec/eth2spec/test/helpers/block.py b/test_libs/pyspec/eth2spec/test/helpers/block.py
--- a/test_libs/pyspec/eth2spec/test/helpers/block.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/block.py
@@ -57,7 +57,7 @@ def build_empty_block(spec, state, slot=None, signed=False):
         slot = state.slot
     empty_block = spec.BeaconBlock()
     empty_block.slot = slot
-    empty_block.body.eth1_data.deposit_count = state.deposit_index
+    empty_block.body.eth1_data.deposit_count = state.eth1_deposit_index
     previous_block_header = deepcopy(state.latest_block_header)
     if previous_block_header.state_root == spec.ZERO_HASH:
         previous_block_header.state_root = state.hash_tree_root()
diff --git a/test_libs/pyspec/eth2spec/test/helpers/deposits.py b/test_libs/pyspec/eth2spec/test/helpers/deposits.py
--- a/test_libs/pyspec/eth2spec/test/helpers/deposits.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/deposits.py
@@ -58,7 +58,7 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c
     """
     Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount.
     """
-    pre_validator_count = len(state.validator_registry)
+    pre_validator_count = len(state.validators)
     # fill previous deposits with zero-hash
     deposit_data_leaves = [spec.ZERO_HASH] * pre_validator_count
 
@@ -80,6 +80,6 @@ def prepare_state_and_deposit(spec, state, validator_index, amount, withdrawal_c
         signed,
     )
 
-    state.latest_eth1_data.deposit_root = root
-    state.latest_eth1_data.deposit_count = len(deposit_data_leaves)
+    state.eth1_data.deposit_root = root
+    state.eth1_data.deposit_count = len(deposit_data_leaves)
     return deposit
diff --git a/test_libs/pyspec/eth2spec/test/helpers/genesis.py b/test_libs/pyspec/eth2spec/test/helpers/genesis.py
--- a/test_libs/pyspec/eth2spec/test/helpers/genesis.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/genesis.py
@@ -22,8 +22,8 @@ def create_genesis_state(spec, num_validators):
 
     state = spec.BeaconState(
         genesis_time=0,
-        deposit_index=num_validators,
-        latest_eth1_data=spec.Eth1Data(
+        eth1_deposit_index=num_validators,
+        eth1_data=spec.Eth1Data(
             deposit_root=deposit_root,
             deposit_count=num_validators,
             block_hash=spec.ZERO_HASH,
@@ -32,16 +32,16 @@ def create_genesis_state(spec, num_validators):
     # We "hack" in the initial validators,
     #  as it is much faster than creating and processing genesis deposits for every single test case.
     state.balances = [spec.MAX_EFFECTIVE_BALANCE] * num_validators
-    state.validator_registry = [build_mock_validator(spec, i, state.balances[i]) for i in range(num_validators)]
+    state.validators = [build_mock_validator(spec, i, state.balances[i]) for i in range(num_validators)]
 
     # Process genesis activations
-    for validator in state.validator_registry:
+    for validator in state.validators:
         if validator.effective_balance >= spec.MAX_EFFECTIVE_BALANCE:
             validator.activation_eligibility_epoch = spec.GENESIS_EPOCH
             validator.activation_epoch = spec.GENESIS_EPOCH
 
     genesis_active_index_root = hash_tree_root(spec.get_active_validator_indices(state, spec.GENESIS_EPOCH))
-    for index in range(spec.LATEST_ACTIVE_INDEX_ROOTS_LENGTH):
-        state.latest_active_index_roots[index] = genesis_active_index_root
+    for index in range(spec.ACTIVE_INDEX_ROOTS_LENGTH):
+        state.active_index_roots[index] = genesis_active_index_root
 
     return state
diff --git a/test_libs/pyspec/eth2spec/test/helpers/proposer_slashings.py b/test_libs/pyspec/eth2spec/test/helpers/proposer_slashings.py
--- a/test_libs/pyspec/eth2spec/test/helpers/proposer_slashings.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/proposer_slashings.py
@@ -7,7 +7,7 @@
 def get_valid_proposer_slashing(spec, state, signed_1=False, signed_2=False):
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
     slot = state.slot
 
     header_1 = spec.BeaconBlockHeader(
diff --git a/test_libs/pyspec/eth2spec/test/helpers/state.py b/test_libs/pyspec/eth2spec/test/helpers/state.py
--- a/test_libs/pyspec/eth2spec/test/helpers/state.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/state.py
@@ -22,4 +22,4 @@ def get_state_root(spec, state, slot) -> bytes:
     Return the state root at a recent ``slot``.
     """
     assert slot < state.slot <= slot + spec.SLOTS_PER_HISTORICAL_ROOT
-    return state.latest_state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT]
+    return state.state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT]
diff --git a/test_libs/pyspec/eth2spec/test/helpers/transfers.py b/test_libs/pyspec/eth2spec/test/helpers/transfers.py
--- a/test_libs/pyspec/eth2spec/test/helpers/transfers.py
+++ b/test_libs/pyspec/eth2spec/test/helpers/transfers.py
@@ -31,7 +31,7 @@ def get_valid_transfer(spec, state, slot=None, sender_index=None, amount=None, f
         sign_transfer(spec, state, transfer, transfer_privkey)
 
     # ensure withdrawal_credentials reproducible
-    state.validator_registry[transfer.sender].withdrawal_credentials = (
+    state.validators[transfer.sender].withdrawal_credentials = (
         spec.int_to_bytes(spec.BLS_WITHDRAWAL_PREFIX, length=1) + spec.hash(transfer.pubkey)[1:]
     )
 
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_attester_slashing.py
@@ -34,7 +34,7 @@ def run_attester_slashing_processing(spec, state, attester_slashing, valid=True)
     # Process slashing
     spec.process_attester_slashing(state, attester_slashing)
 
-    slashed_validator = state.validator_registry[slashed_index]
+    slashed_validator = state.validators[slashed_index]
 
     # Check slashing
     assert slashed_validator.slashed
@@ -135,7 +135,7 @@ def test_participants_already_slashed(spec, state):
     attestation_1 = attester_slashing.attestation_1
     validator_indices = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices
     for index in validator_indices:
-        state.validator_registry[index].slashed = True
+        state.validators[index].slashed = True
 
     yield from run_attester_slashing_processing(spec, state, attester_slashing, False)
 
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_block_header.py
@@ -78,7 +78,7 @@ def test_proposer_slashed(spec, state):
     proposer_index = spec.get_beacon_proposer_index(stub_state)
 
     # set proposer to slashed
-    state.validator_registry[proposer_index].slashed = True
+    state.validators[proposer_index].slashed = True
 
     block = build_empty_block_for_next_slot(spec, state, signed=True)
 
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_deposit.py
@@ -16,7 +16,7 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef
       - post-state ('post').
     If ``valid == False``, run expecting ``AssertionError``
     """
-    pre_validator_count = len(state.validator_registry)
+    pre_validator_count = len(state.validators)
     pre_balance = 0
     if validator_index < pre_validator_count:
         pre_balance = get_balance(state, validator_index)
@@ -34,29 +34,29 @@ def run_deposit_processing(spec, state, deposit, validator_index, valid=True, ef
     yield 'post', state
 
     if not effective:
-        assert len(state.validator_registry) == pre_validator_count
+        assert len(state.validators) == pre_validator_count
         assert len(state.balances) == pre_validator_count
         if validator_index < pre_validator_count:
             assert get_balance(state, validator_index) == pre_balance
     else:
         if validator_index < pre_validator_count:
             # top-up
-            assert len(state.validator_registry) == pre_validator_count
+            assert len(state.validators) == pre_validator_count
             assert len(state.balances) == pre_validator_count
         else:
             # new validator
-            assert len(state.validator_registry) == pre_validator_count + 1
+            assert len(state.validators) == pre_validator_count + 1
             assert len(state.balances) == pre_validator_count + 1
         assert get_balance(state, validator_index) == pre_balance + deposit.data.amount
 
-    assert state.deposit_index == state.latest_eth1_data.deposit_count
+    assert state.eth1_deposit_index == state.eth1_data.deposit_count
 
 
 @with_all_phases
 @spec_state_test
 def test_new_deposit(spec, state):
     # fresh deposit = next validator index = validator appended to registry
-    validator_index = len(state.validator_registry)
+    validator_index = len(state.validators)
     amount = spec.MAX_EFFECTIVE_BALANCE
     deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
 
@@ -68,7 +68,7 @@ def test_new_deposit(spec, state):
 @spec_state_test
 def test_invalid_sig_new_deposit(spec, state):
     # fresh deposit = next validator index = validator appended to registry
-    validator_index = len(state.validator_registry)
+    validator_index = len(state.validators)
     amount = spec.MAX_EFFECTIVE_BALANCE
     deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
     yield from run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=False)
@@ -117,12 +117,12 @@ def test_invalid_withdrawal_credentials_top_up(spec, state):
 @with_all_phases
 @spec_state_test
 def test_wrong_index(spec, state):
-    validator_index = len(state.validator_registry)
+    validator_index = len(state.validators)
     amount = spec.MAX_EFFECTIVE_BALANCE
     deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
 
-    # mess up deposit_index
-    deposit.index = state.deposit_index + 1
+    # mess up eth1_deposit_index
+    deposit.index = state.eth1_deposit_index + 1
 
     sign_deposit_data(spec, state, deposit.data, privkeys[validator_index])
 
@@ -132,7 +132,7 @@ def test_wrong_index(spec, state):
 @with_all_phases
 @spec_state_test
 def test_wrong_deposit_for_deposit_count(spec, state):
-    deposit_data_leaves = [spec.ZERO_HASH] * len(state.validator_registry)
+    deposit_data_leaves = [spec.ZERO_HASH] * len(state.validators)
 
     # build root for deposit_1
     index_1 = len(deposit_data_leaves)
@@ -166,8 +166,8 @@ def test_wrong_deposit_for_deposit_count(spec, state):
     )
 
     # state has root for deposit_2 but is at deposit_count for deposit_1
-    state.latest_eth1_data.deposit_root = root_2
-    state.latest_eth1_data.deposit_count = deposit_count_1
+    state.eth1_data.deposit_root = root_2
+    state.eth1_data.deposit_count = deposit_count_1
 
     yield from run_deposit_processing(spec, state, deposit_2, index_2, valid=False)
 
@@ -178,7 +178,7 @@ def test_wrong_deposit_for_deposit_count(spec, state):
 @with_all_phases
 @spec_state_test
 def test_bad_merkle_proof(spec, state):
-    validator_index = len(state.validator_registry)
+    validator_index = len(state.validators)
     amount = spec.MAX_EFFECTIVE_BALANCE
     deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
 
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_proposer_slashing.py
@@ -28,7 +28,7 @@ def run_proposer_slashing_processing(spec, state, proposer_slashing, valid=True)
     yield 'post', state
 
     # check if slashed
-    slashed_validator = state.validator_registry[proposer_slashing.proposer_index]
+    slashed_validator = state.validators[proposer_slashing.proposer_index]
     assert slashed_validator.slashed
     assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
     assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
@@ -77,7 +77,7 @@ def test_invalid_sig_1_and_2(spec, state):
 def test_invalid_proposer_index(spec, state):
     proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
     # Index just too high (by 1)
-    proposer_slashing.proposer_index = len(state.validator_registry)
+    proposer_slashing.proposer_index = len(state.validators)
 
     yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
 
@@ -111,7 +111,7 @@ def test_proposer_is_not_activated(spec, state):
     proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
 
     # set proposer to be not active yet
-    state.validator_registry[proposer_slashing.proposer_index].activation_epoch = spec.get_current_epoch(state) + 1
+    state.validators[proposer_slashing.proposer_index].activation_epoch = spec.get_current_epoch(state) + 1
 
     yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
 
@@ -122,7 +122,7 @@ def test_proposer_is_slashed(spec, state):
     proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
 
     # set proposer to slashed
-    state.validator_registry[proposer_slashing.proposer_index].slashed = True
+    state.validators[proposer_slashing.proposer_index].slashed = True
 
     yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
 
@@ -137,6 +137,6 @@ def test_proposer_is_withdrawn(spec, state):
     # set proposer withdrawable_epoch in past
     current_epoch = spec.get_current_epoch(state)
     proposer_index = proposer_slashing.proposer_index
-    state.validator_registry[proposer_index].withdrawable_epoch = current_epoch - 1
+    state.validators[proposer_index].withdrawable_epoch = current_epoch - 1
 
     yield from run_proposer_slashing_processing(spec, state, proposer_slashing, False)
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_transfer.py
@@ -41,7 +41,7 @@ def run_transfer_processing(spec, state, transfer, valid=True):
 def test_success_non_activated(spec, state):
     transfer = get_valid_transfer(spec, state, signed=True)
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer)
 
@@ -55,7 +55,7 @@ def test_success_withdrawable(spec, state):
     transfer = get_valid_transfer(spec, state, signed=True)
 
     # withdrawable_epoch in past so can transfer
-    state.validator_registry[transfer.sender].withdrawable_epoch = spec.get_current_epoch(state) - 1
+    state.validators[transfer.sender].withdrawable_epoch = spec.get_current_epoch(state) - 1
 
     yield from run_transfer_processing(spec, state, transfer)
 
@@ -86,7 +86,7 @@ def test_success_active_above_max_effective_fee(spec, state):
 def test_invalid_signature(spec, state):
     transfer = get_valid_transfer(spec, state)
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer, False)
 
@@ -107,7 +107,7 @@ def test_active_but_transfer_past_effective_balance(spec, state):
 def test_incorrect_slot(spec, state):
     transfer = get_valid_transfer(spec, state, slot=state.slot + 1, signed=True)
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer, False)
 
@@ -120,7 +120,7 @@ def test_insufficient_balance_for_fee(spec, state):
     transfer = get_valid_transfer(spec, state, sender_index=sender_index, amount=0, fee=1, signed=True)
 
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer, False)
 
@@ -133,7 +133,7 @@ def test_insufficient_balance(spec, state):
     transfer = get_valid_transfer(spec, state, sender_index=sender_index, amount=1, fee=0, signed=True)
 
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer, False)
 
@@ -153,7 +153,7 @@ def test_no_dust_sender(spec, state):
     )
 
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer, False)
 
@@ -167,7 +167,7 @@ def test_no_dust_recipient(spec, state):
     state.balances[transfer.recipient] = 0
 
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer, False)
 
@@ -176,9 +176,9 @@ def test_no_dust_recipient(spec, state):
 @spec_state_test
 def test_invalid_pubkey(spec, state):
     transfer = get_valid_transfer(spec, state, signed=True)
-    state.validator_registry[transfer.sender].withdrawal_credentials = spec.ZERO_HASH
+    state.validators[transfer.sender].withdrawal_credentials = spec.ZERO_HASH
 
     # un-activate so validator can transfer
-    state.validator_registry[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[transfer.sender].activation_epoch = spec.FAR_FUTURE_EPOCH
 
     yield from run_transfer_processing(spec, state, transfer, False)
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py
--- a/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/block_processing/test_process_voluntary_exit.py
@@ -21,14 +21,14 @@ def run_voluntary_exit_processing(spec, state, voluntary_exit, valid=True):
         yield 'post', None
         return
 
-    pre_exit_epoch = state.validator_registry[validator_index].exit_epoch
+    pre_exit_epoch = state.validators[validator_index].exit_epoch
 
     spec.process_voluntary_exit(state, voluntary_exit)
 
     yield 'post', state
 
     assert pre_exit_epoch == spec.FAR_FUTURE_EPOCH
-    assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
+    assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
 
 
 @with_all_phases
@@ -39,7 +39,7 @@ def test_success(spec, state):
 
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
 
     voluntary_exit = build_voluntary_exit(spec, state, current_epoch, validator_index, privkey, signed=True)
 
@@ -55,7 +55,7 @@ def test_invalid_signature(spec, state):
 
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
 
     voluntary_exit = build_voluntary_exit(spec, state, current_epoch, validator_index, privkey)
 
@@ -76,7 +76,7 @@ def test_success_exit_queue(spec, state):
     # Prepare a bunch of exits, based on the current state
     exit_queue = []
     for index in initial_indices:
-        privkey = pubkey_to_privkey[state.validator_registry[index].pubkey]
+        privkey = pubkey_to_privkey[state.validators[index].pubkey]
         exit_queue.append(build_voluntary_exit(
             spec,
             state,
@@ -94,7 +94,7 @@ def test_success_exit_queue(spec, state):
 
     # exit an additional validator
     validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
     voluntary_exit = build_voluntary_exit(
         spec,
         state,
@@ -109,8 +109,8 @@ def test_success_exit_queue(spec, state):
     yield from run_voluntary_exit_processing(spec, state, voluntary_exit)
 
     assert (
-        state.validator_registry[validator_index].exit_epoch ==
-        state.validator_registry[initial_indices[0]].exit_epoch + 1
+        state.validators[validator_index].exit_epoch ==
+        state.validators[initial_indices[0]].exit_epoch + 1
     )
 
 
@@ -122,7 +122,7 @@ def test_validator_exit_in_future(spec, state):
 
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
 
     voluntary_exit = build_voluntary_exit(
         spec,
@@ -146,7 +146,7 @@ def test_validator_invalid_validator_index(spec, state):
 
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
 
     voluntary_exit = build_voluntary_exit(
         spec,
@@ -156,7 +156,7 @@ def test_validator_invalid_validator_index(spec, state):
         privkey,
         signed=False,
     )
-    voluntary_exit.validator_index = len(state.validator_registry)
+    voluntary_exit.validator_index = len(state.validators)
     sign_voluntary_exit(spec, state, voluntary_exit, privkey)
 
     yield from run_voluntary_exit_processing(spec, state, voluntary_exit, False)
@@ -167,9 +167,9 @@ def test_validator_invalid_validator_index(spec, state):
 def test_validator_not_active(spec, state):
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
 
-    state.validator_registry[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[validator_index].activation_epoch = spec.FAR_FUTURE_EPOCH
 
     # build and test voluntary exit
     voluntary_exit = build_voluntary_exit(
@@ -192,10 +192,10 @@ def test_validator_already_exited(spec, state):
 
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
 
     # but validator already has exited
-    state.validator_registry[validator_index].exit_epoch = current_epoch + 2
+    state.validators[validator_index].exit_epoch = current_epoch + 2
 
     voluntary_exit = build_voluntary_exit(
         spec,
@@ -214,7 +214,7 @@ def test_validator_already_exited(spec, state):
 def test_validator_not_active_long_enough(spec, state):
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[0]
-    privkey = pubkey_to_privkey[state.validator_registry[validator_index].pubkey]
+    privkey = pubkey_to_privkey[state.validators[validator_index].pubkey]
 
     voluntary_exit = build_voluntary_exit(
         spec,
@@ -226,7 +226,7 @@ def test_validator_not_active_long_enough(spec, state):
     )
 
     assert (
-        current_epoch - state.validator_registry[validator_index].activation_epoch <
+        current_epoch - state.validators[validator_index].activation_epoch <
         spec.PERSISTENT_COMMITTEE_PERIOD
     )
 
diff --git a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py
--- a/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py
+++ b/test_libs/pyspec/eth2spec/test/phase_0/epoch_processing/test_process_registry_updates.py
@@ -35,23 +35,23 @@ def run_process_registry_updates(spec, state, valid=True):
 @spec_state_test
 def test_activation(spec, state):
     index = 0
-    assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state))
+    assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
 
     # Mock a new deposit
-    state.validator_registry[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
-    state.validator_registry[index].activation_epoch = spec.FAR_FUTURE_EPOCH
-    state.validator_registry[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
-    assert not spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state))
+    state.validators[index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[index].activation_epoch = spec.FAR_FUTURE_EPOCH
+    state.validators[index].effective_balance = spec.MAX_EFFECTIVE_BALANCE
+    assert not spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
 
     for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
         next_epoch(spec, state)
 
     yield from run_process_registry_updates(spec, state)
 
-    assert state.validator_registry[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
-    assert state.validator_registry[index].activation_epoch != spec.FAR_FUTURE_EPOCH
+    assert state.validators[index].activation_eligibility_epoch != spec.FAR_FUTURE_EPOCH
+    assert state.validators[index].activation_epoch != spec.FAR_FUTURE_EPOCH
     assert spec.is_active_validator(
-        state.validator_registry[index],
+        state.validators[index],
         spec.get_current_epoch(state),
     )
 
@@ -60,19 +60,19 @@ def test_activation(spec, state):
 @spec_state_test
 def test_ejection(spec, state):
     index = 0
-    assert spec.is_active_validator(state.validator_registry[index], spec.get_current_epoch(state))
-    assert state.validator_registry[index].exit_epoch == spec.FAR_FUTURE_EPOCH
+    assert spec.is_active_validator(state.validators[index], spec.get_current_epoch(state))
+    assert state.validators[index].exit_epoch == spec.FAR_FUTURE_EPOCH
 
     # Mock an ejection
-    state.validator_registry[index].effective_balance = spec.EJECTION_BALANCE
+    state.validators[index].effective_balance = spec.EJECTION_BALANCE
 
     for _ in range(spec.ACTIVATION_EXIT_DELAY + 1):
         next_epoch(spec, state)
 
     yield from run_process_registry_updates(spec, state)
 
-    assert state.validator_registry[index].exit_epoch != spec.FAR_FUTURE_EPOCH
+    assert state.validators[index].exit_epoch != spec.FAR_FUTURE_EPOCH
     assert not spec.is_active_validator(
-        state.validator_registry[index],
+        state.validators[index],
         spec.get_current_epoch(state),
     )
diff --git a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py
--- a/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py
+++ b/test_libs/pyspec/eth2spec/test/phase_1/block_processing/test_process_early_derived_secret_reveal.py
@@ -24,7 +24,7 @@ def run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, v
 
     spec.process_early_derived_secret_reveal(state, randao_key_reveal)
 
-    slashed_validator = state.validator_registry[randao_key_reveal.revealed_index]
+    slashed_validator = state.validators[randao_key_reveal.revealed_index]
 
     if randao_key_reveal.epoch >= spec.get_current_epoch(state) + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING:
         assert slashed_validator.slashed
@@ -111,7 +111,7 @@ def test_double_reveal(spec, state):
 @spec_state_test
 def test_revealer_is_slashed(spec, state):
     randao_key_reveal = get_valid_early_derived_secret_reveal(spec, state, spec.get_current_epoch(state))
-    state.validator_registry[randao_key_reveal.revealed_index].slashed = True
+    state.validators[randao_key_reveal.revealed_index].slashed = True
 
     yield from run_early_derived_secret_reveal_processing(spec, state, randao_key_reveal, False)
 
diff --git a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py
--- a/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py
+++ b/test_libs/pyspec/eth2spec/test/sanity/test_blocks.py
@@ -91,7 +91,7 @@ def test_empty_epoch_transition(spec, state):
 
 #     assert state.slot == block.slot
 #     assert state.finalized_epoch < spec.get_current_epoch(state) - 4
-#     for index in range(len(state.validator_registry)):
+#     for index in range(len(state.validators)):
 #         assert get_balance(state, index) < get_balance(pre_state, index)
 
 
@@ -103,7 +103,7 @@ def test_proposer_slashing(spec, state):
     proposer_slashing = get_valid_proposer_slashing(spec, state, signed_1=True, signed_2=True)
     validator_index = proposer_slashing.proposer_index
 
-    assert not state.validator_registry[validator_index].slashed
+    assert not state.validators[validator_index].slashed
 
     yield 'pre', state
 
@@ -119,7 +119,7 @@ def test_proposer_slashing(spec, state):
     yield 'post', state
 
     # check if slashed
-    slashed_validator = state.validator_registry[validator_index]
+    slashed_validator = state.validators[validator_index]
     assert slashed_validator.slashed
     assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
     assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
@@ -137,7 +137,7 @@ def test_attester_slashing(spec, state):
     validator_index = (attester_slashing.attestation_1.custody_bit_0_indices +
                        attester_slashing.attestation_1.custody_bit_1_indices)[0]
 
-    assert not state.validator_registry[validator_index].slashed
+    assert not state.validators[validator_index].slashed
 
     yield 'pre', state
 
@@ -152,7 +152,7 @@ def test_attester_slashing(spec, state):
     spec.state_transition(state, block)
     yield 'post', state
 
-    slashed_validator = state.validator_registry[validator_index]
+    slashed_validator = state.validators[validator_index]
     assert slashed_validator.slashed
     assert slashed_validator.exit_epoch < spec.FAR_FUTURE_EPOCH
     assert slashed_validator.withdrawable_epoch < spec.FAR_FUTURE_EPOCH
@@ -172,10 +172,10 @@ def test_attester_slashing(spec, state):
 @with_all_phases
 @spec_state_test
 def test_deposit_in_block(spec, state):
-    initial_registry_len = len(state.validator_registry)
+    initial_registry_len = len(state.validators)
     initial_balances_len = len(state.balances)
 
-    validator_index = len(state.validator_registry)
+    validator_index = len(state.validators)
     amount = spec.MAX_EFFECTIVE_BALANCE
     deposit = prepare_state_and_deposit(spec, state, validator_index, amount, signed=True)
 
@@ -190,10 +190,10 @@ def test_deposit_in_block(spec, state):
     spec.state_transition(state, block)
     yield 'post', state
 
-    assert len(state.validator_registry) == initial_registry_len + 1
+    assert len(state.validators) == initial_registry_len + 1
     assert len(state.balances) == initial_balances_len + 1
     assert get_balance(state, validator_index) == spec.MAX_EFFECTIVE_BALANCE
-    assert state.validator_registry[validator_index].pubkey == pubkeys[validator_index]
+    assert state.validators[validator_index].pubkey == pubkeys[validator_index]
 
 
 @with_all_phases
@@ -203,7 +203,7 @@ def test_deposit_top_up(spec, state):
     amount = spec.MAX_EFFECTIVE_BALANCE // 4
     deposit = prepare_state_and_deposit(spec, state, validator_index, amount)
 
-    initial_registry_len = len(state.validator_registry)
+    initial_registry_len = len(state.validators)
     initial_balances_len = len(state.balances)
     validator_pre_balance = get_balance(state, validator_index)
 
@@ -218,7 +218,7 @@ def test_deposit_top_up(spec, state):
     spec.state_transition(state, block)
     yield 'post', state
 
-    assert len(state.validator_registry) == initial_registry_len
+    assert len(state.validators) == initial_registry_len
     assert len(state.balances) == initial_balances_len
     assert get_balance(state, validator_index) == validator_pre_balance + amount
 
@@ -289,7 +289,7 @@ def test_voluntary_exit(spec, state):
     sign_block(spec, state, initiate_exit_block)
     spec.state_transition(state, initiate_exit_block)
 
-    assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
+    assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
 
     # Process within epoch transition
     exit_block = build_empty_block_for_next_slot(spec, state)
@@ -300,7 +300,7 @@ def test_voluntary_exit(spec, state):
     yield 'blocks', [initiate_exit_block, exit_block], List[spec.BeaconBlock]
     yield 'post', state
 
-    assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
+    assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
 
 
 # @with_all_phases
@@ -317,7 +317,7 @@ def test_voluntary_exit(spec, state):
     # pre_transfer_recipient_balance = get_balance(state, recipient_index)
 
     # un-activate so validator can transfer
-    # state.validator_registry[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
+    # state.validators[sender_index].activation_eligibility_epoch = spec.FAR_FUTURE_EPOCH
 
     # yield 'pre', state
 
@@ -343,10 +343,10 @@ def test_balance_driven_status_transitions(spec, state):
     current_epoch = spec.get_current_epoch(state)
     validator_index = spec.get_active_validator_indices(state, current_epoch)[-1]
 
-    assert state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
+    assert state.validators[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH
 
     # set validator balance to below ejection threshold
-    state.validator_registry[validator_index].effective_balance = spec.EJECTION_BALANCE
+    state.validators[validator_index].effective_balance = spec.EJECTION_BALANCE
 
     yield 'pre', state
 
@@ -359,7 +359,7 @@ def test_balance_driven_status_transitions(spec, state):
     yield 'blocks', [block], List[spec.BeaconBlock]
     yield 'post', state
 
-    assert state.validator_registry[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
+    assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH
 
 
 @with_all_phases