@lodestar/beacon-node 1.26.0-dev.3dcd668ca9 → 1.26.0-dev.418e81ef2d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/lib/api/impl/beacon/blocks/index.js +1 -0
  2. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  3. package/lib/api/impl/beacon/pool/index.js +22 -12
  4. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  5. package/lib/api/impl/config/constants.d.ts +3 -0
  6. package/lib/api/impl/config/constants.js +4 -1
  7. package/lib/api/impl/config/constants.js.map +1 -1
  8. package/lib/chain/errors/attestationError.d.ts +7 -1
  9. package/lib/chain/errors/attestationError.js +4 -0
  10. package/lib/chain/errors/attestationError.js.map +1 -1
  11. package/lib/chain/opPools/attestationPool.d.ts +2 -2
  12. package/lib/chain/opPools/attestationPool.js +20 -14
  13. package/lib/chain/opPools/attestationPool.js.map +1 -1
  14. package/lib/chain/opPools/opPool.d.ts +3 -2
  15. package/lib/chain/opPools/opPool.js +8 -8
  16. package/lib/chain/opPools/opPool.js.map +1 -1
  17. package/lib/chain/seenCache/seenAttestationData.d.ts +15 -7
  18. package/lib/chain/seenCache/seenAttestationData.js +33 -14
  19. package/lib/chain/seenCache/seenAttestationData.js.map +1 -1
  20. package/lib/chain/validation/aggregateAndProof.js +3 -6
  21. package/lib/chain/validation/aggregateAndProof.js.map +1 -1
  22. package/lib/chain/validation/attestation.d.ts +18 -10
  23. package/lib/chain/validation/attestation.js +129 -81
  24. package/lib/chain/validation/attestation.js.map +1 -1
  25. package/lib/chain/validation/attesterSlashing.d.ts +4 -4
  26. package/lib/chain/validation/attesterSlashing.js +1 -2
  27. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  28. package/lib/chain/validation/blobSidecar.d.ts +2 -1
  29. package/lib/chain/validation/blobSidecar.js +8 -7
  30. package/lib/chain/validation/blobSidecar.js.map +1 -1
  31. package/lib/chain/validation/block.js +3 -2
  32. package/lib/chain/validation/block.js.map +1 -1
  33. package/lib/chain/validation/voluntaryExit.js +1 -1
  34. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  35. package/lib/db/buckets.d.ts +1 -1
  36. package/lib/db/buckets.js +1 -1
  37. package/lib/db/buckets.js.map +1 -1
  38. package/lib/db/repositories/attesterSlashing.d.ts +2 -2
  39. package/lib/db/repositories/attesterSlashing.js +8 -2
  40. package/lib/db/repositories/attesterSlashing.js.map +1 -1
  41. package/lib/execution/engine/interface.d.ts +3 -1
  42. package/lib/execution/engine/interface.js +4 -0
  43. package/lib/execution/engine/interface.js.map +1 -1
  44. package/lib/execution/engine/types.d.ts +2 -2
  45. package/lib/execution/engine/types.js +67 -15
  46. package/lib/execution/engine/types.js.map +1 -1
  47. package/lib/metrics/metrics/beacon.d.ts +1 -1
  48. package/lib/metrics/metrics/beacon.js +3 -3
  49. package/lib/metrics/metrics/beacon.js.map +1 -1
  50. package/lib/metrics/validatorMonitor.js +4 -0
  51. package/lib/metrics/validatorMonitor.js.map +1 -1
  52. package/lib/network/gossip/interface.d.ts +5 -5
  53. package/lib/network/gossip/interface.js.map +1 -1
  54. package/lib/network/gossip/topic.d.ts +962 -956
  55. package/lib/network/gossip/topic.js +22 -3
  56. package/lib/network/gossip/topic.js.map +1 -1
  57. package/lib/network/interface.d.ts +3 -3
  58. package/lib/network/network.d.ts +3 -3
  59. package/lib/network/network.js +4 -2
  60. package/lib/network/network.js.map +1 -1
  61. package/lib/network/processor/extractSlotRootFns.js +4 -4
  62. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  63. package/lib/network/processor/gossipHandlers.js +22 -12
  64. package/lib/network/processor/gossipHandlers.js.map +1 -1
  65. package/lib/network/processor/gossipQueues/index.js +2 -3
  66. package/lib/network/processor/gossipQueues/index.js.map +1 -1
  67. package/lib/network/processor/index.js +1 -1
  68. package/lib/network/processor/index.js.map +1 -1
  69. package/lib/network/processor/types.d.ts +2 -1
  70. package/lib/network/reqresp/ReqRespBeaconNode.js +20 -13
  71. package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
  72. package/lib/network/reqresp/beaconBlocksMaybeBlobsByRoot.js +2 -2
  73. package/lib/network/reqresp/beaconBlocksMaybeBlobsByRoot.js.map +1 -1
  74. package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts +2 -1
  75. package/lib/network/reqresp/handlers/beaconBlocksByRange.js +6 -5
  76. package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
  77. package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts +2 -1
  78. package/lib/network/reqresp/handlers/blobSidecarsByRange.js +6 -5
  79. package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
  80. package/lib/network/reqresp/handlers/index.js +2 -1
  81. package/lib/network/reqresp/handlers/index.js.map +1 -1
  82. package/lib/network/reqresp/protocols.d.ts +16 -15
  83. package/lib/network/reqresp/protocols.js +3 -3
  84. package/lib/network/reqresp/protocols.js.map +1 -1
  85. package/lib/network/reqresp/rateLimit.d.ts +3 -2
  86. package/lib/network/reqresp/rateLimit.js +14 -15
  87. package/lib/network/reqresp/rateLimit.js.map +1 -1
  88. package/lib/network/reqresp/types.d.ts +2 -2
  89. package/lib/network/reqresp/types.js +2 -2
  90. package/lib/network/reqresp/types.js.map +1 -1
  91. package/lib/sync/range/chain.js +8 -3
  92. package/lib/sync/range/chain.js.map +1 -1
  93. package/lib/util/sszBytes.d.ts +42 -7
  94. package/lib/util/sszBytes.js +110 -15
  95. package/lib/util/sszBytes.js.map +1 -1
  96. package/lib/util/types.d.ts +3 -2
  97. package/lib/util/types.js +1 -1
  98. package/lib/util/types.js.map +1 -1
  99. package/package.json +17 -17
