Skip to content

Commit 1f7172a

Browse files
committed
Put validator balances into a separate list in the state
1 parent c8b5f09 commit 1f7172a

File tree

10 files changed

+72
-52
lines changed

10 files changed

+72
-52
lines changed

eth/beacon/deposit_helpers.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@
3030

3131

3232
def get_min_empty_validator_index(validators: Sequence[ValidatorRecord],
33+
validator_balances: Sequence[int],
3334
current_slot: int,
3435
zero_balance_validator_ttl: int) -> int:
35-
for index, validator in enumerate(validators):
36+
for index, (validator, balance) in enumerate(zip(validators, validator_balances)):
3637
is_empty = (
37-
validator.balance == 0 and
38+
balance == 0 and
3839
validator.latest_status_change_slot + zero_balance_validator_ttl <= current_slot
3940
)
4041
if is_empty:
@@ -74,6 +75,7 @@ def validate_proof_of_possession(state: BeaconState,
7475

7576
def add_pending_validator(state: BeaconState,
7677
validator: ValidatorRecord,
78+
deposit: int,
7779
zero_balance_validator_ttl: int) -> Tuple[BeaconState, int]:
7880
"""
7981
Add a validator to the existing minimum empty validator index or
@@ -83,6 +85,7 @@ def add_pending_validator(state: BeaconState,
8385
try:
8486
index = get_min_empty_validator_index(
8587
state.validator_registry,
88+
state.validator_balances,
8689
state.slot,
8790
zero_balance_validator_ttl,
8891
)
@@ -93,11 +96,12 @@ def add_pending_validator(state: BeaconState,
9396
validator_registry = state.validator_registry + (validator,)
9497
state = state.copy(
9598
validator_registry=validator_registry,
99+
validator_balances=state.validator_balances + (deposit, )
96100
)
97101
index = len(state.validator_registry) - 1
98102
else:
99103
# Use the empty validator index
100-
state = state.update_validator(index, validator)
104+
state = state.update_validator(index, validator, deposit)
101105

102106
return state, index
103107

@@ -127,13 +131,13 @@ def process_deposit(*,
127131
pubkey=pubkey,
128132
withdrawal_credentials=withdrawal_credentials,
129133
randao_commitment=randao_commitment,
130-
balance=deposit,
131134
latest_status_change_slot=state.slot,
132135
)
133136

134137
state, index = add_pending_validator(
135138
state,
136139
validator,
140+
deposit,
137141
zero_balance_validator_ttl,
138142
)
139143
else:
@@ -151,9 +155,10 @@ def process_deposit(*,
151155
)
152156

153157
# Update validator's balance and state
154-
validator = validator.copy(
155-
balance=validator.balance + deposit,
158+
state = state.update_validator(
159+
validator_index=index,
160+
validator=validator,
161+
balance=state.validator_balances[index] + deposit,
156162
)
157-
state = state.update_validator(index, validator)
158163

159164
return state, index

eth/beacon/helpers.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,12 @@ def get_attestation_participants(state: 'BeaconState',
350350
#
351351
# Misc
352352
#
353-
def get_effective_balance(validator: 'ValidatorRecord', max_deposit: int) -> int:
353+
def get_effective_balance(validator_balances: Sequence[int], index: int, max_deposit: int) -> int:
354354
"""
355-
Return the effective balance (also known as "balance at stake") for the ``validator``.
355+
Return the effective balance (also known as "balance at stake") for a
356+
``validator`` with the given ``index``.
356357
"""
357-
return min(validator.balance, max_deposit * denoms.gwei)
358+
return min(validator_balances[index], max_deposit * denoms.gwei)
358359

359360

360361
def get_new_validator_registry_delta_chain_tip(current_validator_registry_delta_chain_tip: Hash32,

eth/beacon/types/states.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class BeaconState(rlp.Serializable):
4444

4545
# Validator registry
4646
('validator_registry', CountableList(ValidatorRecord)),
47+
('validator_balances', CountableList(uint64)),
4748
('validator_registry_latest_change_slot', uint64),
4849
('validator_registry_exit_count', uint64),
4950
('validator_registry_delta_chain_tip', hash32), # For light clients to easily track delta
@@ -89,6 +90,7 @@ def __init__(
8990
finalized_slot: int,
9091
processed_pow_receipt_root: Hash32,
9192
validator_registry: Sequence[ValidatorRecord]=(),
93+
validator_balances: Sequence[int]=(),
9294
shard_committees_at_slots: Sequence[Sequence[ShardCommittee]]=(),
9395
persistent_committees: Sequence[Sequence[int]]=(),
9496
persistent_committee_reassignments: Sequence[ShardReassignmentRecord]=(),
@@ -106,6 +108,7 @@ def __init__(
106108
fork_data=fork_data,
107109
# Validator registry
108110
validator_registry=validator_registry,
111+
validator_balances=validator_balances,
109112
validator_registry_latest_change_slot=validator_registry_latest_change_slot,
110113
validator_registry_exit_count=validator_registry_exit_count,
111114
validator_registry_delta_chain_tip=validator_registry_delta_chain_tip,
@@ -160,10 +163,16 @@ def num_crosslinks(self) -> int:
160163

161164
def update_validator(self,
162165
validator_index: int,
163-
validator: ValidatorRecord) -> 'BeaconState':
166+
validator: ValidatorRecord,
167+
balance: int) -> 'BeaconState':
164168
validator_registry = list(self.validator_registry)
165169
validator_registry[validator_index] = validator
170+
171+
validator_balances = list(self.validator_balances)
172+
validator_balances[validator_index] = balance
173+
166174
updated_state = self.copy(
167175
validator_registry=tuple(validator_registry),
176+
validator_balances=tuple(validator_balances),
168177
)
169178
return updated_state

eth/beacon/types/validator_records.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ class ValidatorRecord(rlp.Serializable):
3232
('randao_commitment', hash32),
3333
# Slot the proposer has skipped (ie. layers of RANDAO expected)
3434
('randao_layers', uint64),
35-
# Balance in Gwei
36-
('balance', uint64),
3735
# Status code
3836
('status', uint64),
3937
# Slot when validator last changed status (or 0)
@@ -47,7 +45,6 @@ def __init__(self,
4745
withdrawal_credentials: Hash32,
4846
randao_commitment: Hash32,
4947
randao_layers: int,
50-
balance: int,
5148
status: int,
5249
latest_status_change_slot: int,
5350
exit_count: int) -> None:
@@ -56,7 +53,6 @@ def __init__(self,
5653
withdrawal_credentials=withdrawal_credentials,
5754
randao_commitment=randao_commitment,
5855
randao_layers=randao_layers,
59-
balance=balance,
6056
status=status,
6157
latest_status_change_slot=latest_status_change_slot,
6258
exit_count=exit_count,
@@ -74,7 +70,6 @@ def get_pending_validator(cls,
7470
pubkey: int,
7571
withdrawal_credentials: Hash32,
7672
randao_commitment: Hash32,
77-
balance: int,
7873
latest_status_change_slot: int) -> 'ValidatorRecord':
7974
"""
8075
Return a new pending ``ValidatorRecord`` with the given fields.
@@ -84,7 +79,6 @@ def get_pending_validator(cls,
8479
withdrawal_credentials=withdrawal_credentials,
8580
randao_commitment=randao_commitment,
8681
randao_layers=0,
87-
balance=balance,
8882
status=ValidatorStatusCode.PENDING_ACTIVATION,
8983
latest_status_change_slot=latest_status_change_slot,
9084
exit_count=0,

tests/beacon/conftest.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import pytest
22

3-
from eth_utils import denoms
4-
53
from eth.constants import (
64
ZERO_HASH32,
75
)
@@ -131,6 +129,7 @@ def sample_beacon_state_params(sample_fork_data_params):
131129
'genesis_time': 0,
132130
'fork_data': ForkData(**sample_fork_data_params),
133131
'validator_registry': (),
132+
'validator_balances': (),
134133
'validator_registry_latest_change_slot': 10,
135134
'validator_registry_exit_count': 10,
136135
'validator_registry_delta_chain_tip': b'\x55' * 32,
@@ -287,7 +286,6 @@ def sample_validator_record_params():
287286
'withdrawal_credentials': b'\x01' * 32,
288287
'randao_commitment': b'\x01' * 32,
289288
'randao_layers': 1,
290-
'balance': 100,
291289
'status': 1,
292290
'latest_status_change_slot': 0,
293291
'exit_count': 0
@@ -498,7 +496,6 @@ def genesis_validators(init_validator_keys,
498496
withdrawal_credentials=ZERO_HASH32,
499497
randao_commitment=init_randao,
500498
randao_layers=0,
501-
balance=max_deposit * denoms.gwei,
502499
status=ValidatorStatusCode.ACTIVE,
503500
latest_status_change_slot=0,
504501
exit_count=0,

tests/beacon/helpers.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@
88
from eth_utils import to_tuple
99

1010

11-
def mock_validator_record(pubkey, max_deposit):
11+
def mock_validator_record(pubkey):
1212
return ValidatorRecord(
1313
pubkey=pubkey,
1414
withdrawal_credentials=b'\x44' * 32,
1515
randao_commitment=b'\x55' * 32,
1616
randao_layers=0,
17-
balance=max_deposit,
1817
status=ValidatorStatusCode.ACTIVE,
1918
latest_status_change_slot=0,
2019
exit_count=0,

tests/beacon/test_deposit_helpers.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,24 +60,30 @@ def test_get_min_empty_validator_index(sample_validator_record_params,
6060
latest_status_change_slot,
6161
zero_balance_validator_ttl,
6262
current_slot,
63+
max_deposit,
6364
expected):
6465
validators = [
6566
ValidatorRecord(**sample_validator_record_params).copy(
66-
balance=balance,
6767
latest_status_change_slot=latest_status_change_slot,
6868
)
6969
for _ in range(10)
7070
]
71+
validator_balances = [
72+
balance
73+
for _ in range(10)
74+
]
7175
if isinstance(expected, Exception):
7276
with pytest.raises(MinEmptyValidatorIndexNotFound):
7377
get_min_empty_validator_index(
7478
validators=validators,
79+
validator_balances=validator_balances,
7580
current_slot=current_slot,
7681
zero_balance_validator_ttl=zero_balance_validator_ttl,
7782
)
7883
else:
7984
result = get_min_empty_validator_index(
8085
validators=validators,
86+
validator_balances=validator_balances,
8187
current_slot=current_slot,
8288
zero_balance_validator_ttl=zero_balance_validator_ttl,
8389
)
@@ -103,6 +109,7 @@ def test_add_pending_validator(monkeypatch,
103109
from eth.beacon import deposit_helpers
104110

105111
def mock_get_min_empty_validator_index(validators,
112+
validator_balances,
106113
current_slot,
107114
zero_balance_validator_ttl):
108115
if min_empty_validator_index_result is None:
@@ -118,18 +125,20 @@ def mock_get_min_empty_validator_index(validators,
118125

119126
state = BeaconState(**sample_beacon_state_params).copy(
120127
validator_registry=[
121-
ValidatorRecord(**sample_validator_record_params).copy(
122-
balance=100,
123-
)
128+
ValidatorRecord(**sample_validator_record_params)
124129
for _ in range(validator_registry_len)
125-
]
126-
)
127-
validator = ValidatorRecord(**sample_validator_record_params).copy(
128-
balance=5566,
130+
],
131+
validator_balances=[
132+
100
133+
for _ in range(validator_registry_len)
134+
],
129135
)
136+
validator = ValidatorRecord(**sample_validator_record_params)
137+
deposit = 5566
130138
state, index = add_pending_validator(
131139
state,
132140
validator,
141+
deposit,
133142
zero_balance_validator_ttl=0, # it's for `get_min_empty_validator_index`
134143
)
135144
assert index == expected_index
@@ -225,7 +234,7 @@ def test_process_deposit(sample_beacon_state_params,
225234
assert result_state.validator_registry[0].pubkey == pubkey_1
226235
assert result_state.validator_registry[index].withdrawal_credentials == withdrawal_credentials
227236
assert result_state.validator_registry[index].randao_commitment == randao_commitment
228-
assert result_state.validator_registry[index].balance == deposit
237+
assert result_state.validator_balances[index] == deposit
229238
# test immutable
230239
assert len(state.validator_registry) == 0
231240

@@ -254,11 +263,11 @@ def test_process_deposit(sample_beacon_state_params,
254263
result_state = result_state.copy(
255264
validator_registry=(
256265
result_state.validator_registry[0].copy(
257-
balance=0,
258266
latest_status_change_slot=0,
259267
),
260268
result_state.validator_registry[1],
261-
)
269+
),
270+
validator_balances=(0,) + result_state.validator_balances[1:]
262271
)
263272

264273
# Add the third validator.

tests/beacon/test_helpers.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -606,10 +606,8 @@ def mock_get_shard_committees_at_slot(state,
606606
]
607607
)
608608
def test_get_effective_balance(balance, max_deposit, expected, sample_validator_record_params):
609-
validator = ValidatorRecord(**sample_validator_record_params).copy(
610-
balance=balance,
611-
)
612-
result = get_effective_balance(validator, max_deposit)
609+
balances = (balance,)
610+
result = get_effective_balance(balances, 0, max_deposit)
613611
assert result == expected
614612

615613

tests/beacon/types/test_states.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,17 @@ def test_defaults(sample_beacon_state_params):
6565
def test_num_validators(expected,
6666
max_deposit,
6767
empty_beacon_state):
68-
validator_registry = [
69-
mock_validator_record(
70-
pubkey,
71-
max_deposit,
72-
)
73-
for pubkey in range(expected)
74-
]
7568
state = empty_beacon_state.copy(
76-
validator_registry=validator_registry,
69+
validator_registry=[
70+
mock_validator_record(
71+
pubkey,
72+
)
73+
for pubkey in range(expected)
74+
],
75+
validator_balances=(
76+
max_deposit
77+
for _ in range(10)
78+
)
7779
)
7880

7981
assert state.num_validators == expected
@@ -106,17 +108,26 @@ def test_update_validator(sample_beacon_state_params, sample_validator_record_pa
106108
validator_registry=[
107109
mock_validator_record(
108110
pubkey,
109-
max_deposit,
110111
)
111112
for pubkey in range(10)
112-
]
113+
],
114+
validator_balances=(
115+
max_deposit
116+
for _ in range(10)
117+
)
113118
)
114119

115120
new_pubkey = 100
116121
validator_index = 5
122+
balance = 5566
117123
validator = state.validator_registry[validator_index].copy(
118124
pubkey=new_pubkey,
119125
)
120-
result_state = state.update_validator(validator_index=validator_index, validator=validator)
126+
result_state = state.update_validator(
127+
validator_index=validator_index,
128+
validator=validator,
129+
balance=balance,
130+
)
131+
assert result_state.validator_balances[validator_index] == balance
121132
assert result_state.validator_registry[validator_index].pubkey == new_pubkey
122133
assert state.validator_registry[validator_index].pubkey != new_pubkey

0 commit comments

Comments
 (0)