diff --git a/acceptance-tests/src/testFixtures/java/tech/pegasys/teku/test/acceptance/dsl/TekuBeaconNode.java b/acceptance-tests/src/testFixtures/java/tech/pegasys/teku/test/acceptance/dsl/TekuBeaconNode.java index 095fec6abad..41414e4466a 100644 --- a/acceptance-tests/src/testFixtures/java/tech/pegasys/teku/test/acceptance/dsl/TekuBeaconNode.java +++ b/acceptance-tests/src/testFixtures/java/tech/pegasys/teku/test/acceptance/dsl/TekuBeaconNode.java @@ -693,12 +693,7 @@ public void waitForAttestationBeingGossiped( Set attesterIndicesInAttestations = block.getMessage().getBody().attestations.stream() - .map( - a -> - spec.getAttestingIndices( - state, - a.asInternalAttestation(spec).getData(), - a.asInternalAttestation(spec).getAggregationBits())) + .map(a -> spec.getAttestingIndices(state, a.asInternalAttestation(spec))) .flatMap(Collection::stream) .map(UInt64::valueOf) .collect(toSet()); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java index 82e9e6cc73d..fe1d2288ff2 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java @@ -42,7 +42,6 @@ import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.infrastructure.ssz.Merkleizable; import tech.pegasys.teku.infrastructure.ssz.SszList; -import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.cache.IndexedAttestationCache; import tech.pegasys.teku.spec.config.NetworkingSpecConfig; @@ -868,8 +867,8 @@ public Map getValidatorIndexToCommitteeAssignmentM } // Attestation helpers - public IntList getAttestingIndices(BeaconState state, AttestationData data, SszBitlist bits) { - return atState(state).getAttestationUtil().getAttestingIndices(state, data, bits); + public IntList getAttestingIndices(final BeaconState state, final Attestation attestation) { + return atState(state).getAttestationUtil().getAttestingIndices(state, attestation); } public AttestationData getGenericAttestationData( diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/operations/Attestation.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/operations/Attestation.java index d6bf69e5c2d..f0ee74a4fdc 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/operations/Attestation.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/operations/Attestation.java @@ -28,8 +28,8 @@ import tech.pegasys.teku.spec.datastructures.type.SszSignature; import tech.pegasys.teku.spec.datastructures.type.SszSignatureSchema; -public class Attestation - extends Container3 { +public class Attestation extends Container3 + implements AttestationContainer { public static class AttestationSchema extends ContainerSchema3 { @@ -91,10 +91,12 @@ public Collection getDependentBlockRoots() { return Sets.newHashSet(getData().getTarget().getRoot(), getData().getBeaconBlockRoot()); } + @Override public SszBitlist getAggregationBits() { return getField0(); } + @Override public AttestationData getData() { return getField1(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/operations/AttestationContainer.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/operations/AttestationContainer.java new file mode 100644 index 00000000000..125bad285d6 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/operations/AttestationContainer.java @@ -0,0 +1,29 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * 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.spec.datastructures.operations; + +import tech.pegasys.teku.infrastructure.ssz.SszContainer; +import tech.pegasys.teku.infrastructure.ssz.SszData; +import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist; + +/** + * Interface used to represent different types of attestations ({@link Attestation} and {@link + * tech.pegasys.teku.spec.datastructures.state.PendingAttestation}) + */ +public interface AttestationContainer extends SszData, SszContainer { + + AttestationData getData(); + + SszBitlist getAggregationBits(); +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/state/PendingAttestation.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/state/PendingAttestation.java index 9a5c6b4c1aa..a293bf22bd3 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/state/PendingAttestation.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/state/PendingAttestation.java @@ -22,10 +22,12 @@ import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.config.SpecConfig; +import tech.pegasys.teku.spec.datastructures.operations.AttestationContainer; import tech.pegasys.teku.spec.datastructures.operations.AttestationData; public class PendingAttestation - extends Container4 { + extends Container4 + implements AttestationContainer { public static class PendingAttestationSchema extends ContainerSchema4< @@ -82,10 +84,12 @@ public PendingAttestationSchema getSchema() { return (PendingAttestationSchema) super.getSchema(); } + @Override public SszBitlist getAggregationBits() { return getField0(); } + @Override public AttestationData getData() { return getField1(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/util/AttestationUtil.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/util/AttestationUtil.java index 7e173b79102..39e1371b4b0 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/util/AttestationUtil.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/util/AttestationUtil.java @@ -38,6 +38,7 @@ import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation; import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockSummary; import tech.pegasys.teku.spec.datastructures.operations.Attestation; +import tech.pegasys.teku.spec.datastructures.operations.AttestationContainer; import tech.pegasys.teku.spec.datastructures.operations.AttestationData; import tech.pegasys.teku.spec.datastructures.operations.IndexedAttestation; import tech.pegasys.teku.spec.datastructures.operations.IndexedAttestation.IndexedAttestationSchema; @@ -98,8 +99,7 @@ public boolean isSlashableAttestationData( */ public IndexedAttestation getIndexedAttestation( final BeaconState state, final Attestation attestation) { - final List attestingIndices = - getAttestingIndices(state, attestation.getData(), attestation.getAggregationBits()); + final List attestingIndices = getAttestingIndices(state, attestation); final IndexedAttestationSchema indexedAttestationSchema = schemaDefinitions.getIndexedAttestationSchema(); @@ -116,28 +116,31 @@ public IndexedAttestation getIndexedAttestation( * Return the sorted attesting indices corresponding to ``data`` and ``bits``. * * @param state - * @param data - * @param bits + * @param attestation * @return * @throws IllegalArgumentException * @see - * https://github.com/ethereum/consensus-specs/blob/v0.8.0/specs/core/0_beacon-chain.md#get_attesting_indices + * https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#get_attesting_indices */ public IntList getAttestingIndices( - final BeaconState state, final AttestationData data, final SszBitlist bits) { - return IntList.of(streamAttestingIndices(state, data, bits).toArray()); + final BeaconState state, final AttestationContainer attestation) { + return IntList.of(streamAttestingIndices(state, attestation).toArray()); } public IntStream streamAttestingIndices( - final BeaconState state, final AttestationData data, final SszBitlist bits) { - IntList committee = + final BeaconState state, final AttestationContainer attestation) { + final AttestationData data = attestation.getData(); + final SszBitlist aggregationBits = attestation.getAggregationBits(); + final IntList committee = beaconStateAccessors.getBeaconCommittee(state, data.getSlot(), data.getIndex()); checkArgument( - bits.size() == committee.size(), + aggregationBits.size() == committee.size(), "Aggregation bitlist size (%s) does not match committee size (%s)", - bits.size(), + aggregationBits.size(), committee.size()); - return IntStream.range(0, committee.size()).filter(bits::getBit).map(committee::getInt); + return IntStream.range(0, committee.size()) + .filter(aggregationBits::getBit) + .map(committee::getInt); } public AttestationProcessingResult isValidIndexedAttestation( diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/altair/forktransition/AltairStateUpgrade.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/altair/forktransition/AltairStateUpgrade.java index 8e180c59e56..87d84395f8c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/altair/forktransition/AltairStateUpgrade.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/altair/forktransition/AltairStateUpgrade.java @@ -102,7 +102,7 @@ private void translateParticipation( // Apply flags to all attesting validators final SszMutableList epochParticipation = state.getPreviousEpochParticipation(); attestationUtil - .streamAttestingIndices(state, data, attestation.getAggregationBits()) + .streamAttestingIndices(state, attestation) .forEach( index -> { final byte previousFlags = epochParticipation.get(index).get(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/phase0/statetransition/epoch/ValidatorStatusFactoryPhase0.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/phase0/statetransition/epoch/ValidatorStatusFactoryPhase0.java index 84fd99c43b6..bc22f19b7ca 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/phase0/statetransition/epoch/ValidatorStatusFactoryPhase0.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/phase0/statetransition/epoch/ValidatorStatusFactoryPhase0.java @@ -96,7 +96,7 @@ protected void processParticipation( // Apply flags to attestingIndices attestationUtil - .streamAttestingIndices(state, data, attestation.getAggregationBits()) + .streamAttestingIndices(state, attestation) .mapToObj(statuses::get) .forEach(updates::apply); }); diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/AggregateAttestationValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/AggregateAttestationValidator.java index 8d623f9ad7c..282ac4474eb 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/AggregateAttestationValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/AggregateAttestationValidator.java @@ -142,9 +142,7 @@ private SafeFuture verifyAggregate( final BeaconState state = maybeState.get(); // [REJECT] The aggregate attestation has participants - final IntList attestingIndices = - spec.getAttestingIndices( - state, aggregate.getData(), aggregate.getAggregationBits()); + final IntList attestingIndices = spec.getAttestingIndices(state, aggregate); if (attestingIndices.isEmpty()) { return SafeFuture.completedFuture( reject(