@lodestar/beacon-node 1.41.0-dev.49f680d9f0 → 1.41.0-dev.4e115ed25d

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 (197) hide show
  1. package/lib/api/impl/beacon/state/index.js +8 -8
  2. package/lib/api/impl/beacon/state/index.js.map +1 -1
  3. package/lib/api/impl/beacon/state/utils.d.ts +3 -4
  4. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/state/utils.js +5 -24
  6. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  7. package/lib/api/impl/debug/index.d.ts.map +1 -1
  8. package/lib/api/impl/debug/index.js +1 -0
  9. package/lib/api/impl/debug/index.js.map +1 -1
  10. package/lib/api/impl/node/utils.d.ts +1 -1
  11. package/lib/api/impl/node/utils.d.ts.map +1 -1
  12. package/lib/api/impl/node/utils.js.map +1 -1
  13. package/lib/api/impl/validator/index.d.ts.map +1 -1
  14. package/lib/api/impl/validator/index.js +3 -5
  15. package/lib/api/impl/validator/index.js.map +1 -1
  16. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +5 -6
  17. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +9 -10
  19. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  20. package/lib/chain/archiveStore/historicalState/worker.js +3 -3
  21. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  22. package/lib/chain/blocks/blockInput/blockInput.d.ts +20 -2
  23. package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
  24. package/lib/chain/blocks/blockInput/blockInput.js +47 -0
  25. package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
  26. package/lib/chain/blocks/blockInput/types.d.ts +2 -1
  27. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  28. package/lib/chain/blocks/blockInput/types.js +1 -0
  29. package/lib/chain/blocks/blockInput/types.js.map +1 -1
  30. package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
  31. package/lib/chain/blocks/verifyBlocksDataAvailability.js +3 -0
  32. package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
  33. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +4 -0
  34. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  35. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -1
  36. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  37. package/lib/chain/bls/multithread/index.d.ts +3 -3
  38. package/lib/chain/bls/multithread/index.d.ts.map +1 -1
  39. package/lib/chain/bls/multithread/index.js +5 -5
  40. package/lib/chain/bls/multithread/index.js.map +1 -1
  41. package/lib/chain/bls/multithread/jobItem.d.ts +2 -2
  42. package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
  43. package/lib/chain/bls/multithread/jobItem.js +2 -2
  44. package/lib/chain/bls/multithread/jobItem.js.map +1 -1
  45. package/lib/chain/bls/singleThread.d.ts +4 -4
  46. package/lib/chain/bls/singleThread.d.ts.map +1 -1
  47. package/lib/chain/bls/singleThread.js +4 -4
  48. package/lib/chain/bls/singleThread.js.map +1 -1
  49. package/lib/chain/bls/utils.d.ts +2 -2
  50. package/lib/chain/bls/utils.d.ts.map +1 -1
  51. package/lib/chain/bls/utils.js +7 -4
  52. package/lib/chain/bls/utils.js.map +1 -1
  53. package/lib/chain/chain.d.ts +4 -7
  54. package/lib/chain/chain.d.ts.map +1 -1
  55. package/lib/chain/chain.js +8 -10
  56. package/lib/chain/chain.js.map +1 -1
  57. package/lib/chain/interface.d.ts +2 -4
  58. package/lib/chain/interface.d.ts.map +1 -1
  59. package/lib/chain/interface.js.map +1 -1
  60. package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
  61. package/lib/chain/seenCache/seenGossipBlockInput.js +15 -7
  62. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  63. package/lib/chain/validation/attestation.d.ts.map +1 -1
  64. package/lib/chain/validation/attestation.js +4 -1
  65. package/lib/chain/validation/attestation.js.map +1 -1
  66. package/lib/chain/validation/attesterSlashing.js +1 -1
  67. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  68. package/lib/chain/validation/payloadAttestationMessage.js +8 -1
  69. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  70. package/lib/chain/validation/proposerSlashing.js +1 -1
  71. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  72. package/lib/chain/validation/syncCommitteeContributionAndProof.js +1 -1
  73. package/lib/db/repositories/blockArchive.d.ts.map +1 -1
  74. package/lib/db/repositories/blockArchive.js +1 -2
  75. package/lib/db/repositories/blockArchive.js.map +1 -1
  76. package/lib/execution/engine/http.d.ts +1 -0
  77. package/lib/execution/engine/http.d.ts.map +1 -1
  78. package/lib/execution/engine/http.js +3 -0
  79. package/lib/execution/engine/http.js.map +1 -1
  80. package/lib/metrics/metrics/lodestar.d.ts +3 -0
  81. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  82. package/lib/metrics/metrics/lodestar.js +5 -0
  83. package/lib/metrics/metrics/lodestar.js.map +1 -1
  84. package/lib/monitoring/service.d.ts +2 -2
  85. package/lib/monitoring/service.d.ts.map +1 -1
  86. package/lib/monitoring/service.js +3 -2
  87. package/lib/monitoring/service.js.map +1 -1
  88. package/lib/network/core/networkCore.d.ts +3 -3
  89. package/lib/network/core/networkCore.d.ts.map +1 -1
  90. package/lib/network/core/networkCore.js.map +1 -1
  91. package/lib/network/core/networkCoreWorkerHandler.d.ts +3 -3
  92. package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
  93. package/lib/network/core/types.d.ts +2 -2
  94. package/lib/network/core/types.d.ts.map +1 -1
  95. package/lib/network/events.d.ts +2 -1
  96. package/lib/network/events.d.ts.map +1 -1
  97. package/lib/network/events.js.map +1 -1
  98. package/lib/network/gossip/encoding.d.ts +3 -3
  99. package/lib/network/gossip/encoding.d.ts.map +1 -1
  100. package/lib/network/gossip/encoding.js.map +1 -1
  101. package/lib/network/gossip/gossipsub.d.ts +13 -4
  102. package/lib/network/gossip/gossipsub.d.ts.map +1 -1
  103. package/lib/network/gossip/gossipsub.js +47 -20
  104. package/lib/network/gossip/gossipsub.js.map +1 -1
  105. package/lib/network/gossip/interface.d.ts +3 -3
  106. package/lib/network/gossip/interface.d.ts.map +1 -1
  107. package/lib/network/gossip/scoringParameters.d.ts +1 -1
  108. package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
  109. package/lib/network/gossip/scoringParameters.js +1 -1
  110. package/lib/network/gossip/scoringParameters.js.map +1 -1
  111. package/lib/network/interface.d.ts +3 -3
  112. package/lib/network/interface.d.ts.map +1 -1
  113. package/lib/network/libp2p/index.d.ts +1 -1
  114. package/lib/network/libp2p/index.d.ts.map +1 -1
  115. package/lib/network/libp2p/index.js +29 -9
  116. package/lib/network/libp2p/index.js.map +1 -1
  117. package/lib/network/network.d.ts +2 -2
  118. package/lib/network/network.d.ts.map +1 -1
  119. package/lib/network/network.js.map +1 -1
  120. package/lib/network/options.d.ts.map +1 -1
  121. package/lib/network/options.js +3 -0
  122. package/lib/network/options.js.map +1 -1
  123. package/lib/network/peers/datastore.d.ts +7 -5
  124. package/lib/network/peers/datastore.d.ts.map +1 -1
  125. package/lib/network/peers/datastore.js +10 -10
  126. package/lib/network/peers/datastore.js.map +1 -1
  127. package/lib/network/peers/peerManager.d.ts +3 -0
  128. package/lib/network/peers/peerManager.d.ts.map +1 -1
  129. package/lib/network/peers/peerManager.js +103 -53
  130. package/lib/network/peers/peerManager.js.map +1 -1
  131. package/lib/network/peers/utils/prioritizePeers.d.ts +3 -3
  132. package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
  133. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  134. package/lib/network/processor/gossipHandlers.js +3 -1
  135. package/lib/network/processor/gossipHandlers.js.map +1 -1
  136. package/lib/network/processor/gossipValidatorFn.js +1 -1
  137. package/lib/network/processor/types.d.ts +1 -1
  138. package/lib/network/processor/types.d.ts.map +1 -1
  139. package/lib/network/reqresp/score.d.ts.map +1 -1
  140. package/lib/network/reqresp/score.js +0 -1
  141. package/lib/network/reqresp/score.js.map +1 -1
  142. package/lib/network/util.js +2 -2
  143. package/lib/network/util.js.map +1 -1
  144. package/lib/node/nodejs.d.ts +3 -5
  145. package/lib/node/nodejs.d.ts.map +1 -1
  146. package/lib/node/nodejs.js +6 -4
  147. package/lib/node/nodejs.js.map +1 -1
  148. package/package.json +38 -41
  149. package/src/api/impl/beacon/state/index.ts +8 -8
  150. package/src/api/impl/beacon/state/utils.ts +15 -29
  151. package/src/api/impl/debug/index.ts +1 -0
  152. package/src/api/impl/node/utils.ts +3 -3
  153. package/src/api/impl/validator/index.ts +3 -4
  154. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +10 -11
  155. package/src/chain/archiveStore/historicalState/worker.ts +3 -3
  156. package/src/chain/blocks/blockInput/blockInput.ts +68 -3
  157. package/src/chain/blocks/blockInput/types.ts +1 -0
  158. package/src/chain/blocks/verifyBlocksDataAvailability.ts +3 -0
  159. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -2
  160. package/src/chain/bls/multithread/index.ts +7 -7
  161. package/src/chain/bls/multithread/jobItem.ts +3 -3
  162. package/src/chain/bls/singleThread.ts +5 -5
  163. package/src/chain/bls/utils.ts +8 -5
  164. package/src/chain/chain.ts +10 -15
  165. package/src/chain/interface.ts +2 -9
  166. package/src/chain/seenCache/seenGossipBlockInput.ts +16 -7
  167. package/src/chain/validation/attestation.ts +4 -1
  168. package/src/chain/validation/attesterSlashing.ts +1 -1
  169. package/src/chain/validation/payloadAttestationMessage.ts +9 -1
  170. package/src/chain/validation/proposerSlashing.ts +1 -1
  171. package/src/chain/validation/syncCommitteeContributionAndProof.ts +1 -1
  172. package/src/db/repositories/blockArchive.ts +1 -2
  173. package/src/execution/engine/http.ts +3 -0
  174. package/src/metrics/metrics/lodestar.ts +5 -0
  175. package/src/monitoring/service.ts +3 -2
  176. package/src/network/core/networkCore.ts +3 -3
  177. package/src/network/core/networkCoreWorkerHandler.ts +3 -3
  178. package/src/network/core/types.ts +2 -2
  179. package/src/network/events.ts +2 -1
  180. package/src/network/gossip/encoding.ts +3 -3
  181. package/src/network/gossip/gossipsub.ts +86 -25
  182. package/src/network/gossip/interface.ts +3 -3
  183. package/src/network/gossip/scoringParameters.ts +4 -4
  184. package/src/network/interface.ts +3 -3
  185. package/src/network/libp2p/index.ts +33 -10
  186. package/src/network/network.ts +3 -3
  187. package/src/network/options.ts +3 -0
  188. package/src/network/peers/datastore.ts +13 -10
  189. package/src/network/peers/peerManager.ts +118 -54
  190. package/src/network/peers/utils/prioritizePeers.ts +3 -3
  191. package/src/network/processor/gossipHandlers.ts +7 -3
  192. package/src/network/processor/gossipValidatorFn.ts +1 -1
  193. package/src/network/processor/types.ts +1 -1
  194. package/src/network/reqresp/score.ts +0 -1
  195. package/src/network/util.ts +2 -2
  196. package/src/node/nodejs.ts +8 -9
  197. package/src/util/workerEvents.ts +1 -1
