Skip to content

Commit fa338e6

Browse files
committed
Merge branch 'master' into p2p-dump
2 parents 721e66d + a3248fe commit fa338e6

File tree

11 files changed

+346
-36
lines changed

11 files changed

+346
-36
lines changed

Diff for: ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/WithdrawalPrefixes.java

+2
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@
1818
public class WithdrawalPrefixes {
1919
public static final Bytes BLS_WITHDRAWAL_PREFIX = Bytes.fromHexString("0x00");
2020
public static final byte ETH1_ADDRESS_WITHDRAWAL_BYTE = 0x01;
21+
public static final byte COMPOUNDING_WITHDRAWAL_BYTE = 0x02;
2122
public static final Bytes ETH1_ADDRESS_WITHDRAWAL_PREFIX = Bytes.of(ETH1_ADDRESS_WITHDRAWAL_BYTE);
23+
public static final Bytes COMPOUNDING_WITHDRAWAL_PREFIX = Bytes.of(COMPOUNDING_WITHDRAWAL_BYTE);
2224
}

Diff for: ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/statetransition/epoch/AbstractEpochProcessor.java

+14-7
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public abstract class AbstractEpochProcessor implements EpochProcessor {
6363
protected final BeaconStateMutators beaconStateMutators;
6464

6565
private static final Logger LOG = LogManager.getLogger();
66+
protected final UInt64 maxEffectiveBalance;
6667
// Used to log once per epoch (throttlingPeriod = 1)
6768
private final Throttler<Logger> loggerThrottler = new Throttler<>(LOG, UInt64.ONE);
6869

@@ -83,6 +84,7 @@ protected AbstractEpochProcessor(
8384
this.beaconStateUtil = beaconStateUtil;
8485
this.validatorStatusFactory = validatorStatusFactory;
8586
this.schemaDefinitions = schemaDefinitions;
87+
this.maxEffectiveBalance = specConfig.getMaxEffectiveBalance();
8688
}
8789

8890
/**
@@ -310,20 +312,14 @@ public void processRegistryUpdates(
310312
SszMutableList<Validator> validators = state.getValidators();
311313
final UInt64 currentEpoch = beaconStateAccessors.getCurrentEpoch(state);
312314
final UInt64 finalizedEpoch = state.getFinalizedCheckpoint().getEpoch();
313-
final UInt64 maxEffectiveBalance = specConfig.getMaxEffectiveBalance();
314315
final UInt64 ejectionBalance = specConfig.getEjectionBalance();
315316
final Supplier<ValidatorExitContext> validatorExitContextSupplier =
316317
beaconStateMutators.createValidatorExitContextSupplier(state);
317318

318319
for (int index = 0; index < validators.size(); index++) {
319320
final ValidatorStatus status = statuses.get(index);
320321

321-
// Slightly optimised form of isEligibleForActivationQueue to avoid accessing the
322-
// state for the majority of validators. Can't be eligible for activation if already active
323-
// or if effective balance is too low. Only get the validator if both those checks pass to
324-
// confirm it isn't already in the queue.
325-
if (!status.isActiveInCurrentEpoch()
326-
&& status.getCurrentEpochEffectiveBalance().equals(maxEffectiveBalance)) {
322+
if (isEligibleForActivationQueue(status)) {
327323
final Validator validator = validators.get(index);
328324
if (validator.getActivationEligibilityEpoch().equals(SpecConfig.FAR_FUTURE_EPOCH)) {
329325
validators.set(
@@ -381,6 +377,17 @@ public void processRegistryUpdates(
381377
}
382378
}
383379

380+
/**
381+
* Can't be eligible for activation if already active or if effective balance is too low.
382+
*
383+
* @param status - Validator status
384+
* @return true if validator is eligible to be added to the activation queue
385+
*/
386+
protected boolean isEligibleForActivationQueue(final ValidatorStatus status) {
387+
return !status.isActiveInCurrentEpoch()
388+
&& status.getCurrentEpochEffectiveBalance().equals(maxEffectiveBalance);
389+
}
390+
384391
/** Processes slashings */
385392
@Override
386393
public void processSlashings(

Diff for: ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/SpecLogicElectra.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@
2828
import tech.pegasys.teku.spec.logic.common.util.LightClientUtil;
2929
import tech.pegasys.teku.spec.logic.common.util.SyncCommitteeUtil;
3030
import tech.pegasys.teku.spec.logic.common.util.ValidatorsUtil;
31-
import tech.pegasys.teku.spec.logic.versions.altair.helpers.BeaconStateAccessorsAltair;
3231
import tech.pegasys.teku.spec.logic.versions.altair.statetransition.epoch.ValidatorStatusFactoryAltair;
3332
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BeaconStateMutatorsBellatrix;
3433
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BellatrixTransitionHelpers;
3534
import tech.pegasys.teku.spec.logic.versions.bellatrix.util.BlindBlockUtilBellatrix;
3635
import tech.pegasys.teku.spec.logic.versions.capella.block.BlockProcessorCapella;
3736
import tech.pegasys.teku.spec.logic.versions.capella.operations.validation.OperationValidatorCapella;
38-
import tech.pegasys.teku.spec.logic.versions.capella.statetransition.epoch.EpochProcessorCapella;
39-
import tech.pegasys.teku.spec.logic.versions.deneb.helpers.BeaconStateAccessorsDeneb;
4037
import tech.pegasys.teku.spec.logic.versions.deneb.helpers.MiscHelpersDeneb;
4138
import tech.pegasys.teku.spec.logic.versions.deneb.operations.validation.AttestationDataValidatorDeneb;
4239
import tech.pegasys.teku.spec.logic.versions.deneb.util.AttestationUtilDeneb;
4340
import tech.pegasys.teku.spec.logic.versions.deneb.util.ForkChoiceUtilDeneb;
4441
import tech.pegasys.teku.spec.logic.versions.electra.block.BlockProcessorElectra;
4542
import tech.pegasys.teku.spec.logic.versions.electra.forktransition.ElectraStateUpgrade;
43+
import tech.pegasys.teku.spec.logic.versions.electra.helpers.BeaconStateAccessorsElectra;
4644
import tech.pegasys.teku.spec.logic.versions.electra.helpers.MiscHelpersElectra;
45+
import tech.pegasys.teku.spec.logic.versions.electra.helpers.PredicatesElectra;
46+
import tech.pegasys.teku.spec.logic.versions.electra.statetransition.epoch.EpochProcessorElectra;
4747
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra;
4848

4949
public class SpecLogicElectra extends AbstractSpecLogic {
@@ -53,15 +53,15 @@ public class SpecLogicElectra extends AbstractSpecLogic {
5353
private SpecLogicElectra(
5454
final Predicates predicates,
5555
final MiscHelpersDeneb miscHelpers,
56-
final BeaconStateAccessorsAltair beaconStateAccessors,
56+
final BeaconStateAccessorsElectra beaconStateAccessors,
5757
final BeaconStateMutatorsBellatrix beaconStateMutators,
5858
final OperationSignatureVerifier operationSignatureVerifier,
5959
final ValidatorsUtil validatorsUtil,
6060
final BeaconStateUtil beaconStateUtil,
6161
final AttestationUtil attestationUtil,
6262
final OperationValidator operationValidator,
6363
final ValidatorStatusFactoryAltair validatorStatusFactory,
64-
final EpochProcessorCapella epochProcessor,
64+
final EpochProcessorElectra epochProcessor,
6565
final BlockProcessorCapella blockProcessor,
6666
final ForkChoiceUtil forkChoiceUtil,
6767
final BlockProposalUtil blockProposalUtil,
@@ -93,11 +93,11 @@ private SpecLogicElectra(
9393
public static SpecLogicElectra create(
9494
final SpecConfigElectra config, final SchemaDefinitionsElectra schemaDefinitions) {
9595
// Helpers
96-
final Predicates predicates = new Predicates(config);
96+
final PredicatesElectra predicates = new PredicatesElectra(config);
9797
final MiscHelpersElectra miscHelpers =
9898
new MiscHelpersElectra(config, predicates, schemaDefinitions);
99-
final BeaconStateAccessorsDeneb beaconStateAccessors =
100-
new BeaconStateAccessorsDeneb(config, predicates, miscHelpers);
99+
final BeaconStateAccessorsElectra beaconStateAccessors =
100+
new BeaconStateAccessorsElectra(config, predicates, miscHelpers);
101101
final BeaconStateMutatorsBellatrix beaconStateMutators =
102102
new BeaconStateMutatorsBellatrix(config, miscHelpers, beaconStateAccessors);
103103

@@ -126,8 +126,8 @@ public static SpecLogicElectra create(
126126
predicates,
127127
miscHelpers,
128128
beaconStateAccessors);
129-
final EpochProcessorCapella epochProcessor =
130-
new EpochProcessorCapella(
129+
final EpochProcessorElectra epochProcessor =
130+
new EpochProcessorElectra(
131131
config,
132132
miscHelpers,
133133
beaconStateAccessors,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright Consensys Software Inc., 2024
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package tech.pegasys.teku.spec.logic.versions.electra.helpers;
15+
16+
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
17+
import tech.pegasys.teku.spec.config.SpecConfigDeneb;
18+
import tech.pegasys.teku.spec.datastructures.state.Validator;
19+
import tech.pegasys.teku.spec.logic.versions.deneb.helpers.BeaconStateAccessorsDeneb;
20+
import tech.pegasys.teku.spec.logic.versions.deneb.helpers.MiscHelpersDeneb;
21+
22+
public class BeaconStateAccessorsElectra extends BeaconStateAccessorsDeneb {
23+
24+
private final UInt64 maxEffectiveBalanceElectra;
25+
private final UInt64 minActivationBalance;
26+
27+
protected PredicatesElectra predicatesElectra;
28+
29+
public BeaconStateAccessorsElectra(
30+
final SpecConfigDeneb config,
31+
final PredicatesElectra predicatesElectra,
32+
final MiscHelpersDeneb miscHelpers) {
33+
super(config, predicatesElectra, miscHelpers);
34+
this.maxEffectiveBalanceElectra =
35+
config.toVersionElectra().orElseThrow().getMaxEffectiveBalanceElectra();
36+
this.minActivationBalance = config.toVersionElectra().orElseThrow().getMinActivationBalance();
37+
this.predicatesElectra = predicatesElectra;
38+
}
39+
40+
/**
41+
* implements get_validator_max_effective_balance state accessor
42+
*
43+
* @param validator - a validator from a state.
44+
* @return the max effective balance for the specified validator based on its withdrawal
45+
* credentials.
46+
*/
47+
public UInt64 getValidatorMaxEffectiveBalance(final Validator validator) {
48+
return predicatesElectra.hasCompoundingWithdrawalCredential(validator)
49+
? maxEffectiveBalanceElectra
50+
: minActivationBalance;
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright Consensys Software Inc., 2024
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package tech.pegasys.teku.spec.logic.versions.electra.helpers;
15+
16+
import static tech.pegasys.teku.spec.constants.WithdrawalPrefixes.COMPOUNDING_WITHDRAWAL_BYTE;
17+
18+
import org.apache.tuweni.bytes.Bytes32;
19+
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
20+
import tech.pegasys.teku.spec.config.SpecConfig;
21+
import tech.pegasys.teku.spec.config.SpecConfigElectra;
22+
import tech.pegasys.teku.spec.datastructures.state.Validator;
23+
import tech.pegasys.teku.spec.logic.common.helpers.Predicates;
24+
25+
public class PredicatesElectra extends Predicates {
26+
private final SpecConfigElectra specConfigElectra;
27+
28+
public PredicatesElectra(SpecConfig specConfig) {
29+
super(specConfig);
30+
this.specConfigElectra = SpecConfigElectra.required(specConfig);
31+
}
32+
33+
@Override
34+
public boolean isPartiallyWithdrawableValidator(final Validator validator, final UInt64 balance) {
35+
if (hasEth1WithdrawalCredential(validator)) {
36+
return isPartiallyWithdrawableValidatorEth1CredentialsChecked(validator, balance);
37+
}
38+
if (hasCompoundingWithdrawalCredential(validator)) {
39+
return isPartiallyWithdrawableValidatorCompoundingCredentialChecked(validator, balance);
40+
}
41+
42+
return false;
43+
}
44+
45+
private boolean isPartiallyWithdrawableValidatorCompoundingCredentialChecked(
46+
final Validator validator, final UInt64 balance) {
47+
final UInt64 maxEffectiveBalance = specConfigElectra.getMaxEffectiveBalanceElectra();
48+
final boolean hasMaxEffectiveBalance =
49+
validator.getEffectiveBalance().equals(maxEffectiveBalance);
50+
final boolean hasExcessBalance = balance.isGreaterThan(maxEffectiveBalance);
51+
52+
return hasMaxEffectiveBalance && hasExcessBalance;
53+
}
54+
55+
protected boolean hasCompoundingWithdrawalCredential(final Validator validator) {
56+
return isCompoundingWithdrawalCredential(validator.getWithdrawalCredentials());
57+
}
58+
59+
protected boolean isCompoundingWithdrawalCredential(final Bytes32 withdrawalCredentials) {
60+
return withdrawalCredentials.get(0) == COMPOUNDING_WITHDRAWAL_BYTE;
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright Consensys Software Inc., 2024
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package tech.pegasys.teku.spec.logic.versions.electra.statetransition.epoch;
15+
16+
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
17+
import tech.pegasys.teku.spec.config.SpecConfigBellatrix;
18+
import tech.pegasys.teku.spec.logic.common.helpers.BeaconStateMutators;
19+
import tech.pegasys.teku.spec.logic.common.statetransition.epoch.status.ValidatorStatus;
20+
import tech.pegasys.teku.spec.logic.common.statetransition.epoch.status.ValidatorStatusFactory;
21+
import tech.pegasys.teku.spec.logic.common.util.BeaconStateUtil;
22+
import tech.pegasys.teku.spec.logic.common.util.ValidatorsUtil;
23+
import tech.pegasys.teku.spec.logic.versions.altair.helpers.BeaconStateAccessorsAltair;
24+
import tech.pegasys.teku.spec.logic.versions.altair.helpers.MiscHelpersAltair;
25+
import tech.pegasys.teku.spec.logic.versions.bellatrix.statetransition.epoch.EpochProcessorBellatrix;
26+
import tech.pegasys.teku.spec.schemas.SchemaDefinitions;
27+
28+
public class EpochProcessorElectra extends EpochProcessorBellatrix {
29+
30+
private final UInt64 minActivationBalance;
31+
32+
public EpochProcessorElectra(
33+
final SpecConfigBellatrix specConfig,
34+
final MiscHelpersAltair miscHelpers,
35+
final BeaconStateAccessorsAltair beaconStateAccessors,
36+
final BeaconStateMutators beaconStateMutators,
37+
final ValidatorsUtil validatorsUtil,
38+
final BeaconStateUtil beaconStateUtil,
39+
final ValidatorStatusFactory validatorStatusFactory,
40+
final SchemaDefinitions schemaDefinitions) {
41+
super(
42+
specConfig,
43+
miscHelpers,
44+
beaconStateAccessors,
45+
beaconStateMutators,
46+
validatorsUtil,
47+
beaconStateUtil,
48+
validatorStatusFactory,
49+
schemaDefinitions);
50+
this.minActivationBalance =
51+
specConfig.toVersionElectra().orElseThrow().getMinActivationBalance();
52+
}
53+
54+
@Override
55+
protected boolean isEligibleForActivationQueue(final ValidatorStatus status) {
56+
return !status.isActiveInCurrentEpoch()
57+
&& status.getCurrentEpochEffectiveBalance().isGreaterThanOrEqualTo(minActivationBalance);
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright Consensys Software Inc., 2024
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package tech.pegasys.teku.spec.logic.versions.electra.helpers;
15+
16+
import static org.assertj.core.api.Assertions.assertThat;
17+
18+
import org.junit.jupiter.api.Test;
19+
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
20+
import tech.pegasys.teku.spec.Spec;
21+
import tech.pegasys.teku.spec.TestSpecFactory;
22+
import tech.pegasys.teku.spec.datastructures.state.Validator;
23+
import tech.pegasys.teku.spec.util.DataStructureUtil;
24+
25+
class PredicatesElectraTest {
26+
private final Spec spec = TestSpecFactory.createMinimalElectra();
27+
private final DataStructureUtil dataStructureUtil = new DataStructureUtil(spec);
28+
private final PredicatesElectra predicates = new PredicatesElectra(spec.getGenesisSpecConfig());
29+
30+
private final UInt64 excessLargeValidatorBalance = UInt64.valueOf(2050_000_000_000L);
31+
32+
private final UInt64 maxEffectiveBalanceNonCompounding = UInt64.THIRTY_TWO_ETH;
33+
34+
private final UInt64 maxEffectiveBalanceCompounding = UInt64.valueOf(2048_000_000_000L);
35+
36+
@Test
37+
void isPartiallyWithdrawableValidator_shouldNotDetermineBlsWithdrawalAsNotWithdrawable() {
38+
final Validator validator =
39+
dataStructureUtil
40+
.validatorBuilder()
41+
.withdrawalCredentials(dataStructureUtil.randomBlsWithdrawalCredentials())
42+
.effectiveBalance(maxEffectiveBalanceNonCompounding)
43+
.build();
44+
assertThat(predicates.isPartiallyWithdrawableValidator(validator, excessLargeValidatorBalance))
45+
.isFalse();
46+
}
47+
48+
@Test
49+
void isPartiallyWithdrawableValidator_shouldDetermineEth1WithdrawalAsWithdrawable() {
50+
final Validator validator =
51+
dataStructureUtil
52+
.validatorBuilder()
53+
.withdrawalCredentials(dataStructureUtil.randomEth1WithdrawalCredentials())
54+
.effectiveBalance(maxEffectiveBalanceNonCompounding)
55+
.build();
56+
assertThat(predicates.isPartiallyWithdrawableValidator(validator, excessLargeValidatorBalance))
57+
.isTrue();
58+
}
59+
60+
@Test
61+
void isPartiallyWithdrawableValidator_shouldDetermineCompoundingWithdrawalAsWithdrawable() {
62+
final Validator validator =
63+
dataStructureUtil
64+
.validatorBuilder()
65+
.withdrawalCredentials(dataStructureUtil.randomCompoundingWithdrawalCredentials())
66+
.effectiveBalance(maxEffectiveBalanceCompounding)
67+
.build();
68+
assertThat(predicates.isPartiallyWithdrawableValidator(validator, excessLargeValidatorBalance))
69+
.isTrue();
70+
}
71+
72+
@Test
73+
void isPartiallyWithdrawableValidator_shouldDetermineCompoundingWithdrawalAsAsNotWithdrawable() {
74+
final Validator validator =
75+
dataStructureUtil
76+
.validatorBuilder()
77+
.withdrawalCredentials(dataStructureUtil.randomCompoundingWithdrawalCredentials())
78+
.effectiveBalance(maxEffectiveBalanceNonCompounding)
79+
.build();
80+
assertThat(
81+
predicates.isPartiallyWithdrawableValidator(
82+
validator, maxEffectiveBalanceNonCompounding))
83+
.isFalse();
84+
}
85+
}

0 commit comments

Comments
 (0)