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

fix: cache attester index during attestation validation #7260

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
@@ -1,5 +1,5 @@
import {BitArray} from "@chainsafe/ssz";
import {CommitteeIndex, RootHex, Slot, phase0} from "@lodestar/types";
import {CommitteeIndex, RootHex, Slot, ValidatorIndex, phase0} from "@lodestar/types";
import {MapDef} from "@lodestar/utils";
import {Metrics} from "../../metrics/metrics.js";
import {InsertOutcome} from "../opPools/types.js";
Expand All @@ -11,8 +11,8 @@ type AttDataBase64 = string;
export type AttestationDataCacheEntry = {
// part of shuffling data, so this does not take memory
committeeValidatorIndices: Uint32Array;
// TODO: remove this? this is available in SingleAttestation
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@twoeths I am not sure about this comment, seems simpler to keep the committee index in the cache as if in case of loading the attestation from cache we won't deserialize the SingleAttestation to get the committe index from there, and for pre-electra we would still need it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes let's keep it in the cache and remove "TODO"

committeeIndex: CommitteeIndex;
attesterIndex: ValidatorIndex;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not correct to have attesterIndex here, this is the common cache for the whole committee while this is specific information of a validator

should also remove aggregationBits below as it's specific to the validator

// IndexedAttestationData signing root, 32 bytes
signingRoot: Uint8Array;
// to be consumed by forkchoice and oppool
Expand Down
18 changes: 14 additions & 4 deletions packages/beacon-node/src/chain/validation/attestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,10 +407,16 @@ async function validateAttestationNoSignatureCheck(
if (!isForkPostElectra(fork)) {
// The validity of aggregation bits are already checked above
assert.notNull(aggregationBits);
const bitIndex = aggregationBits.getSingleTrueBit();
assert.notNull(bitIndex);

validatorIndex = committeeValidatorIndices[bitIndex];
if (attestationOrCache.attestation) {
const bitIndex = aggregationBits.getSingleTrueBit();
assert.notNull(bitIndex);

validatorIndex = committeeValidatorIndices[bitIndex];
} else {
validatorIndex = attestationOrCache.cache.attesterIndex;
}

// [REJECT] The number of aggregation bits matches the committee size
// -- i.e. len(attestation.aggregation_bits) == len(get_beacon_committee(state, data.slot, data.index)).
// > TODO: Is this necessary? Lighthouse does not do this check.
Expand All @@ -420,7 +426,10 @@ async function validateAttestationNoSignatureCheck(
});
}
} else {
validatorIndex = (attestationOrCache.attestation as SingleAttestation<ForkPostElectra>).attesterIndex;
validatorIndex = attestationOrCache.attestation
? (attestationOrCache.attestation as SingleAttestation<ForkPostElectra>).attesterIndex
: attestationOrCache.cache.attesterIndex;

// [REJECT] The attester is a member of the committee -- i.e.
// `attestation.attester_index in get_beacon_committee(state, attestation.data.slot, index)`.
// If `aggregationBitsElectra` exists, that means we have already cached it. No need to check again
Expand Down Expand Up @@ -498,6 +507,7 @@ async function validateAttestationNoSignatureCheck(
chain.seenAttestationDatas.add(attSlot, committeeIndex, attDataKey, {
committeeValidatorIndices,
committeeIndex,
attesterIndex: validatorIndex,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could consider renaming validatorIndex to attesterIndex (or vice versa)

signingRoot: signatureSet.signingRoot,
subnet: expectedSubnet,
// precompute this to be used in forkchoice
Expand Down
Loading