@@ -1,5 +1,5 @@
1
- import {ForkName, ForkPostFulu, ForkPreDeneb, ForkPreGloas, NUMBER_OF_COLUMNS} from "@lodestar/params";
2
- import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
1
+ import {ForkName, ForkPostFulu, ForkPostGloas, ForkPreDeneb, ForkPreGloas, NUMBER_OF_COLUMNS} from "@lodestar/params";
2
+ import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu, gloas} from "@lodestar/types";
3
3
  import {byteArrayEquals, fromHex, prettyBytes, toRootHex, withTimeout} from "@lodestar/utils";
4
4
  import {VersionedHashes} from "../../../execution/index.js";
5
5
  import {kzgCommitmentToVersionedHash} from "../../../util/blobs.js";
@@ -24,7 +24,7 @@ import {
24
24
  SourceMeta,
25
25
  } from "./types.js";
26
26
 
27
- export type BlockInput = BlockInputPreData | BlockInputBlobs | BlockInputColumns;
27
+ export type BlockInput = BlockInputPreData | BlockInputBlobs | BlockInputColumns | BlockInputNoData;
28
28
 
29
29
  export function isBlockInputPreDeneb(blockInput: IBlockInput): blockInput is BlockInputPreData {
30
30
  return blockInput.type === DAType.PreData;
@@ -37,6 +37,10 @@ export function isBlockInputColumns(blockInput: IBlockInput): blockInput is Bloc
37
37
  return blockInput.type === DAType.Columns;
38
38
  }
