Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove equivocating indices from score consideration #5397

Merged
merged 28 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3c9ddd3
Add equivocating validator indices
zilm13 Apr 27, 2022
f9bc84c
Merge branch 'master' into equivocating-indices
zilm13 Apr 27, 2022
e3b848f
Fix spotless
zilm13 Apr 27, 2022
10405cd
Remove unused logic in AttesterSlashing handling
zilm13 Apr 28, 2022
737ac14
Copy equivocatingIndices set as it could change during usage
zilm13 Apr 28, 2022
968edb3
Add AttesterSlashings to equivocating indices from imported blocks
zilm13 Apr 28, 2022
47fc31d
Disable equivocating validator scores using only votes
zilm13 Apr 29, 2022
913f7ae
Merge branch 'master' into equivocating-indices
zilm13 Apr 29, 2022
2a9b23b
Add votes serialize/deserialize test for V2
zilm13 Apr 29, 2022
a4c3c31
Fix style
zilm13 Apr 29, 2022
1e585c7
Add equivocation test path in VotesTest
zilm13 Apr 29, 2022
6048165
Apply equivocation validators infor from block before votes
zilm13 Apr 29, 2022
76a2cb1
Apply equivocation validators info from block before votes
zilm13 Apr 29, 2022
703feef
Merge branch 'equivocating-indices' of github.com:zilm13/teku into eq…
zilm13 Apr 29, 2022
bc80f38
Rename equivocating vote flags
zilm13 Apr 29, 2022
5af2536
Add ForkChoiceTest with equivocating AttesterSlashings in block
zilm13 Apr 30, 2022
1949178
Access AttestationUtil in more convenient style
zilm13 May 3, 2022
e236bb0
Access AttesterSlashings from block with better style
zilm13 May 3, 2022
d376a96
Create VoteTracker with better style
zilm13 May 3, 2022
b45c2b0
Create VoteTracker with one constructor, no matter whether equivocati…
zilm13 May 3, 2022
92f7be9
Refactor equivocating VoteTracker, removed versions, use different se…
zilm13 May 9, 2022
803e736
Merge branch 'master' into equivocating-indices
zilm13 May 9, 2022
48ba057
Initialize ForkChoice with equivocatingIndicesEnabled flag for more f…
zilm13 May 9, 2022
bd12159
Update validator record in ProtoArray for equivocating validator too
zilm13 May 10, 2022
098d0e1
Merge branch 'master' into equivocating-indices
zilm13 May 10, 2022
de6f976
Merge branch 'master' into equivocating-indices
zilm13 May 12, 2022
c286b00
Move whether to store equivocation in votes to StorageConfiguration
zilm13 May 12, 2022
2a7d92f
Merge branch 'master' into equivocating-indices
ajsutton May 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Warmup;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.TestSpecFactory;
import tech.pegasys.teku.spec.datastructures.forkchoice.VoteTracker;
import tech.pegasys.teku.spec.util.DataStructureUtil;
import tech.pegasys.teku.storage.server.kvstore.serialization.KvStoreSerializer;

public class VoteTrackerSerialize {

private static VoteTracker votes =
new DataStructureUtil(TestSpecFactory.createDefault()).randomVoteTracker();
private static KvStoreSerializer<VoteTracker> serializer = KvStoreSerializer.VOTES_SERIALIZER;
private static Spec spec = TestSpecFactory.createDefault();
private static VoteTracker votes = new DataStructureUtil(spec).randomVoteTracker();
private static KvStoreSerializer<VoteTracker> serializer =
KvStoreSerializer.createVoteTrackerSerializer(false);
private static Bytes votesSerialized = Bytes.wrap(serializer.serialize(votes));

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package tech.pegasys.teku.reference.phase0.forkchoice;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static tech.pegasys.teku.infrastructure.time.TimeUtilities.secondsToMillis;

import com.google.common.collect.ImmutableMap;
Expand Down Expand Up @@ -43,6 +44,7 @@
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState;
import tech.pegasys.teku.spec.datastructures.execution.PowBlock;
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing;
import tech.pegasys.teku.spec.datastructures.state.AnchorPoint;
import tech.pegasys.teku.spec.datastructures.state.Checkpoint;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;
Expand All @@ -52,6 +54,7 @@
import tech.pegasys.teku.statetransition.forkchoice.ForkChoice;
import tech.pegasys.teku.statetransition.forkchoice.MergeTransitionBlockValidator;
import tech.pegasys.teku.statetransition.forkchoice.StubForkChoiceNotifier;
import tech.pegasys.teku.statetransition.validation.InternalValidationResult;
import tech.pegasys.teku.storage.client.RecentChainData;
import tech.pegasys.teku.storage.storageSystem.InMemoryStorageSystemBuilder;
import tech.pegasys.teku.storage.storageSystem.StorageSystem;
Expand Down Expand Up @@ -106,6 +109,7 @@ spec, new SignedBlockAndState(anchorBlock, anchorState)),
recentChainData,
new StubForkChoiceNotifier(),
transitionBlockValidator,
true,
true);
final ExecutionLayerChannelStub executionLayer = new ExecutionLayerChannelStub(spec, false);