@@ -9,6 +9,9 @@ export var RejectReason;
9
9
  // attestation data is already known
10
10
  RejectReason["already_known"] = "already_known";
11
11
  })(RejectReason || (RejectReason = {}));
12
+ // For pre-electra, there is no committeeIndex in SingleAttestation, so we hard code it to 0
13
+ // AttDataBase64 has committeeIndex instead
14
+ export const PRE_ELECTRA_SINGLE_ATTESTATION_COMMITTEE_INDEX = 0;
12
15
  /**
13
16
  * There are maximum 64 committees per slot, assuming 1 committee may have up to 3 different data due to some nodes
14
17
  * are not up to date, we can have up to 192 different attestation data per slot.
@@ -31,31 +34,42 @@ export class SeenAttestationDatas {
31
34
  this.metrics = metrics;
32
35
  this.cacheSlotDistance = cacheSlotDistance;
33
36
  this.maxCacheSizePerSlot = maxCacheSizePerSlot;
34
- this.cacheEntryByAttDataBase64BySlot = new MapDef(() => new Map());
37
+ this.cacheEntryByAttDataByIndexBySlot = new MapDef(() => new MapDef(() => new Map()));
35
38
  this.lowestPermissibleSlot = 0;
36
39
  metrics?.seenCache.attestationData.totalSlot.addCollect(() => this.onScrapeLodestarMetrics(metrics));
37
40
  }
38
- // TODO: Move InsertOutcome type definition to a common place
39
- add(slot, attDataKey, cacheEntry) {
41
+ /**
42
+ * Add an AttestationDataCacheEntry to the cache.
43
+ * - preElectra: add(slot, PRE_ELECTRA_SINGLE_ATTESTATION_COMMITTEE_INDEX, attDataBase64, cacheEntry)
44
+ * - electra: add(slot, committeeIndex, attDataBase64, cacheEntry)
45
+ */
46
+ add(slot, committeeIndex, attDataBase64, cacheEntry) {
40
47
  if (slot < this.lowestPermissibleSlot) {
41
48
  this.metrics?.seenCache.attestationData.reject.inc({ reason: RejectReason.too_old });
42
49
  return InsertOutcome.Old;
43
50
  }
44
- const cacheEntryByAttDataBase64 = this.cacheEntryByAttDataBase64BySlot.getOrDefault(slot);
45
- if (cacheEntryByAttDataBase64.has(attDataKey)) {
51
+ const cacheEntryByAttDataByIndex = this.cacheEntryByAttDataByIndexBySlot.getOrDefault(slot);
52
+ const cacheEntryByAttData = cacheEntryByAttDataByIndex.getOrDefault(committeeIndex);
53
+ if (cacheEntryByAttData.has(attDataBase64)) {
46
54
  this.metrics?.seenCache.attestationData.reject.inc({ reason: RejectReason.already_known });
47
55
  return InsertOutcome.AlreadyKnown;
48
56
  }
49
- if (cacheEntryByAttDataBase64.size >= this.maxCacheSizePerSlot) {
57
+ if (cacheEntryByAttData.size >= this.maxCacheSizePerSlot) {
50
58
  this.metrics?.seenCache.attestationData.reject.inc({ reason: RejectReason.reached_limit });
51
59
  return InsertOutcome.ReachLimit;
52
60
  }
53
- cacheEntryByAttDataBase64.set(attDataKey, cacheEntry);
61
+ cacheEntryByAttData.set(attDataBase64, cacheEntry);
54
62
  return InsertOutcome.NewData;
55
63
  }
56
- get(slot, attDataBase64) {
57
- const cacheEntryByAttDataBase64 = this.cacheEntryByAttDataBase64BySlot.get(slot);
58
- const cacheEntry = cacheEntryByAttDataBase64?.get(attDataBase64);
64
+ /**
65
+ * Get an AttestationDataCacheEntry from the cache.
66
+ * - preElectra: get(slot, PRE_ELECTRA_SINGLE_ATTESTATION_COMMITTEE_INDEX, attDataBase64)
67
+ * - electra: get(slot, committeeIndex, attDataBase64)
68
+ */
69
+ get(slot, committeeIndex, attDataBase64) {
70
+ const cacheEntryByAttDataByIndex = this.cacheEntryByAttDataByIndexBySlot.get(slot);
71
+ const cacheEntryByAttData = cacheEntryByAttDataByIndex?.get(committeeIndex);
72
+ const cacheEntry = cacheEntryByAttData?.get(attDataBase64);
59
73
  if (cacheEntry) {
60
74
  this.metrics?.seenCache.attestationData.hit.inc();
61
75
  }
@@ -66,18 +80,23 @@ export class SeenAttestationDatas {
66
80
  }
67
81
  onSlot(clockSlot) {
68
82
  this.lowestPermissibleSlot = Math.max(clockSlot - this.cacheSlotDistance, 0);
69
- for (const slot of this.cacheEntryByAttDataBase64BySlot.keys()) {
83
+ for (const slot of this.cacheEntryByAttDataByIndexBySlot.keys()) {
70
84
  if (slot < this.lowestPermissibleSlot) {
71
- this.cacheEntryByAttDataBase64BySlot.delete(slot);
85
+ this.cacheEntryByAttDataByIndexBySlot.delete(slot);
72
86
  }
73
87
  }
74
88
  }
75
89
  onScrapeLodestarMetrics(metrics) {
76
- metrics?.seenCache.attestationData.totalSlot.set(this.cacheEntryByAttDataBase64BySlot.size);
90
+ metrics?.seenCache.attestationData.totalSlot.set(this.cacheEntryByAttDataByIndexBySlot.size);
77
91
  // tracking number of attestation data at current slot may not be correct if scrape time is not at the end of slot
78
92
  // so we track it at the previous slot
79
93
  const previousSlot = this.lowestPermissibleSlot + this.cacheSlotDistance - 1;
80
- metrics?.seenCache.attestationData.countPerSlot.set(this.cacheEntryByAttDataBase64BySlot.get(previousSlot)?.size ?? 0);
94
+ const cacheEntryByAttDataByIndex = this.cacheEntryByAttDataByIndexBySlot.get(previousSlot);
95
+ let count = 0;
96
+ for (const cacheEntryByAttDataBase64 of cacheEntryByAttDataByIndex?.values() ?? []) {
97
+ count += cacheEntryByAttDataBase64.size;
98
+ }
99
+ metrics?.seenCache.attestationData.countPerSlot.set(count);
81
100
  }
82
101
  }
83
102
  //# sourceMappingURL=seenAttestationData.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"seenAttestationData.js","sourceRoot":"","sources":["../../../src/chain/seenCache/seenAttestationData.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"seenAttestationData.js","sourceRoot":"","sources":["../../../src/chain/seenCache/seenAttestationData.ts"],"names":[],"mappings":"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"}
@@ -33,8 +33,6 @@ async function validateAggregateAndProof(fork, chain, signedAggregateAndProof, s
33
33
  const { aggregationBits } = aggregate;
34
34
  const attData = aggregate.data;
35
35
  const attSlot = attData.slot;
36
- const seenAttDataKey = serializedData ? getSeenAttDataKeyFromSignedAggregateAndProof(fork, serializedData) : null;
37
- const cachedAttData = seenAttDataKey ? chain.seenAttestationDatas.get(attSlot, seenAttDataKey) : null;
38
36
  let attIndex;
39
37
  if (ForkSeq[fork] >= ForkSeq.electra) {
40
38
  attIndex = aggregate.committeeBits.getSingleTrueBit();
@@ -50,6 +48,8 @@ async function validateAggregateAndProof(fork, chain, signedAggregateAndProof, s
50
48
  else {
51
49
  attIndex = attData.index;
52
50
  }
51
+ const seenAttDataKey = serializedData ? getSeenAttDataKeyFromSignedAggregateAndProof(fork, serializedData) : null;
52
+ const cachedAttData = seenAttDataKey ? chain.seenAttestationDatas.get(attSlot, attIndex, seenAttDataKey) : null;
53
53
  const attEpoch = computeEpochAtSlot(attSlot);
54
54
  const attTarget = attData.target;
55
55
  const targetEpoch = attTarget.epoch;
@@ -109,14 +109,11 @@ async function validateAggregateAndProof(fork, chain, signedAggregateAndProof, s
109
109
  throw new AttestationError(GossipAction.REJECT, { code: AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS });
110
110
  }
111
111
  const attestingIndices = aggregate.aggregationBits.intersectValues(committeeIndices);
112
- const indexedAttestationContent = {
112
+ const indexedAttestation = {
113
113
  attestingIndices,
114
114
  data: attData,
115
115
  signature: aggregate.signature,
116
116
  };
117
- const indexedAttestation = ForkSeq[fork] >= ForkSeq.electra
118
- ? indexedAttestationContent
119
- : indexedAttestationContent;
120
117
  // TODO: Check this before regen
121
118
  // [REJECT] The attestation has participants -- that is,
122
119
  // len(get_attesting_indices(state, aggregate.data, aggregate.aggregation_bits)) >= 1.
@@ -1 +1 @@
1
- {"version":3,"file":"aggregateAndProof.js","sourceRoot":"","sources":["../../../src/chain/validation/aggregateAndProof.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"aggregateAndProof.js","sourceRoot":"","sources":["../../../src/chain/validation/aggregateAndProof.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { BeaconConfig } from "@lodestar/config";
2
2
  import { ProtoBlock } from "@lodestar/fork-choice";
3
- import { ForkName } from "@lodestar/params";
3
+ import { ForkName, ForkPostElectra, ForkPreElectra } from "@lodestar/params";
4
4
  import { EpochShuffling, SingleSignatureSet } from "@lodestar/state-transition";
5
- import { Attestation, CommitteeIndex, Epoch, IndexedAttestation, Root, RootHex, Slot, SubnetID, phase0 } from "@lodestar/types";
5
+ import { CommitteeIndex, Epoch, IndexedAttestation, Root, RootHex, SingleAttestation, Slot, SubnetID, ValidatorIndex, phase0 } from "@lodestar/types";
6
6
  import { Result } from "../../util/wrapError.js";
7
7
  import { IBeaconChain } from "../interface.js";
8
8
  import { RegenCaller } from "../regen/index.js";
@@ -12,16 +12,18 @@ export type BatchResult = {
12
12
  batchableBls: boolean;
13
13
  };
14
14
  export type AttestationValidationResult = {
15
- attestation: Attestation;
15
+ attestation: SingleAttestation;
16
16
  indexedAttestation: IndexedAttestation;
17
17
  subnet: SubnetID;
18
18
  attDataRootHex: RootHex;
19
19
  committeeIndex: CommitteeIndex;
20
+ committeeValidatorIndex: number;
21
+ committeeSize: number;
20
22
  };
21
23
  export type AttestationOrBytes = ApiAttestation | GossipAttestation;
22
24
  /** attestation from api */
23
25
  export type ApiAttestation = {
24
- attestation: Attestation;
26
+ attestation: SingleAttestation;
25
27
  serializedData: null;
26
28
  };
27
29
  /** attestation from gossip */
@@ -50,7 +52,7 @@ export declare function validateGossipAttestationsSameAttData(fork: ForkName, ch
50
52
  */
51
53
  export declare function validateApiAttestation(fork: ForkName, chain: IBeaconChain, attestationOrBytes: ApiAttestation): Promise<AttestationValidationResult>;
52
54
  /**
53
- * Only deserialize the attestation if needed, use the cached AttestationData instead
55
+ * Only deserialize the single attestation if needed, use the cached AttestationData instead
54
56
  * This is to avoid deserializing similar attestation multiple times which could help the gc
55
57
  */
56
58
  declare function validateAttestationNoSignatureCheck(fork: ForkName, chain: IBeaconChain, attestationOrBytes: AttestationOrBytes,
@@ -98,15 +100,21 @@ export declare function getCommitteeIndices(shuffling: EpochShuffling, attestati
98
100
  export declare function computeSubnetForSlot(shuffling: EpochShuffling, slot: number, committeeIndex: number): SubnetID;
99
101
  /**
100
102
  * Return fork-dependent seen attestation key
101
- * - for pre-electra, it's the AttestationData base64
102
- * - for electra and later, it's the AttestationData base64 + committeeBits base64
103
+ * - for pre-electra, it's the AttestationData base64 from Attestation
104
+ * - for electra and later, it's the AttestationData base64 from SingleAttestation
105
+ * - consumers need to also pass slot + committeeIndex to get the correct SeenAttestationData
103
106
  */
104
- export declare function getSeenAttDataKeyFromGossipAttestation(fork: ForkName, attestation: GossipAttestation): SeenAttDataKey | null;
107
+ export declare function getSeenAttDataKeyFromGossipAttestation(attestation: GossipAttestation): SeenAttDataKey | null;
105
108
  /**
106
109
  * Extract attestation data key from SignedAggregateAndProof Uint8Array to use cached data from SeenAttestationDatas
107
- * - for pre-electra, it's the AttestationData base64
108
- * - for electra and later, it's the AttestationData base64 + committeeBits base64
110
+ * - for both electra + pre-electra, it's the AttestationData base64
111
+ * - consumers need to also pass slot + committeeIndex to get the correct SeenAttestationData
109
112
  */
110
113
  export declare function getSeenAttDataKeyFromSignedAggregateAndProof(fork: ForkName, aggregateAndProof: Uint8Array): SeenAttDataKey | null;
114
+ export declare function getCommitteeIndexFromAttestationOrBytes(fork: ForkName, attestationOrBytes: AttestationOrBytes): CommitteeIndex | null;
115
+ /**
116
+ * Convert pre-electra single attestation (`phase0.Attestation`) to post-electra `SingleAttestation`
117
+ */
118
+ export declare function toElectraSingleAttestation(attestation: SingleAttestation<ForkPreElectra>, attesterIndex: ValidatorIndex): SingleAttestation<ForkPostElectra>;
111
119
  export {};
112
120
  //# sourceMappingURL=attestation.d.ts.map
@@ -1,14 +1,15 @@
1
- import { ATTESTATION_SUBNET_COUNT, DOMAIN_BEACON_ATTESTER, ForkSeq, SLOTS_PER_EPOCH, isForkPostElectra, } from "@lodestar/params";
1
+ import { ATTESTATION_SUBNET_COUNT, DOMAIN_BEACON_ATTESTER, ForkName, ForkSeq, SLOTS_PER_EPOCH, isForkPostElectra, } from "@lodestar/params";
2
2
  import { EpochCacheError, EpochCacheErrorCode, computeEpochAtSlot, computeSigningRoot, computeStartSlotAtEpoch, createSingleSignatureSetFromComponents, } from "@lodestar/state-transition";
3
- import { isElectraAttestation, ssz, } from "@lodestar/types";
4
- import { toRootHex } from "@lodestar/utils";
3
+ import { isElectraSingleAttestation, ssz, } from "@lodestar/types";
4
+ import { assert, toRootHex } from "@lodestar/utils";
5
5
  import { MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC } from "../../constants/index.js";
6
- import { sszDeserializeAttestation } from "../../network/gossip/topic.js";
6
+ import { sszDeserializeSingleAttestation } from "../../network/gossip/topic.js";
7
7
  import { getShufflingDependentRoot } from "../../util/dependentRoot.js";
8
- import { getAggregationBitsFromAttestationSerialized, getAttDataFromSignedAggregateAndProofElectra, getAttDataFromSignedAggregateAndProofPhase0, getCommitteeBitsFromAttestationSerialized, getCommitteeBitsFromSignedAggregateAndProofElectra, getSignatureFromAttestationSerialized, } from "../../util/sszBytes.js";
8
+ import { getAggregationBitsFromAttestationSerialized, getAttDataFromSignedAggregateAndProofElectra, getAttDataFromSignedAggregateAndProofPhase0, getAttesterIndexFromSingleAttestationSerialized, getCommitteeIndexFromSingleAttestationSerialized, getSignatureFromAttestationSerialized, getSignatureFromSingleAttestationSerialized, } from "../../util/sszBytes.js";
9
9
  import { wrapError } from "../../util/wrapError.js";
10
10
  import { AttestationError, AttestationErrorCode, GossipAction } from "../errors/index.js";
11
11
  import { RegenCaller } from "../regen/index.js";
12
+ import { PRE_ELECTRA_SINGLE_ATTESTATION_COMMITTEE_INDEX, } from "../seenCache/seenAttestationData.js";
12
13
  /**
13
14
  * Verify gossip attestations of the same attestation data. The main advantage is we can batch verify bls signatures
14
15
  * through verifySignatureSetsSameMessage bls api to improve performance.
@@ -127,7 +128,7 @@ export async function validateApiAttestation(fork, chain, attestationOrBytes) {
127
128
  }
128
129
  }
129
130
  /**
130
- * Only deserialize the attestation if needed, use the cached AttestationData instead
131
+ * Only deserialize the single attestation if needed, use the cached AttestationData instead
131
132
  * This is to avoid deserializing similar attestation multiple times which could help the gc
132
133
  */
133
134
  async function validateAttestationNoSignatureCheck(fork, chain, attestationOrBytes,
@@ -146,10 +147,13 @@ subnet) {
146
147
  if (attestationOrBytes.serializedData) {
147
148
  // gossip
148
149
  const attSlot = attestationOrBytes.attSlot;
149
- attDataKey = getSeenAttDataKeyFromGossipAttestation(fork, attestationOrBytes);
150
- const cachedAttData = attDataKey !== null ? chain.seenAttestationDatas.get(attSlot, attDataKey) : null;
150
+ attDataKey = getSeenAttDataKeyFromGossipAttestation(attestationOrBytes);
151
+ const committeeIndexForLookup = isForkPostElectra(fork)
152
+ ? (getCommitteeIndexFromAttestationOrBytes(fork, attestationOrBytes) ?? 0)
153
+ : PRE_ELECTRA_SINGLE_ATTESTATION_COMMITTEE_INDEX;
154
+ const cachedAttData = attDataKey !== null ? chain.seenAttestationDatas.get(attSlot, committeeIndexForLookup, attDataKey) : null;
151
155
  if (cachedAttData === null) {
152
- const attestation = sszDeserializeAttestation(fork, attestationOrBytes.serializedData);
156
+ const attestation = sszDeserializeSingleAttestation(fork, attestationOrBytes.serializedData);
153
157
  // only deserialize on the first AttestationData that's not cached
154
158
  attestationOrCache = { attestation, cache: null };
155
159
  }
@@ -171,19 +175,10 @@ subnet) {
171
175
  const targetEpoch = attTarget.epoch;
172
176
  let committeeIndex;
173
177
  if (attestationOrCache.attestation) {
174
- if (isElectraAttestation(attestationOrCache.attestation)) {
178
+ if (isElectraSingleAttestation(attestationOrCache.attestation)) {
175
179
  // api or first time validation of a gossip attestation
176
- const { committeeBits } = attestationOrCache.attestation;
177
- // throw in both in case of undefined and null
178
- if (committeeBits == null) {
179
- throw new AttestationError(GossipAction.REJECT, { code: AttestationErrorCode.INVALID_SERIALIZED_BYTES });
180
- }
181
- committeeIndex = committeeBits.getSingleTrueBit();
182
- // [REJECT] len(committee_indices) == 1, where committee_indices = get_committee_indices(aggregate)
183
- if (committeeIndex === null) {
184
- throw new AttestationError(GossipAction.REJECT, { code: AttestationErrorCode.NOT_EXACTLY_ONE_COMMITTEE_BIT_SET });
185
- }
186
- // [REJECT] aggregate.data.index == 0
180
+ committeeIndex = attestationOrCache.attestation.committeeIndex;
181
+ // [REJECT] attestation.data.index == 0
187
182
  if (attData.index !== 0) {
188
183
  throw new AttestationError(GossipAction.REJECT, { code: AttestationErrorCode.NON_ZERO_ATTESTATION_DATA_INDEX });
189
184
  }
@@ -210,22 +205,27 @@ subnet) {
210
205
  // (a client MAY queue future attestations for processing at the appropriate slot).
211
206
  verifyPropagationSlotRange(fork, chain, attestationOrCache.attestation.data.slot);
212
207
  }
213
- // [REJECT] The attestation is unaggregated -- that is, it has exactly one participating validator
214
- // (len([bit for bit in attestation.aggregation_bits if bit]) == 1, i.e. exactly 1 bit is set).
215
- // > TODO: Do this check **before** getting the target state but don't recompute zipIndexes
216
- const aggregationBits = attestationOrCache.attestation
217
- ? attestationOrCache.attestation.aggregationBits
218
- : getAggregationBitsFromAttestationSerialized(fork, attestationOrCache.serializedData);
219
- if (aggregationBits === null) {
220
- throw new AttestationError(GossipAction.REJECT, {
221
- code: AttestationErrorCode.INVALID_SERIALIZED_BYTES,
222
- });
223
- }
224
- const bitIndex = aggregationBits.getSingleTrueBit();
225
- if (bitIndex === null) {
226
- throw new AttestationError(GossipAction.REJECT, {
227
- code: AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET,
228
- });
208
+ let aggregationBits = null;
209
+ let committeeValidatorIndex = null;
210
+ if (!isForkPostElectra(fork)) {
211
+ // [REJECT] The attestation is unaggregated -- that is, it has exactly one participating validator
212
+ // (len([bit for bit in attestation.aggregation_bits if bit]) == 1, i.e. exactly 1 bit is set).
213
+ // > TODO: Do this check **before** getting the target state but don't recompute zipIndexes
214
+ aggregationBits = attestationOrCache.attestation
215
+ ? attestationOrCache.attestation.aggregationBits
216
+ : getAggregationBitsFromAttestationSerialized(attestationOrCache.serializedData);
217
+ if (aggregationBits === null) {
218
+ throw new AttestationError(GossipAction.REJECT, {
219
+ code: AttestationErrorCode.INVALID_SERIALIZED_BYTES,
220
+ });
221
+ }
222
+ const bitIndex = aggregationBits.getSingleTrueBit();
223
+ if (bitIndex === null) {
224
+ throw new AttestationError(GossipAction.REJECT, {
225
+ code: AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET,
226
+ });
227
+ }
228
+ committeeValidatorIndex = bitIndex;
229
229
  }
230
230
  let committeeValidatorIndices;
231
231
  let getSigningRoot;
@@ -259,14 +259,43 @@ subnet) {
259
259
  getSigningRoot = () => getAttestationDataSigningRoot(chain.config, attData);
260
260
  expectedSubnet = computeSubnetForSlot(shuffling, attSlot, committeeIndex);
261
261
  }
262
- const validatorIndex = committeeValidatorIndices[bitIndex];
263
- // [REJECT] The number of aggregation bits matches the committee size
264
- // -- i.e. len(attestation.aggregation_bits) == len(get_beacon_committee(state, data.slot, data.index)).
265
- // > TODO: Is this necessary? Lighthouse does not do this check.
266
- if (aggregationBits.bitLen !== committeeValidatorIndices.length) {
267
- throw new AttestationError(GossipAction.REJECT, {
268
- code: AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS,
269
- });
262
+ let validatorIndex;
263
+ if (!isForkPostElectra(fork)) {
264
+ // The validity of aggregation bits are already checked above
265
+ assert.notNull(aggregationBits);
266
+ assert.notNull(committeeValidatorIndex);
267
+ validatorIndex = committeeValidatorIndices[committeeValidatorIndex];
268
+ // [REJECT] The number of aggregation bits matches the committee size
269
+ // -- i.e. len(attestation.aggregation_bits) == len(get_beacon_committee(state, data.slot, data.index)).
270
+ // > TODO: Is this necessary? Lighthouse does not do this check.
271
+ if (aggregationBits.bitLen !== committeeValidatorIndices.length) {
272
+ throw new AttestationError(GossipAction.REJECT, {
273
+ code: AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS,
274
+ });
275
+ }
276
+ }
277
+ else {
278
+ if (attestationOrCache.attestation) {
279
+ validatorIndex = attestationOrCache.attestation.attesterIndex;
280
+ }
281
+ else {
282
+ const attesterIndex = getAttesterIndexFromSingleAttestationSerialized(attestationOrCache.serializedData);
283
+ if (attesterIndex === null) {
284
+ throw new AttestationError(GossipAction.REJECT, {
285
+ code: AttestationErrorCode.INVALID_SERIALIZED_BYTES,
286
+ });
287
+ }
288
+ validatorIndex = attesterIndex;
289
+ }
290
+ // [REJECT] The attester is a member of the committee -- i.e.
291
+ // `attestation.attester_index in get_beacon_committee(state, attestation.data.slot, index)`.
292
+ // Position of the validator in its committee
293
+ committeeValidatorIndex = committeeValidatorIndices.indexOf(validatorIndex);
294
+ if (committeeValidatorIndex === -1) {
295
+ throw new AttestationError(GossipAction.REJECT, {
296
+ code: AttestationErrorCode.ATTESTER_NOT_IN_COMMITTEE,
297
+ });
298
+ }
270
299
  }
271
300
  // LH > verify_middle_checks
272
301
  // Run the checks that apply to the indexed attestation before the signature is checked.
@@ -298,31 +327,26 @@ subnet) {
298
327
  let attDataRootHex;
299
328
  const signature = attestationOrCache.attestation
300
329
  ? attestationOrCache.attestation.signature
301
- : getSignatureFromAttestationSerialized(attestationOrCache.serializedData);
330
+ : !isForkPostElectra(fork)
331
+ ? getSignatureFromAttestationSerialized(attestationOrCache.serializedData)
332
+ : getSignatureFromSingleAttestationSerialized(attestationOrCache.serializedData);
302
333
  if (signature === null) {
303
334
  throw new AttestationError(GossipAction.REJECT, {
304
335
  code: AttestationErrorCode.INVALID_SERIALIZED_BYTES,
305
336
  });
306
337
  }
307
- let committeeBits = undefined;
308
338
  if (attestationOrCache.cache) {
309
339
  // there could be up to 6% of cpu time to compute signing root if we don't clone the signature set
310
340
  signatureSet = createSingleSignatureSetFromComponents(chain.index2pubkey[validatorIndex], attestationOrCache.cache.signingRoot, signature);
311
341
  attDataRootHex = attestationOrCache.cache.attDataRootHex;
312
- committeeBits = attestationOrCache.cache.committeeBits;
313
342
  }
314
343
  else {
315
344
  signatureSet = createSingleSignatureSetFromComponents(chain.index2pubkey[validatorIndex], getSigningRoot(), signature);
316
345
  // add cached attestation data before verifying signature
317
346
  attDataRootHex = toRootHex(ssz.phase0.AttestationData.hashTreeRoot(attData));
318
- // if attestation is phase0 the committeeBits is undefined anyway
319
- committeeBits = isElectraAttestation(attestationOrCache.attestation)
320
- ? attestationOrCache.attestation.committeeBits.clone()
321
- : undefined;
322
347
  if (attDataKey) {
323
- chain.seenAttestationDatas.add(attSlot, attDataKey, {
348
+ chain.seenAttestationDatas.add(attSlot, committeeIndex, attDataKey, {
324
349
  committeeValidatorIndices,
325
- committeeBits,
326
350
  committeeIndex,
327
351
  signingRoot: signatureSet.signingRoot,
328
352
  subnet: expectedSubnet,
@@ -334,20 +358,26 @@ subnet) {
334
358
  }
335
359
  }
336
360
  // no signature check, leave that for step1
337
- const indexedAttestationContent = {
361
+ const indexedAttestation = {
338
362
  attestingIndices,
339
363
  data: attData,
340
364
  signature,
341
365
  };
342
- const indexedAttestation = ForkSeq[fork] >= ForkSeq.electra
343
- ? indexedAttestationContent
344
- : indexedAttestationContent;
345
- const attestation = attestationOrCache.attestation ?? {
346
- aggregationBits,
347
- data: attData,
348
- committeeBits,
349
- signature,
350
- };
366
+ const attestation = attestationOrCache.attestation
367
+ ? attestationOrCache.attestation
368
+ : !isForkPostElectra(fork)
369
+ ? {
370
+ // Aggregation bits are already asserted above to not be null
371
+ aggregationBits: aggregationBits,
372
+ data: attData,
373
+ signature,
374
+ }
375
+ : {
376
+ committeeIndex,
377
+ attesterIndex: validatorIndex,
378
+ data: attData,
379
+ signature,
380
+ };
351
381
  return {
352
382
  attestation,
353
383
  indexedAttestation,
@@ -356,6 +386,8 @@ subnet) {
356
386
  signatureSet,
357
387
  validatorIndex,
358
388
  committeeIndex,
389
+ committeeValidatorIndex,
390
+ committeeSize: committeeValidatorIndices.length,
359
391
  };
360
392
  }
361
393
  /**
@@ -576,30 +608,46 @@ export function computeSubnetForSlot(shuffling, slot, committeeIndex) {
576
608
  }
577
609
  /**
578
610
  * Return fork-dependent seen attestation key
579
- * - for pre-electra, it's the AttestationData base64
580
- * - for electra and later, it's the AttestationData base64 + committeeBits base64
611
+ * - for pre-electra, it's the AttestationData base64 from Attestation
612
+ * - for electra and later, it's the AttestationData base64 from SingleAttestation
613
+ * - consumers need to also pass slot + committeeIndex to get the correct SeenAttestationData
581
614
  */
582
- export function getSeenAttDataKeyFromGossipAttestation(fork, attestation) {
583
- const { attDataBase64, serializedData } = attestation;
584
- if (isForkPostElectra(fork)) {
585
- const committeeBits = getCommitteeBitsFromAttestationSerialized(serializedData);
586
- return attDataBase64 && committeeBits ? attDataBase64 + committeeBits : null;
587
- }
588
- // pre-electra
589
- return attDataBase64;
615
+ export function getSeenAttDataKeyFromGossipAttestation(attestation) {
616
+ // SeenAttDataKey is the same as gossip index
617
+ return attestation.attDataBase64;
590
618
  }
591
619
  /**
592
620
  * Extract attestation data key from SignedAggregateAndProof Uint8Array to use cached data from SeenAttestationDatas
593
- * - for pre-electra, it's the AttestationData base64
594
- * - for electra and later, it's the AttestationData base64 + committeeBits base64
621
+ * - for both electra + pre-electra, it's the AttestationData base64
622
+ * - consumers need to also pass slot + committeeIndex to get the correct SeenAttestationData
595
623
  */
596
624
  export function getSeenAttDataKeyFromSignedAggregateAndProof(fork, aggregateAndProof) {
625
+ return isForkPostElectra(fork)
626
+ ? getAttDataFromSignedAggregateAndProofElectra(aggregateAndProof)
627
+ : getAttDataFromSignedAggregateAndProofPhase0(aggregateAndProof);
628
+ }
629
+ export function getCommitteeIndexFromAttestationOrBytes(fork, attestationOrBytes) {
630
+ const isGossipAttestation = attestationOrBytes.serializedData !== null;
597
631
  if (isForkPostElectra(fork)) {
598
- const attData = getAttDataFromSignedAggregateAndProofElectra(aggregateAndProof);
599
- const committeeBits = getCommitteeBitsFromSignedAggregateAndProofElectra(aggregateAndProof);
600
- return attData && committeeBits ? attData + committeeBits : null;
632
+ if (isGossipAttestation) {
633
+ return getCommitteeIndexFromSingleAttestationSerialized(ForkName.electra, attestationOrBytes.serializedData);
634
+ }
635
+ return attestationOrBytes.attestation.committeeIndex;
636
+ }
637
+ if (isGossipAttestation) {
638
+ return getCommitteeIndexFromSingleAttestationSerialized(ForkName.phase0, attestationOrBytes.serializedData);
601
639
  }
602
- // pre-electra
603
- return getAttDataFromSignedAggregateAndProofPhase0(aggregateAndProof);
640
+ return attestationOrBytes.attestation.data.index;
641
+ }
642
+ /**
643
+ * Convert pre-electra single attestation (`phase0.Attestation`) to post-electra `SingleAttestation`
644
+ */
645
+ export function toElectraSingleAttestation(attestation, attesterIndex) {
646
+ return {
647
+ committeeIndex: attestation.data.index,
648
+ attesterIndex,
649
+ data: attestation.data,
650
+ signature: attestation.signature,
651
+ };
604
652
  }
605
653
  //# sourceMappingURL=attestation.js.map