From d2547c56993a8fca4ec9ef7c24f7f320f2fe452d Mon Sep 17 00:00:00 2001 From: Paul Harris Date: Tue, 9 Jul 2024 16:14:13 +1000 Subject: [PATCH] updated proposer logic for maxEB (#8343) * updated proposer logic for maxEB Added test to show that the consolidation factor affects the proposals in an epoch. Proposer index 3 went from 0 proposals in epoch 1 up to 4 proposals in epoch 1 after this change (consolidation of 16, so it has 16x32 eth) Signed-off-by: Paul Harris * review feedback Signed-off-by: Paul Harris * fixed conflicts Signed-off-by: Paul Harris * undo electra milestone Signed-off-by: Paul Harris --------- Signed-off-by: Paul Harris --- .../logic/common/helpers/MiscHelpers.java | 6 +- .../helpers/MiscHelpersElectraTest.java | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java index 8ee882c205e..3ba1a0c6355 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java @@ -113,12 +113,12 @@ protected int computeProposerIndex( final int total = indices.size(); byte[] hash = null; while (true) { - int candidateIndex = indices.getInt(computeShuffledIndex(i % total, total, seed)); + final int candidateIndex = indices.getInt(computeShuffledIndex(i % total, total, seed)); if (i % 32 == 0) { hash = sha256.digest(seed, uint64ToBytes(Math.floorDiv(i, 32L))); } - int randomByte = UnsignedBytes.toInt(hash[i % 32]); - UInt64 validatorEffectiveBalance = + final int randomByte = UnsignedBytes.toInt(hash[i % 32]); + final UInt64 validatorEffectiveBalance = state.getValidators().get(candidateIndex).getEffectiveBalance(); if (validatorEffectiveBalance .times(MAX_RANDOM_BYTE) diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectraTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectraTest.java index 5549a68965e..9cd9376ecfc 100644 --- a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectraTest.java +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/helpers/MiscHelpersElectraTest.java @@ -17,14 +17,19 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static tech.pegasys.teku.spec.logic.common.helpers.MathHelpers.uint64ToBytes; +import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; +import tech.pegasys.teku.infrastructure.crypto.Hash; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.config.SpecConfigElectra; +import tech.pegasys.teku.spec.constants.Domain; import tech.pegasys.teku.spec.datastructures.state.BeaconStateTestBuilder; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.electra.BeaconStateElectra; @@ -36,6 +41,7 @@ public class MiscHelpersElectraTest { private final Spec spec = TestSpecFactory.createMinimalElectra(); + private static final int PROPOSER_INDEX = 3; private final Predicates predicates = new Predicates(spec.getGenesisSpecConfig()); private final SchemaDefinitionsElectra schemaDefinitionsElectra = SchemaDefinitionsElectra.required(spec.getGenesisSchemaDefinitions()); @@ -45,6 +51,13 @@ public class MiscHelpersElectraTest { predicates, schemaDefinitionsElectra); private final DataStructureUtil dataStructureUtil = new DataStructureUtil(spec); + final BeaconStateAccessorsElectra beaconStateAccessors = + new BeaconStateAccessorsElectra( + spec.getGenesisSpecConfig(), + new PredicatesElectra(spec.getGenesisSpecConfig()), + miscHelpersElectra); + + private final IntList validatorIndices = IntArrayList.of(1, 2, 3, 4, 5, 6, 7, 0); @Test public void isFormerDepositMechanismDisabled_returnsTrueIfDisabled() { @@ -100,4 +113,46 @@ public void computeProposerIndexShouldUseMaxEffectiveBalanceElectra() { verify(specConfigElectra).getMaxEffectiveBalanceElectra(); verify(specConfigElectra, never()).getMaxEffectiveBalance(); } + + @Test + void consolidatedValidatorsMoreLikelyToPropose() { + final int consolidationAmount = 16; + final BeaconState state = randomStateWithConsolidatedValidator(consolidationAmount); + int proposerIndexCount = 0; + for (int i = 1; i < 8; i++) { + final UInt64 slot = UInt64.valueOf(8 + i); + final Bytes32 seed = + Hash.sha256( + beaconStateAccessors.getSeed(state, UInt64.ONE, Domain.BEACON_PROPOSER), + uint64ToBytes(slot)); + + if (miscHelpersElectra.computeProposerIndex(state, validatorIndices, seed) + == PROPOSER_INDEX) { + proposerIndexCount++; + } + } + assertThat(proposerIndexCount).isEqualTo(4); + } + + private BeaconState randomStateWithConsolidatedValidator(final int consolidationAmount) { + final BeaconState preState = dataStructureUtil.randomBeaconState(8); + return BeaconStateElectra.required(preState) + .updated( + mutableState -> { + mutableState + .getValidators() + .set( + PROPOSER_INDEX, + dataStructureUtil + .validatorBuilder() + .withdrawalCredentials( + dataStructureUtil.randomCompoundingWithdrawalCredentials()) + .effectiveBalance(UInt64.THIRTY_TWO_ETH.times(consolidationAmount)) + .build()); + mutableState + .getBalances() + .set(3, SszUInt64.of(UInt64.THIRTY_TWO_ETH.times(consolidationAmount))); + mutableState.setSlot(UInt64.valueOf(8)); + }); + } }