Skip to content

Commit ca64850

Browse files
authored
Merge pull request #3783 from mkalinin/electra-maxeb-preset
Switch the rest of the spec to MAX_EFFECTIVE_BALANCE_ELECTRA
2 parents 031b191 + 718aadf commit ca64850

File tree

6 files changed

+121
-17
lines changed

6 files changed

+121
-17
lines changed

specs/electra/beacon-chain.md

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
- [New `get_active_balance`](#new-get_active_balance)
5959
- [New `get_pending_balance_to_withdraw`](#new-get_pending_balance_to_withdraw)
6060
- [Modified `get_attesting_indices`](#modified-get_attesting_indices)
61+
- [Modified `get_next_sync_committee_indices`](#modified-get_next_sync_committee_indices)
6162
- [Beacon state mutators](#beacon-state-mutators)
6263
- [Updated `initiate_validator_exit`](#updated--initiate_validator_exit)
6364
- [New `switch_to_compounding_validator`](#new-switch_to_compounding_validator)
@@ -126,8 +127,6 @@ The following values are (non-configurable) constants used throughout the specif
126127

127128
| Name | Value |
128129
| - | - |
129-
| `BLS_WITHDRAWAL_PREFIX` | `Bytes1('0x00')` |
130-
| `ETH1_ADDRESS_WITHDRAWAL_PREFIX` | `Bytes1('0x01')` |
131130
| `COMPOUNDING_WITHDRAWAL_PREFIX` | `Bytes1('0x02')` |
132131

133132
### Domains
@@ -432,6 +431,8 @@ class BeaconState(Container):
432431

433432
#### Updated `compute_proposer_index`
434433

434+
*Note*: The function is modified to use `MAX_EFFECTIVE_BALANCE_ELECTRA` preset.
435+
435436
```python
436437
def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32) -> ValidatorIndex:
437438
"""
@@ -615,6 +616,36 @@ def get_attesting_indices(state: BeaconState, attestation: Attestation) -> Set[V
615616
return output
616617
```
617618

619+
#### Modified `get_next_sync_committee_indices`
620+
621+
*Note*: The function is modified to use `MAX_EFFECTIVE_BALANCE_ELECTRA` preset.
622+
623+
```python
624+
def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]:
625+
"""
626+
Return the sync committee indices, with possible duplicates, for the next sync committee.
627+
"""
628+
epoch = Epoch(get_current_epoch(state) + 1)
629+
630+
MAX_RANDOM_BYTE = 2**8 - 1
631+
active_validator_indices = get_active_validator_indices(state, epoch)
632+
active_validator_count = uint64(len(active_validator_indices))
633+
seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE)
634+
i = 0
635+
sync_committee_indices: List[ValidatorIndex] = []
636+
while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE:
637+
shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed)
638+
candidate_index = active_validator_indices[shuffled_index]
639+
random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32]
640+
effective_balance = state.validators[candidate_index].effective_balance
641+
# [Modified in Electra:EIP7251]
642+
if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_byte:
643+
sync_committee_indices.append(candidate_index)
644+
i += 1
645+
return sync_committee_indices
646+
```
647+
648+
618649
### Beacon state mutators
619650

620651
#### Updated `initiate_validator_exit`
@@ -1438,8 +1469,10 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
14381469
# Process activations
14391470
for index, validator in enumerate(state.validators):
14401471
balance = state.balances[index]
1441-
validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
1442-
if validator.effective_balance == MAX_EFFECTIVE_BALANCE:
1472+
# [Modified in Electra:EIP7251]
1473+
validator.effective_balance = min(
1474+
balance - balance % EFFECTIVE_BALANCE_INCREMENT, get_validator_max_effective_balance(validator))
1475+
if validator.effective_balance >= MIN_ACTIVATION_BALANCE:
14431476
validator.activation_eligibility_epoch = GENESIS_EPOCH
14441477
validator.activation_epoch = GENESIS_EPOCH
14451478

tests/core/pyspec/eth2spec/test/altair/block_processing/sync_aggregate/test_process_sync_aggregate.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
with_presets,
2525
spec_state_test,
2626
always_bls,
27+
single_phase,
28+
with_custom_state,
29+
spec_test,
30+
default_balances_electra,
31+
default_activation_threshold,
2732
)
2833

2934

@@ -143,7 +148,9 @@ def is_duplicate_sync_committee(committee_indices):
143148

144149
@with_altair_and_later
145150
@with_presets([MINIMAL], reason="to create nonduplicate committee")
146-
@spec_state_test
151+
@spec_test
152+
@with_custom_state(balances_fn=default_balances_electra, threshold_fn=default_activation_threshold)
153+
@single_phase
147154
def test_sync_committee_rewards_nonduplicate_committee(spec, state):
148155
committee_indices = compute_committee_indices(state)
149156

tests/core/pyspec/eth2spec/test/altair/block_processing/sync_aggregate/test_process_sync_aggregate_random.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
with_custom_state,
2525
with_presets,
2626
spec_test,
27+
default_balances_electra,
28+
misc_balances_electra,
2729
)
2830

2931

@@ -132,7 +134,9 @@ def test_random_with_exits_with_duplicates(spec, state):
132134

133135
@with_altair_and_later
134136
@with_presets([MINIMAL], reason="to create nonduplicate committee")
135-
@spec_state_test
137+
@spec_test
138+
@with_custom_state(balances_fn=default_balances_electra, threshold_fn=default_activation_threshold)
139+
@single_phase
136140
def test_random_only_one_participant_without_duplicates(spec, state):
137141
rng = random.Random(501)
138142
yield from _test_harness_for_randomized_test_case(
@@ -144,7 +148,9 @@ def test_random_only_one_participant_without_duplicates(spec, state):
144148

145149
@with_altair_and_later
146150
@with_presets([MINIMAL], reason="to create nonduplicate committee")
147-
@spec_state_test
151+
@spec_test
152+
@with_custom_state(balances_fn=default_balances_electra, threshold_fn=default_activation_threshold)
153+
@single_phase
148154
def test_random_low_participation_without_duplicates(spec, state):
149155
rng = random.Random(601)
150156
yield from _test_harness_for_randomized_test_case(
@@ -156,7 +162,9 @@ def test_random_low_participation_without_duplicates(spec, state):
156162

157163
@with_altair_and_later
158164
@with_presets([MINIMAL], reason="to create nonduplicate committee")
159-
@spec_state_test
165+
@spec_test
166+
@with_custom_state(balances_fn=default_balances_electra, threshold_fn=default_activation_threshold)
167+
@single_phase
160168
def test_random_high_participation_without_duplicates(spec, state):
161169
rng = random.Random(701)
162170
yield from _test_harness_for_randomized_test_case(
@@ -168,7 +176,9 @@ def test_random_high_participation_without_duplicates(spec, state):
168176

169177
@with_altair_and_later
170178
@with_presets([MINIMAL], reason="to create nonduplicate committee")
171-
@spec_state_test
179+
@spec_test
180+
@with_custom_state(balances_fn=default_balances_electra, threshold_fn=default_activation_threshold)
181+
@single_phase
172182
def test_random_all_but_one_participating_without_duplicates(spec, state):
173183
rng = random.Random(801)
174184
yield from _test_harness_for_randomized_test_case(
@@ -181,7 +191,7 @@ def test_random_all_but_one_participating_without_duplicates(spec, state):
181191
@with_altair_and_later
182192
@with_presets([MINIMAL], reason="to create nonduplicate committee")
183193
@spec_test
184-
@with_custom_state(balances_fn=misc_balances, threshold_fn=default_activation_threshold)
194+
@with_custom_state(balances_fn=misc_balances_electra, threshold_fn=default_activation_threshold)
185195
@single_phase
186196
def test_random_misc_balances_and_half_participation_without_duplicates(spec, state):
187197
rng = random.Random(1501)
@@ -194,7 +204,8 @@ def test_random_misc_balances_and_half_participation_without_duplicates(spec, st
194204

195205
@with_altair_and_later
196206
@with_presets([MINIMAL], reason="to create nonduplicate committee")
197-
@spec_state_test
207+
@spec_test
208+
@with_custom_state(balances_fn=default_balances_electra, threshold_fn=default_activation_threshold)
198209
@single_phase
199210
def test_random_with_exits_without_duplicates(spec, state):
200211
rng = random.Random(1502)

tests/core/pyspec/eth2spec/test/context.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
ALLOWED_TEST_RUNNER_FORKS,
1717
LIGHT_CLIENT_TESTING_FORKS,
1818
)
19-
from .helpers.forks import is_post_fork
19+
from .helpers.forks import is_post_fork, is_post_electra
2020
from .helpers.genesis import create_genesis_state
2121
from .helpers.typing import (
2222
Spec,
@@ -86,7 +86,10 @@ def default_activation_threshold(spec: Spec):
8686
Helper method to use the default balance activation threshold for state creation for tests.
8787
Usage: `@with_custom_state(threshold_fn=default_activation_threshold, ...)`
8888
"""
89-
return spec.MAX_EFFECTIVE_BALANCE
89+
if is_post_electra(spec):
90+
return spec.MIN_ACTIVATION_BALANCE
91+
else:
92+
return spec.MAX_EFFECTIVE_BALANCE
9093

9194

9295
def zero_activation_threshold(spec: Spec):
@@ -106,6 +109,18 @@ def default_balances(spec: Spec):
106109
return [spec.MAX_EFFECTIVE_BALANCE] * num_validators
107110

108111

112+
def default_balances_electra(spec: Spec):
113+
"""
114+
Helper method to create a series of default balances for Electra.
115+
Usage: `@with_custom_state(balances_fn=default_balances_electra, ...)`
116+
"""
117+
if not is_post_electra(spec):
118+
return default_balances(spec)
119+
120+
num_validators = spec.SLOTS_PER_EPOCH * 8
121+
return [spec.MAX_EFFECTIVE_BALANCE_ELECTRA] * num_validators
122+
123+
109124
def scaled_churn_balances_min_churn_limit(spec: Spec):
110125
"""
111126
Helper method to create enough validators to scale the churn limit.
@@ -175,6 +190,21 @@ def misc_balances(spec: Spec):
175190
return balances
176191

177192

193+
def misc_balances_electra(spec: Spec):
194+
"""
195+
Helper method to create a series of balances that includes some misc. balances for Electra.
196+
Usage: `@with_custom_state(balances_fn=misc_balances, ...)`
197+
"""
198+
if not is_post_electra(spec):
199+
return misc_balances(spec)
200+
201+
num_validators = spec.SLOTS_PER_EPOCH * 8
202+
balances = [spec.MAX_EFFECTIVE_BALANCE_ELECTRA * 2 * i // num_validators for i in range(num_validators)]
203+
rng = Random(1234)
204+
rng.shuffle(balances)
205+
return balances
206+
207+
178208
def misc_balances_in_default_range_with_many_validators(spec: Spec):
179209
"""
180210
Helper method to create a series of balances that includes some misc. balances but

tests/core/pyspec/eth2spec/test/helpers/genesis.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,31 @@
1515
def build_mock_validator(spec, i: int, balance: int):
1616
active_pubkey = pubkeys[i]
1717
withdrawal_pubkey = pubkeys[-1 - i]
18-
# insecurely use pubkey as withdrawal key as well
19-
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(withdrawal_pubkey)[1:]
18+
if is_post_electra(spec):
19+
if balance > spec.MIN_ACTIVATION_BALANCE:
20+
# use compounding withdrawal credentials if the balance is higher than MIN_ACTIVATION_BALANCE
21+
withdrawal_credentials = (
22+
spec.COMPOUNDING_WITHDRAWAL_PREFIX
23+
+ b'\x00' * 11
24+
+ spec.hash(withdrawal_pubkey)[12:]
25+
)
26+
else:
27+
# insecurely use pubkey as withdrawal key as well
28+
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(withdrawal_pubkey)[1:]
29+
max_effective_balace = spec.MAX_EFFECTIVE_BALANCE_ELECTRA
30+
else:
31+
# insecurely use pubkey as withdrawal key as well
32+
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(withdrawal_pubkey)[1:]
33+
max_effective_balace = spec.MAX_EFFECTIVE_BALANCE
34+
2035
validator = spec.Validator(
2136
pubkey=active_pubkey,
2237
withdrawal_credentials=withdrawal_credentials,
2338
activation_eligibility_epoch=spec.FAR_FUTURE_EPOCH,
2439
activation_epoch=spec.FAR_FUTURE_EPOCH,
2540
exit_epoch=spec.FAR_FUTURE_EPOCH,
2641
withdrawable_epoch=spec.FAR_FUTURE_EPOCH,
27-
effective_balance=min(balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, spec.MAX_EFFECTIVE_BALANCE)
42+
effective_balance=min(balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, max_effective_balace)
2843
)
2944

3045
return validator

tests/core/pyspec/eth2spec/test/phase0/genesis/test_initialization.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
)
1212
from eth2spec.test.helpers.forks import (
1313
is_post_altair,
14+
is_post_electra,
1415
)
1516

1617

@@ -69,9 +70,14 @@ def test_initialize_beacon_state_some_small_balances(spec):
6970
if is_post_altair(spec):
7071
yield 'description', 'meta', get_post_altair_description(spec)
7172

73+
if is_post_electra(spec):
74+
max_effective_balance = spec.MAX_EFFECTIVE_BALANCE_ELECTRA
75+
else:
76+
max_effective_balance = spec.MAX_EFFECTIVE_BALANCE
77+
7278
main_deposit_count = spec.config.MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
7379
main_deposits, _, deposit_data_list = prepare_full_genesis_deposits(
74-
spec, spec.MAX_EFFECTIVE_BALANCE,
80+
spec, max_effective_balance,
7581
deposit_count=main_deposit_count, signed=True,
7682
)
7783
# For deposits above, and for another deposit_count, add a balance of EFFECTIVE_BALANCE_INCREMENT
@@ -99,6 +105,8 @@ def test_initialize_beacon_state_some_small_balances(spec):
99105
assert state.eth1_data.deposit_count == len(deposits)
100106
assert state.eth1_data.block_hash == eth1_block_hash
101107
# only main deposits participate to the active balance
108+
# NOTE: they are pre-ELECTRA deposits with BLS_WITHDRAWAL_PREFIX,
109+
# so `MAX_EFFECTIVE_BALANCE` is used
102110
assert spec.get_total_active_balance(state) == main_deposit_count * spec.MAX_EFFECTIVE_BALANCE
103111

104112
# yield state

0 commit comments

Comments
 (0)