39
39
 
40
+ export function isBlockInputNoData(blockInput: IBlockInput): blockInput is BlockInputNoData {
41
+ return blockInput.type === DAType.NoData;
42
+ }
43
+
40
44
  function createPromise<T>(): PromiseParts<T> {
41
45
  let resolve!: (value: T) => void;
42
46
  let reject!: (e: Error) => void;
@@ -903,3 +907,64 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
903
907
  return Promise.resolve(this.getSampledColumns());
904
908
  }
905
909
  }
910
+
911
+ type BlockInputNoDataState = {
912
+ hasBlock: true;
913
+ hasAllData: true;
914
+ block: SignedBeaconBlock<ForkPostGloas>;
915
+ source: SourceMeta;
916
+ timeCompleteSec: number;
917
+ };
918
+
919
+ export class BlockInputNoData extends AbstractBlockInput<ForkPostGloas, null> {
920
+ type = DAType.NoData as const;
921
+
922
+ state: BlockInputNoDataState;
923
+
924
+ private constructor(init: BlockInputInit, state: BlockInputNoDataState) {
925
+ super(init);
926
+ this.state = state;
927
+ this.dataPromise.resolve(null);
928
+ this.blockPromise.resolve(state.block);
929
+ }
930
+
931
+ static createFromBlock(props: AddBlock<ForkPostGloas> & CreateBlockInputMeta): BlockInputNoData {
932
+ const init: BlockInputInit = {
933
+ daOutOfRange: props.daOutOfRange,
934
+ timeCreated: props.seenTimestampSec,
935
+ forkName: props.forkName,
936
+ slot: props.block.message.slot,
937
+ blockRootHex: props.blockRootHex,
938
+ parentRootHex: toRootHex(props.block.message.parentRoot),
939
+ };
940
+ const state: BlockInputNoDataState = {
941
+ hasBlock: true,
942
+ hasAllData: true,
943
+ block: props.block,
944
+ source: {
945
+ source: props.source,
946
+ seenTimestampSec: props.seenTimestampSec,
947
+ peerIdStr: props.peerIdStr,
948
+ },
949
+ timeCompleteSec: props.seenTimestampSec,
950
+ };
951
+ return new BlockInputNoData(init, state);
952
+ }
953
+
954
+ addBlock(_: AddBlock<ForkPostGloas>, opts = {throwOnDuplicateAdd: true}): void {
955
+ if (opts.throwOnDuplicateAdd) {
956
+ throw new BlockInputError(
957
+ {
958
+ code: BlockInputErrorCode.INVALID_CONSTRUCTION,
959
+ blockRoot: this.blockRootHex,
960
+ },
961
+ "Cannot addBlock to BlockInputNoData - block already exists"
962
+ );
963
+ }
964
+ }
965
+
966
+ getBlobKzgCommitments(): deneb.BlobKzgCommitments {
967
+ return (this.state.block.message.body as gloas.BeaconBlockBody).signedExecutionPayloadBid.message
968
+ .blobKzgCommitments;
969
+ }
970
+ }
@@ -6,6 +6,7 @@ export enum DAType {
6
6
  PreData = "pre-data",
7
7
  Blobs = "blobs",
8
8
  Columns = "columns",
9
+ NoData = "no-data",
9
10
  }
10
11
 
11
12
  export type DAData = null | deneb.BlobSidecars | fulu.DataColumnSidecars;