Expand Down Expand Up @@ -153,6 +157,9 @@ private void runSteps(
} else if (step.containsKey("pow_block")) {
applyPowBlock(testDefinition, step, executionLayer);

} else if (step.containsKey("attester_slashing")) {
applyAttesterSlashing(testDefinition, forkChoice, step);

} else {
throw new UnsupportedOperationException("Unsupported step: " + step);
}
Expand Down Expand Up @@ -202,6 +209,21 @@ private void applyAttestation(
.isCompleted();
}

private void applyAttesterSlashing(
final TestDefinition testDefinition,
final ForkChoice forkChoice,
final Map<String, Object> step) {
final String slashingName = get(step, "attester_slashing");
final AttesterSlashing attesterSlashing =
TestDataUtils.loadSsz(
testDefinition,
slashingName + ".ssz_snappy",
testDefinition.getSpec().getGenesisSchemaDefinitions().getAttesterSlashingSchema());
assertDoesNotThrow(
() ->
forkChoice.onAttesterSlashing(attesterSlashing, InternalValidationResult.ACCEPT, true));
}

private void applyBlock(
final TestDefinition testDefinition,
final Spec spec,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright 2022 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.core;

import static tech.pegasys.teku.infrastructure.async.SyncAsyncRunner.SYNC_RUNNER;

import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
import java.util.Optional;
import tech.pegasys.teku.bls.BLSKeyPair;
import tech.pegasys.teku.bls.BLSSignature;
import tech.pegasys.teku.core.signatures.LocalSigner;
import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState;
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
import tech.pegasys.teku.spec.datastructures.operations.Attestation.AttestationSchema;
import tech.pegasys.teku.spec.datastructures.operations.AttestationData;
import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing;
import tech.pegasys.teku.spec.datastructures.operations.IndexedAttestation;
import tech.pegasys.teku.spec.datastructures.state.Checkpoint;
import tech.pegasys.teku.spec.datastructures.state.Committee;
import tech.pegasys.teku.spec.datastructures.state.CommitteeAssignment;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;
import tech.pegasys.teku.spec.logic.common.util.AttestationUtil;
import tech.pegasys.teku.spec.util.DataStructureUtil;

public class AttesterSlashingGenerator {
private final Spec spec;
private final List<BLSKeyPair> validatorKeys;
private final DataStructureUtil dataStructureUtil;

public AttesterSlashingGenerator(final Spec spec, final List<BLSKeyPair> validatorKeys) {
this.spec = spec;
this.validatorKeys = validatorKeys;
this.dataStructureUtil = new DataStructureUtil(spec);
}

public AttesterSlashing createAttesterSlashingForAttestation(
final Attestation goodAttestation, final SignedBlockAndState blockAndState) {
if (!goodAttestation.getData().getSlot().equals(blockAndState.getSlot())) {
throw new RuntimeException("Good attestation slot and input block slot should match");
}
AttestationUtil attestationUtil = spec.atSlot(blockAndState.getSlot()).getAttestationUtil();
IndexedAttestation indexedGoodAttestation =
attestationUtil.getIndexedAttestation(blockAndState.getState(), goodAttestation);
int validatorIndex = indexedGoodAttestation.getAttestingIndices().get(0).get().intValue();

UInt64 epoch = spec.computeEpochAtSlot(blockAndState.getSlot());
Optional<CommitteeAssignment> maybeAssignment =
spec.getCommitteeAssignment(blockAndState.getState(), epoch, validatorIndex);
IntList committeeIndices = maybeAssignment.orElseThrow().getCommittee();
UInt64 committeeIndex = maybeAssignment.orElseThrow().getCommitteeIndex();
Committee committee = new Committee(committeeIndex, committeeIndices);
int indexIntoCommittee = committeeIndices.indexOf(validatorIndex);

AttestationData genericAttestationData =
spec.getGenericAttestationData(
blockAndState.getSlot(),
blockAndState.getState(),
blockAndState.getBlock(),
committeeIndex);
AttestationData brokenAttestationData =
new AttestationData(
genericAttestationData.getSlot(),
genericAttestationData.getIndex(),
genericAttestationData.getBeaconBlockRoot(),
genericAttestationData.getSource(),
new Checkpoint(
genericAttestationData.getTarget().getEpoch(), dataStructureUtil.randomBytes32()));
BLSKeyPair validatorKeyPair = validatorKeys.get(validatorIndex);
Attestation badAttestation =
createAttestation(
blockAndState.getState(),
validatorKeyPair,
indexIntoCommittee,
committee,
brokenAttestationData);
IndexedAttestation indexedBadAttestation =
attestationUtil.getIndexedAttestation(blockAndState.getState(), badAttestation);

return spec.getGenesisSchemaDefinitions()
.getAttesterSlashingSchema()
.create(indexedGoodAttestation, indexedBadAttestation);
}

private Attestation createAttestation(
final BeaconState state,
final BLSKeyPair attesterKeyPair,
final int indexIntoCommittee,
final Committee committee,
final AttestationData attestationData) {
int committeeSize = committee.getCommitteeSize();
AttestationSchema attestationSchema =
spec.atSlot(attestationData.getSlot()).getSchemaDefinitions().getAttestationSchema();
SszBitlist aggregationBitfield =
attestationSchema.getAggregationBitsSchema().ofBits(committeeSize, indexIntoCommittee);

BLSSignature signature =
new LocalSigner(spec, attesterKeyPair, SYNC_RUNNER)
.signAttestationData(attestationData, state.getForkInfo())
.join();
return attestationSchema.create(aggregationBitfield, attestationData, signature);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload;
import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSchema;
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing;
import tech.pegasys.teku.spec.datastructures.operations.Deposit;
import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing;
import tech.pegasys.teku.spec.datastructures.operations.SignedVoluntaryExit;
Expand Down Expand Up @@ -68,7 +69,8 @@ public SignedBlockAndState createNewBlock(
final Bytes32 parentBlockSigningRoot,
final Eth1Data eth1Data,
final SszList<Attestation> attestations,
final SszList<ProposerSlashing> slashings,
final SszList<ProposerSlashing> proposerSlashings,
final SszList<AttesterSlashing> attesterSlashings,
final SszList<Deposit> deposits,
final SszList<SignedVoluntaryExit> exits,
final Optional<List<Bytes>> transactions,
Expand All @@ -93,8 +95,8 @@ public SignedBlockAndState createNewBlock(
.eth1Data(eth1Data)
.graffiti(Bytes32.ZERO)
.attestations(attestations)
.proposerSlashings(slashings)
.attesterSlashings(blockBodyLists.createAttesterSlashings())
.proposerSlashings(proposerSlashings)
.attesterSlashings(attesterSlashings)
.deposits(deposits)
.voluntaryExits(exits)
.syncAggregate(
Expand Down Expand Up @@ -122,7 +124,8 @@ public SignedBlockAndState createNewBlockSkippingStateTransition(
final Bytes32 parentBlockSigningRoot,
final Eth1Data eth1Data,
final SszList<Attestation> attestations,
final SszList<ProposerSlashing> slashings,
final SszList<ProposerSlashing> proposerSlashings,
final SszList<AttesterSlashing> attesterSlashings,
final SszList<Deposit> deposits,
final SszList<SignedVoluntaryExit> exits,
final Optional<List<Bytes>> transactions,
Expand All @@ -149,8 +152,8 @@ public SignedBlockAndState createNewBlockSkippingStateTransition(
.eth1Data(eth1Data)
.graffiti(Bytes32.ZERO)
.attestations(attestations)
.proposerSlashings(slashings)
.attesterSlashings(blockBodyLists.createAttesterSlashings())
.proposerSlashings(proposerSlashings)
.attesterSlashings(attesterSlashings)
.deposits(deposits)
.voluntaryExits(exits)
.syncAggregate(
Expand Down Expand Up @@ -231,6 +234,7 @@ public SignedBlockAndState createBlock(
final Bytes32 parentBlockSigningRoot,
final Optional<SszList<Attestation>> attestations,
final Optional<SszList<Deposit>> deposits,
final Optional<SszList<AttesterSlashing>> attesterSlashings,
final Optional<SszList<SignedVoluntaryExit>> exits,
final Optional<Eth1Data> eth1Data,
final Optional<List<Bytes>> transactions,
Expand All @@ -248,6 +252,7 @@ public SignedBlockAndState createBlock(
eth1Data.orElse(getEth1DataStub(previousState, newEpoch)),
attestations.orElse(blockBodyLists.createAttestations()),
blockBodyLists.createProposerSlashings(),
attesterSlashings.orElse(blockBodyLists.createAttesterSlashings()),
deposits.orElse(blockBodyLists.createDeposits()),
exits.orElse(blockBodyLists.createVoluntaryExits()),
transactions,
Expand All @@ -262,6 +267,7 @@ public SignedBlockAndState createBlock(
eth1Data.orElse(getEth1DataStub(previousState, newEpoch)),
attestations.orElse(blockBodyLists.createAttestations()),
blockBodyLists.createProposerSlashings(),
attesterSlashings.orElse(blockBodyLists.createAttesterSlashings()),
deposits.orElse(blockBodyLists.createDeposits()),
exits.orElse(blockBodyLists.createVoluntaryExits()),
transactions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import tech.pegasys.teku.spec.datastructures.interop.MockStartDepositGenerator;
import tech.pegasys.teku.spec.datastructures.interop.MockStartValidatorKeyPairFactory;
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing;
import tech.pegasys.teku.spec.datastructures.operations.DepositData;
import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncAggregatorSelectionData;
import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncCommitteeMessage;
Expand All @@ -75,6 +76,7 @@ public class ChainBuilder {
private final Spec spec;
private final List<BLSKeyPair> validatorKeys;
private final AttestationGenerator attestationGenerator;
private final AttesterSlashingGenerator attesterSlashingGenerator;
private final NavigableMap<UInt64, SignedBlockAndState> blocks = new TreeMap<>();
private final Map<Bytes32, SignedBlockAndState> blocksByHash = new HashMap<>();

Expand All @@ -88,6 +90,7 @@ private ChainBuilder(
this.validatorKeys = validatorKeys;

attestationGenerator = new AttestationGenerator(spec, validatorKeys);
attesterSlashingGenerator = new AttesterSlashingGenerator(spec, validatorKeys);
blockProposalTestUtil = new BlockProposalTestUtil(spec);
blocks.putAll(existingBlocks);
existingBlocks.values().forEach(b -> blocksByHash.put(b.getRoot(), b));
Expand Down Expand Up @@ -370,6 +373,12 @@ public Stream<Attestation> streamValidAttestationsWithTargetBlock(
return attestationGenerator.streamAttestations(attestedHead, attestedHead.getSlot());
}

public AttesterSlashing createAttesterSlashingForAttestation(
final Attestation attestation, final SignedBlockAndState blockAndState) {
return attesterSlashingGenerator.createAttesterSlashingForAttestation(
attestation, blockAndState);
}

private void assertChainIsNotEmpty() {
checkState(!blocks.isEmpty(), "Unable to execute operation on empty chain");
}
Expand Down Expand Up @@ -398,6 +407,10 @@ private SignedBlockAndState appendNewBlockToChain(final UInt64 slot, final Block
SszList<Attestation> attestations =
BeaconBlockBodyLists.ofSpec(spec)
.createAttestations(options.getAttestations().toArray(new Attestation[0]));
SszList<AttesterSlashing> attesterSlashings =
BeaconBlockBodyLists.ofSpec(spec)
.createAttesterSlashings(
options.getAttesterSlashings().toArray(new AttesterSlashing[0]));
nextBlockAndState =
blockProposalTestUtil.createBlock(
signer,
Expand All @@ -406,6 +419,7 @@ private SignedBlockAndState appendNewBlockToChain(final UInt64 slot, final Block
parentRoot,
Optional.of(attestations),
Optional.empty(),
Optional.of(attesterSlashings),
Optional.empty(),
options.getEth1Data(),
options.getTransactions(),
Expand Down Expand Up @@ -529,6 +543,7 @@ public Signer getSigner(final int validatorId) {
public static final class BlockOptions {

private final List<Attestation> attestations = new ArrayList<>();
private final List<AttesterSlashing> attesterSlashings = new ArrayList<>();
private Optional<Eth1Data> eth1Data = Optional.empty();
private Optional<List<Bytes>> transactions = Optional.empty();
private Optional<Bytes32> terminalBlockHash = Optional.empty();
Expand All @@ -547,6 +562,11 @@ public BlockOptions addAttestation(final Attestation attestation) {
return this;
}

public BlockOptions addAttesterSlashing(final AttesterSlashing attesterSlashing) {
attesterSlashings.add(attesterSlashing);
return this;
}

public BlockOptions setEth1Data(final Eth1Data eth1Data) {
this.eth1Data = Optional.ofNullable(eth1Data);
return this;
Expand Down Expand Up @@ -604,5 +624,9 @@ public boolean getSkipStateTransition() {
public boolean getWrongProposer() {
return wrongProposer;
}

public List<AttesterSlashing> getAttesterSlashings() {
return attesterSlashings;
}
}
}
Loading