@@ -29,6 +29,9 @@ export async function verifyBlocksDataAvailability(
29
29
 
30
30
  const availableTime = Math.max(0, Math.max(...blocks.map((blockInput) => blockInput.getTimeComplete())));
31
31
  const dataAvailabilityStatuses: DataAvailabilityStatus[] = blocks.map((blockInput) => {
32
+ if (blockInput.type === DAType.NoData) {
33
+ return DataAvailabilityStatus.NotRequired;
34
+ }
32
35
  if (blockInput.type === DAType.PreData) {
33
36
  return DataAvailabilityStatus.PreData;
34
37
  }
@@ -21,7 +21,7 @@ import {Metrics} from "../../metrics/metrics.js";
21
21
  import {IClock} from "../../util/clock.js";
22
22
  import {BlockError, BlockErrorCode} from "../errors/index.js";
23
23
  import {BlockProcessOpts} from "../options.js";
24
- import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
24
+ import {isBlockInputBlobs, isBlockInputColumns, isBlockInputNoData} from "./blockInput/blockInput.js";
25
25
  import {IBlockInput} from "./blockInput/types.js";
26
26
  import {ImportBlockOpts} from "./types.js";
27
27
 
@@ -51,7 +51,8 @@ type VerifyBlockExecutionResponse =
51
51
  | VerifyExecutionErrorResponse
52
52
  | {executionStatus: ExecutionStatus.Valid; lvhResponse: LVHValidResponse; execError: null}
53
53
  | {executionStatus: ExecutionStatus.Syncing; lvhResponse?: LVHValidResponse; execError: null}
54
- | {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null};
54
+ | {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
55
+ | {executionStatus: ExecutionStatus.PayloadSeparated; lvhResponse: undefined; execError: null};
55
56
 
56
57
  /**
57
58
  * Verifies 1 or more execution payloads from a linear sequence of blocks.
@@ -148,6 +149,12 @@ export async function verifyBlockExecutionPayload(
148
149
  preState0: CachedBeaconStateAllForks
149
150
  ): Promise<VerifyBlockExecutionResponse> {
150
151
  const block = blockInput.getBlock();
152
+
153
+ // Gloas block doesn't have execution payload. Return right away
154
+ if (isBlockInputNoData(blockInput)) {
155
+ return {executionStatus: ExecutionStatus.PayloadSeparated, lvhResponse: undefined, execError: null};
156
+ }
157
+
151
158
  /** Not null if execution is enabled */
152
159
  const executionPayloadEnabled =
153
160
  isExecutionStateType(preState0) &&
@@ -7,7 +7,7 @@ import {Worker, spawn} from "@chainsafe/threads";
7
7
  self = undefined;
8
8
 
9
9
  import {PublicKey} from "@chainsafe/blst";
10
- import {ISignatureSet, Index2PubkeyCache} from "@lodestar/state-transition";
10
+ import {ISignatureSet, PubkeyCache} from "@lodestar/state-transition";
11
11
  import {Logger} from "@lodestar/utils";
12
12
  import {Metrics} from "../../../metrics/index.js";
13
13
  import {LinkedList} from "../../../util/array.js";
@@ -34,7 +34,7 @@ const workerDir = process.env.NODE_ENV === "test" ? "../../../../lib/chain/bls/m
34
34
  export type BlsMultiThreadWorkerPoolModules = {
35
35
  logger: Logger;
36
36
  metrics: Metrics | null;
37
- index2pubkey: Index2PubkeyCache;
37
+ pubkeyCache: PubkeyCache;
38
38
  };
39
39
 
40
40
  export type BlsMultiThreadWorkerPoolOptions = {
@@ -114,7 +114,7 @@ type WorkerDescriptor = {
114
114
  export class BlsMultiThreadWorkerPool implements IBlsVerifier {
115
115
  private readonly logger: Logger;
116
116
  private readonly metrics: Metrics | null;
117
- private readonly index2pubkey: Index2PubkeyCache;
117
+ private readonly pubkeyCache: PubkeyCache;
118
118
 
119
119
  private readonly workers: WorkerDescriptor[];
120
120
  private readonly jobs = new LinkedList<JobQueueItem>();
@@ -130,10 +130,10 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
130
130
  private workersBusy = 0;
131
131
 
132
132
  constructor(options: BlsMultiThreadWorkerPoolOptions, modules: BlsMultiThreadWorkerPoolModules) {
133
- const {logger, metrics, index2pubkey} = modules;
133
+ const {logger, metrics, pubkeyCache} = modules;
134
134
  this.logger = logger;
135
135
  this.metrics = metrics;
136
- this.index2pubkey = index2pubkey;
136
+ this.pubkeyCache = pubkeyCache;
137
137
  this.blsVerifyAllMultiThread = options.blsVerifyAllMultiThread ?? false;
138
138
 
139
139
  // Use compressed for herumi for now.
@@ -173,7 +173,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
173
173
  try {
174
174
  return verifySignatureSetsMaybeBatch(
175
175
  sets.map((set) => ({
176
- publicKey: getAggregatedPubkey(set, this.index2pubkey),
176
+ publicKey: getAggregatedPubkey(set, this.pubkeyCache),
177
177
  message: set.signingRoot.valueOf(),
178
178
  signature: set.signature,
179
179
  }))
@@ -398,7 +398,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier {
398
398
  try {
399
399
  // Note: This can throw, must be handled per-job.
400
400
  // Pubkey and signature aggregation is defered here
401
- workReq = await jobItemWorkReq(job, this.index2pubkey, this.metrics);
401
+ workReq = await jobItemWorkReq(job, this.pubkeyCache, this.metrics);
402
402
  } catch (e) {
403
403
  this.metrics?.blsThreadPool.errorAggregateSignatureSetsCount.inc({type: job.type});
404
404
 
@@ -1,5 +1,5 @@
1
1
  import {PublicKey, asyncAggregateWithRandomness} from "@chainsafe/blst";
2
- import {ISignatureSet, Index2PubkeyCache, SignatureSetType} from "@lodestar/state-transition";
2
+ import {ISignatureSet, PubkeyCache, SignatureSetType} from "@lodestar/state-transition";
3
3
  import {Metrics} from "../../../metrics/metrics.js";
4
4
  import {LinkedList} from "../../../util/array.js";
5
5
  import {VerifySignatureOpts} from "../interface.js";
@@ -50,7 +50,7 @@ export function jobItemSigSets(job: JobQueueItem): number {
50
50
  */
51
51
  export async function jobItemWorkReq(
52
52
  job: JobQueueItem,
53
- index2pubkey: Index2PubkeyCache,
53
+ pubkeyCache: PubkeyCache,
54
54
  metrics: Metrics | null
55
55
  ): Promise<BlsWorkReq> {
56
56
  switch (job.type) {
@@ -59,7 +59,7 @@ export async function jobItemWorkReq(
59
59
  opts: job.opts,
60
60
  sets: job.sets.map((set) => ({
61
61
  // this can throw, handled in the consumer code
62
- publicKey: getAggregatedPubkey(set, index2pubkey, metrics).toBytes(),
62
+ publicKey: getAggregatedPubkey(set, pubkeyCache, metrics).toBytes(),
63
63
  signature: set.signature,
64
64
  message: set.signingRoot,
65
65
  })),
@@ -1,5 +1,5 @@
1
1
  import {PublicKey, Signature, aggregatePublicKeys, aggregateSignatures, verify} from "@chainsafe/blst";
2
- import {ISignatureSet, Index2PubkeyCache} from "@lodestar/state-transition";
2
+ import {ISignatureSet, PubkeyCache} from "@lodestar/state-transition";
3
3
  import {Metrics} from "../../metrics/index.js";
4
4
  import {IBlsVerifier} from "./interface.js";
5
5
  import {verifySignatureSetsMaybeBatch} from "./maybeBatch.js";
@@ -7,18 +7,18 @@ import {getAggregatedPubkey, getAggregatedPubkeysCount} from "./utils.js";
7
7
 
8
8
  export class BlsSingleThreadVerifier implements IBlsVerifier {
9
9
  private readonly metrics: Metrics | null;
10
- private readonly index2pubkey: Index2PubkeyCache;
10
+ private readonly pubkeyCache: PubkeyCache;
11
11
 
12
- constructor({metrics = null, index2pubkey}: {metrics: Metrics | null; index2pubkey: Index2PubkeyCache}) {
12
+ constructor({metrics = null, pubkeyCache}: {metrics: Metrics | null; pubkeyCache: PubkeyCache}) {
13
13
  this.metrics = metrics;
14
- this.index2pubkey = index2pubkey;
14
+ this.pubkeyCache = pubkeyCache;
15
15
  }
16
16
 
17
17
  async verifySignatureSets(sets: ISignatureSet[]): Promise<boolean> {
18
18
  this.metrics?.bls.aggregatedPubkeys.inc(getAggregatedPubkeysCount(sets));
19
19
 
20
20
  const setsAggregated = sets.map((set) => ({
21
- publicKey: getAggregatedPubkey(set, this.index2pubkey, this.metrics),
21
+ publicKey: getAggregatedPubkey(set, this.pubkeyCache, this.metrics),
22
22
  message: set.signingRoot,
23
23
  signature: set.signature,
24
24
  }));
@@ -1,22 +1,25 @@
1
1
  import {PublicKey, aggregatePublicKeys} from "@chainsafe/blst";
2
- import {ISignatureSet, Index2PubkeyCache, SignatureSetType} from "@lodestar/state-transition";
2
+ import {ISignatureSet, PubkeyCache, SignatureSetType} from "@lodestar/state-transition";
3
3
  import {Metrics} from "../../metrics/metrics.js";
4
4
 
5
5
  export function getAggregatedPubkey(
6
6
  signatureSet: ISignatureSet,
7
- index2pubkey: Index2PubkeyCache,
7
+ pubkeyCache: PubkeyCache,
8
8
  metrics: Metrics | null = null
9
9
  ): PublicKey {
10
10
  switch (signatureSet.type) {
11
11
  case SignatureSetType.single:
12
12
  return signatureSet.pubkey;
13
13
 
14
- case SignatureSetType.indexed:
15
- return index2pubkey[signatureSet.index];
14
+ case SignatureSetType.indexed: {
15
+ return pubkeyCache.getOrThrow(signatureSet.index);
16
+ }
16
17
 
17
18
  case SignatureSetType.aggregate: {
18
19
  const timer = metrics?.blsThreadPool.pubkeysAggregationMainThreadDuration.startTimer();
19
- const pubkeys = signatureSet.indices.map((i) => index2pubkey[i]);
20
+ const pubkeys = signatureSet.indices.map((i) => {
21
+ return pubkeyCache.getOrThrow(i);
22
+ });
20
23
  const aggregated = aggregatePublicKeys(pubkeys);
21
24
  timer?.();
22
25
  return aggregated;
@@ -1,6 +1,5 @@
1
1
  import path from "node:path";
2
2
  import {PrivateKey} from "@libp2p/interface";
3
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
4
3
  import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
5
4
  import {BeaconConfig} from "@lodestar/config";
6
5
  import {CheckpointWithHex, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
@@ -21,7 +20,7 @@ import {
21
20
  CachedBeaconStateGloas,
22
21
  EffectiveBalanceIncrements,
23
22
  EpochShuffling,
24
- Index2PubkeyCache,
23
+ PubkeyCache,
25
24
  computeAnchorCheckpoint,
26
25
  computeAttestationsRewards,
27
26
  computeBlockRewards,
@@ -192,8 +191,7 @@ export class BeaconChain implements IBeaconChain {
192
191
  readonly seenBlockAttesters = new SeenBlockAttesters();
193
192
 
194
193
  // Global state caches
195
- readonly pubkey2index: PubkeyIndexMap;
196
- readonly index2pubkey: Index2PubkeyCache;
194
+ readonly pubkeyCache: PubkeyCache;
197
195
 
198
196
  readonly beaconProposerCache: BeaconProposerCache;
199
197
  readonly checkpointBalancesCache: CheckpointBalancesCache;
@@ -239,8 +237,7 @@ export class BeaconChain implements IBeaconChain {
239
237
  {
240
238
  privateKey,
241
239
  config,
242
- pubkey2index,
243
- index2pubkey,
240
+ pubkeyCache,
244
241
  db,
245
242
  dbName,
246
243
  dataDir,
@@ -256,8 +253,7 @@ export class BeaconChain implements IBeaconChain {
256
253
  }: {
257
254
  privateKey: PrivateKey;
258
255
  config: BeaconConfig;
259
- pubkey2index: PubkeyIndexMap;
260
- index2pubkey: Index2PubkeyCache;
256
+ pubkeyCache: PubkeyCache;
261
257
  db: IBeaconDb;
262
258
  dbName: string;
263
259
  dataDir: string;
@@ -289,8 +285,8 @@ export class BeaconChain implements IBeaconChain {
289
285
  const emitter = new ChainEventEmitter();
290
286
  // by default, verify signatures on both main threads and worker threads
291
287
  const bls = opts.blsVerifyAllMainThread
292
- ? new BlsSingleThreadVerifier({metrics, index2pubkey})
293
- : new BlsMultiThreadWorkerPool(opts, {logger, metrics, index2pubkey});
288
+ ? new BlsSingleThreadVerifier({metrics, pubkeyCache})
289
+ : new BlsMultiThreadWorkerPool(opts, {logger, metrics, pubkeyCache});
294
290
 
295
291
  if (!clock) clock = new Clock({config, genesisTime: this.genesisTime, signal});
296
292
 
@@ -346,8 +342,7 @@ export class BeaconChain implements IBeaconChain {
346
342
  ]);
347
343
 
348
344
  // Global cache of validators pubkey/index mapping
349
- this.pubkey2index = pubkey2index;
350
- this.index2pubkey = index2pubkey;
345
+ this.pubkeyCache = pubkeyCache;
351
346
 
352
347
  const fileDataStore = opts.nHistoricalStatesFileDataStore ?? true;
353
348
  const blockStateCache = new FIFOBlockStateCache(this.opts, {metrics});
@@ -920,7 +915,7 @@ export class BeaconChain implements IBeaconChain {
920
915
  RegenCaller.produceBlock
921
916
  );
922
917
  const proposerIndex = state.epochCtx.getBeaconProposer(slot);
923
- const proposerPubKey = this.index2pubkey[proposerIndex].toBytes();
918
+ const proposerPubKey = this.pubkeyCache.getOrThrow(proposerIndex).toBytes();
924
919
 
925
920
  const {body, produceResult, executionPayloadValue, shouldOverrideBuilder} = await produceBlockBody.call(
926
921
  this,
@@ -1536,7 +1531,7 @@ export class BeaconChain implements IBeaconChain {
1536
1531
  throw Error(`State is not in cache for slot ${slot}`);
1537
1532
  }
1538
1533
 
1539
- const rewards = await computeAttestationsRewards(this.config, this.pubkey2index, cachedState, validatorIds);
1534
+ const rewards = await computeAttestationsRewards(this.config, this.pubkeyCache, cachedState, validatorIds);
1540
1535
 
1541
1536
  return {rewards, executionOptimistic, finalized};
1542
1537
  }
@@ -1553,6 +1548,6 @@ export class BeaconChain implements IBeaconChain {
1553
1548
 
1554
1549
  preState = processSlots(preState, block.slot); // Dial preState's slot to block.slot
1555
1550
 
1556
- return computeSyncCommitteeRewards(this.config, this.index2pubkey, block, preState, validatorIds);
1551
+ return computeSyncCommitteeRewards(this.config, this.pubkeyCache, block, preState, validatorIds);
1557
1552
  }
1558
1553
  }
@@ -1,13 +1,7 @@
1
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
2
1
  import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
3
2
  import {BeaconConfig} from "@lodestar/config";
4
3
  import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
5
- import {
6
- BeaconStateAllForks,
7
- CachedBeaconStateAllForks,
8
- EpochShuffling,
9
- Index2PubkeyCache,
10
- } from "@lodestar/state-transition";
4
+ import {BeaconStateAllForks, CachedBeaconStateAllForks, EpochShuffling, PubkeyCache} from "@lodestar/state-transition";
11
5
  import {
12
6
  BeaconBlock,
13
7
  BlindedBeaconBlock,
@@ -117,8 +111,7 @@ export interface IBeaconChain {
117
111
  readonly regen: IStateRegenerator;
118
112
  readonly lightClientServer?: LightClientServer;
119
113
  readonly reprocessController: ReprocessController;
120
- readonly pubkey2index: PubkeyIndexMap;
121
- readonly index2pubkey: Index2PubkeyCache;
114
+ readonly pubkeyCache: PubkeyCache;
122
115
  readonly archiveStore: IArchiveStore;
123
116
 
124
117
  // Ops pool
@@ -3,6 +3,7 @@ import {CheckpointWithHex} from "@lodestar/fork-choice";
3
3
  import {
4
4
  ForkName,
5
5
  ForkPostFulu,
6
+ ForkPostGloas,
6
7
  ForkPreGloas,
7
8
  SLOTS_PER_EPOCH,
8
9
  isForkPostDeneb,
@@ -20,6 +21,7 @@ import {
20
21
  BlockInput,
21
22
  BlockInputBlobs,
22
23
  BlockInputColumns,
24
+ BlockInputNoData,
23
25
  BlockInputPreData,
24
26
  BlockWithSource,
25
27
  DAType,
@@ -179,12 +181,19 @@ export class SeenBlockInput {
179
181
  if (!blockInput) {
180
182
  const {forkName, daOutOfRange} = this.buildCommonProps(block.message.slot);
181
183
 
182
- // TODO GLOAS: Implement
183
184
  if (isForkPostGloas(forkName)) {
184
- throw Error("Not implemented");
185
- }
186
- // Pre-deneb
187
- if (!isForkPostDeneb(forkName)) {
185
+ // Post-gloas
186
+ blockInput = BlockInputNoData.createFromBlock({
187
+ block: block as SignedBeaconBlock<ForkPostGloas>,
188
+ blockRootHex,
189
+ daOutOfRange,
190
+ forkName,
191
+ source,
192
+ seenTimestampSec,
193
+ peerIdStr,
194
+ });
195
+ } else if (!isForkPostDeneb(forkName)) {
196
+ // Pre-deneb
188
197
  blockInput = BlockInputPreData.createFromBlock({
189
198
  block,
190
199
  blockRootHex,
@@ -194,8 +203,8 @@ export class SeenBlockInput {
194
203
  seenTimestampSec,
195
204
  peerIdStr,
196
205
  });
197
- // Fulu Only
198
206
  } else if (isForkPostFulu(forkName)) {
207
+ // Fulu Only
199
208
  blockInput = BlockInputColumns.createFromBlock({
200
209
  block: block as SignedBeaconBlock<ForkPostFulu & ForkPreGloas>,
201
210
  blockRootHex,
@@ -207,8 +216,8 @@ export class SeenBlockInput {
207
216
  seenTimestampSec,
208
217
  peerIdStr,
209
218
  });
210
- // Deneb and Electra
211
219
  } else {
220
+ // Deneb and Electra
212
221
  blockInput = BlockInputBlobs.createFromBlock({
213
222
  block: block as SignedBeaconBlock<ForkBlobsDA>,
214
223
  blockRootHex,
@@ -143,7 +143,10 @@ export async function validateGossipAttestationsSameAttData(
143
143
  if (batchableBls) {
144
144
  // all signature sets should have same signing root since we filtered in network processor
145
145
  signatureValids = await chain.bls.verifySignatureSetsSameMessage(
146
- signatureSets.map((set) => ({publicKey: chain.index2pubkey[set.index], signature: set.signature})),
146
+ signatureSets.map((set) => {
147
+ const publicKey = chain.pubkeyCache.getOrThrow(set.index);
148
+ return {publicKey, signature: set.signature};
149
+ }),
147
150
  signatureSets[0].signingRoot
148
151
  );
149
152
  } else {
@@ -45,7 +45,7 @@ export async function validateAttesterSlashing(
45
45
  // verifySignature = false, verified in batch below
46
46
  assertValidAttesterSlashing(
47
47
  chain.config,
48
- chain.index2pubkey,
48
+ chain.pubkeyCache,
49
49
  state.slot,
50
50
  state.validators.length,
51
51
  attesterSlashing,
@@ -87,8 +87,16 @@ async function validatePayloadAttestationMessage(
87
87
  }
88
88
 
89
89
  // [REJECT] `payload_attestation_message.signature` is valid with respect to the validator's public key.
90
+ const validatorPubkey = chain.pubkeyCache.get(validatorIndex);
91
+ if (!validatorPubkey) {
92
+ throw new PayloadAttestationError(GossipAction.REJECT, {
93
+ code: PayloadAttestationErrorCode.INVALID_ATTESTER,
94
+ attesterIndex: validatorIndex,
95
+ });
96
+ }
97
+
90
98
  const signatureSet = createSingleSignatureSetFromComponents(
91
- chain.index2pubkey[validatorIndex],
99
+ validatorPubkey,
92
100
  getPayloadAttestationDataSigningRoot(chain.config, data),
93
101
  payloadAttestationMessage.signature
94
102
  );
@@ -37,7 +37,7 @@ async function validateProposerSlashing(
37
37
  try {
38
38
  const proposer = state.validators.getReadonly(proposerSlashing.signedHeader1.message.proposerIndex);
39
39
  // verifySignature = false, verified in batch below
40
- assertValidProposerSlashing(chain.config, chain.index2pubkey, state.slot, proposerSlashing, proposer, false);
40
+ assertValidProposerSlashing(chain.config, chain.pubkeyCache, state.slot, proposerSlashing, proposer, false);
41
41
  } catch (e) {
42
42
  throw new ProposerSlashingError(GossipAction.REJECT, {
43
43
  code: ProposerSlashingErrorCode.INVALID,
@@ -106,7 +106,7 @@ export async function validateSyncCommitteeGossipContributionAndProof(
106
106
  /**
107
107
  * Retrieve pubkeys in contribution aggregate using epochCtx:
108
108
  * - currSyncCommitteeIndexes cache
109
- * - index2pubkey cache
109
+ * - pubkeyCache
110
110
  */
111
111
  function getContributionIndices(
112
112
  state: CachedBeaconStateAltair,
@@ -1,4 +1,3 @@
1
- import all from "it-all";
2
1
  import {ChainForkConfig} from "@lodestar/config";
3
2
  import {Db, FilterOptions, KeyValue, Repository} from "@lodestar/db";
4
3
  import {Root, SignedBeaconBlock, Slot, ssz} from "@lodestar/types";
@@ -121,7 +120,7 @@ export class BlockArchiveRepository extends Repository<Slot, SignedBeaconBlock>
121
120
  }
122
121
 
123
122
  async values(opts?: BlockFilterOptions): Promise<SignedBeaconBlock[]> {
124
- return all(this.valuesStream(opts));
123
+ return await Array.fromAsync(this.valuesStream(opts));
125
124
  }
126
125
 
127
126
  // INDEX
@@ -128,6 +128,7 @@ const getClientVersionOpts: ReqOpts = {routeId: "getClientVersion"};
128
128
  */
129
129
  export class ExecutionEngineHttp implements IExecutionEngine {
130
130
  private logger: Logger;
131
+ private metrics: Metrics | null;
131
132
 
132
133
  // The default state is ONLINE, it will be updated to SYNCING once we receive the first payload
133
134
  // This assumption is better than the OFFLINE state, since we can't be sure if the EL is offline and being offline may trigger some notifications
@@ -167,6 +168,7 @@ export class ExecutionEngineHttp implements IExecutionEngine {
167
168
  metrics?.engineHttpProcessorQueue
168
169
  );
169
170
  this.logger = logger;
171
+ this.metrics = metrics ?? null;
170
172
 
171
173
  this.rpc.emitter.on(JsonRpcHttpClientEvent.ERROR, ({error}) => {
172
174
  this.updateEngineState(getExecutionEngineState({payloadError: error, oldState: this.state}));
@@ -369,6 +371,7 @@ export class ExecutionEngineHttp implements IExecutionEngine {
369
371
  } = await request;
370
372
 
371
373
  this.updateEngineState(getExecutionEngineState({payloadStatus: status, oldState: this.state}));
374
+ this.metrics?.engineNotifyForkchoiceUpdateResult.inc({result: status});
372
375
 
373
376
  switch (status) {
374
377
  case ExecutionPayloadStatus.VALID:
@@ -928,6 +928,11 @@ export function createLodestarMetrics(
928
928
  help: "The total result of calling notifyNewPayload execution engine api",
929
929
  labelNames: ["result"],
930
930
  }),
931
+ engineNotifyForkchoiceUpdateResult: register.gauge<{result: ExecutionPayloadStatus}>({
932
+ name: "lodestar_execution_engine_notify_forkchoice_update_result_total",
933
+ help: "The total result of calling notifyForkchoiceUpdate execution engine api",
934
+ labelNames: ["result"],
935
+ }),
931
936
  backfillSync: {
932
937
  backfilledTillSlot: register.gauge({
933
938
  name: "lodestar_backfill_till_slot",
@@ -89,9 +89,9 @@ export class MonitoringService {
89
89
  }
90
90
 
91
91
  /**
92
- * Stop sending client stats
92
+ * Stop sending client stats and wait for any pending request to complete
93
93
  */
94
- close(): void {
94
+ async close(): Promise<void> {
95
95
  if (this.status === Status.Closed) return;
96
96
  this.status = Status.Closed;
97
97
 
@@ -103,6 +103,7 @@ export class MonitoringService {
103
103
  }
104
104
  if (this.pendingRequest) {
105
105
  this.fetchAbortController?.abort(FetchAbortReason.Close);
106
+ await this.pendingRequest;
106
107
  }
107
108
  }
108
109
 
@@ -1,8 +1,8 @@
1
- import {Connection, PrivateKey} from "@libp2p/interface";
1
+ import type {PeerScoreStatsDump} from "@libp2p/gossipsub/score";
2
+ import type {PublishOpts} from "@libp2p/gossipsub/types";
3
+ import type {Connection, PrivateKey} from "@libp2p/interface";
2
4
  import {peerIdFromPrivateKey} from "@libp2p/peer-id";
3
5
  import {multiaddr} from "@multiformats/multiaddr";
4
- import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/score";
5
- import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
6
6
  import {routes} from "@lodestar/api";
7
7
  import {BeaconConfig, ForkBoundary} from "@lodestar/config";
8
8
  import type {LoggerNode} from "@lodestar/logger/node";
@@ -1,9 +1,9 @@
1
1
  import path from "node:path";
2
2
  import workerThreads from "node:worker_threads";
3
3
  import {privateKeyToProtobuf} from "@libp2p/crypto/keys";
4
- import {PrivateKey} from "@libp2p/interface";
5
- import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/score";
6
- import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
4
+ import type {PeerScoreStatsDump} from "@libp2p/gossipsub/score";
5
+ import type {PublishOpts} from "@libp2p/gossipsub/types";
6
+ import type {PrivateKey} from "@libp2p/interface";
7
7
  import {ModuleThread, Thread, Worker, spawn} from "@chainsafe/threads";
8
8
  import {routes} from "@lodestar/api";
9
9
  import {BeaconConfig, chainConfigToJson} from "@lodestar/config";
@@ -1,5 +1,5 @@
1
- import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/score";
2
- import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
1
+ import type {PeerScoreStatsDump} from "@libp2p/gossipsub/score";
2
+ import type {PublishOpts} from "@libp2p/gossipsub/types";
3
3
  import {routes} from "@lodestar/api";
4
4
  import {SpecJson} from "@lodestar/config";
5
5
  import {LoggerNodeOpts} from "@lodestar/logger/node";
@@ -1,5 +1,6 @@
1
1
  import {EventEmitter} from "node:events";
2
- import {PeerId, TopicValidatorResult} from "@libp2p/interface";
2
+ import type {TopicValidatorResult} from "@libp2p/gossipsub";
3
+ import type {PeerId} from "@libp2p/interface";
3
4
  import {CustodyIndex, Status} from "@lodestar/types";
4
5
  import {PeerIdStr} from "../util/peerId.js";
5
6
  import {StrictEventEmitterSingleArg} from "../util/strictEvents.js";