@lodestar/beacon-node 1.41.0-dev.628870a020 → 1.41.0-dev.95cf2edc4c

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 (200) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +121 -3
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/index.js +8 -8
  5. package/lib/api/impl/beacon/state/index.js.map +1 -1
  6. package/lib/api/impl/beacon/state/utils.d.ts +3 -4
  7. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  8. package/lib/api/impl/beacon/state/utils.js +5 -24
  9. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  10. package/lib/api/impl/debug/index.d.ts.map +1 -1
  11. package/lib/api/impl/debug/index.js +5 -2
  12. package/lib/api/impl/debug/index.js.map +1 -1
  13. package/lib/api/impl/validator/index.d.ts.map +1 -1
  14. package/lib/api/impl/validator/index.js +104 -6
  15. package/lib/api/impl/validator/index.js.map +1 -1
  16. package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
  17. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/archiveStore.js +9 -0
  19. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  20. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +5 -6
  21. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  22. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +9 -10
  23. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  24. package/lib/chain/archiveStore/historicalState/worker.js +3 -3
  25. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  26. package/lib/chain/archiveStore/utils/archivePayloads.d.ts +7 -0
  27. package/lib/chain/archiveStore/utils/archivePayloads.d.ts.map +1 -0
  28. package/lib/chain/archiveStore/utils/archivePayloads.js +10 -0
  29. package/lib/chain/archiveStore/utils/archivePayloads.js.map +1 -0
  30. package/lib/chain/bls/multithread/index.d.ts +3 -3
  31. package/lib/chain/bls/multithread/index.d.ts.map +1 -1
  32. package/lib/chain/bls/multithread/index.js +5 -5
  33. package/lib/chain/bls/multithread/index.js.map +1 -1
  34. package/lib/chain/bls/multithread/jobItem.d.ts +2 -2
  35. package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
  36. package/lib/chain/bls/multithread/jobItem.js +2 -2
  37. package/lib/chain/bls/multithread/jobItem.js.map +1 -1
  38. package/lib/chain/bls/singleThread.d.ts +4 -4
  39. package/lib/chain/bls/singleThread.d.ts.map +1 -1
  40. package/lib/chain/bls/singleThread.js +4 -4
  41. package/lib/chain/bls/singleThread.js.map +1 -1
  42. package/lib/chain/bls/utils.d.ts +2 -2
  43. package/lib/chain/bls/utils.d.ts.map +1 -1
  44. package/lib/chain/bls/utils.js +7 -4
  45. package/lib/chain/bls/utils.js.map +1 -1
  46. package/lib/chain/chain.d.ts +6 -9
  47. package/lib/chain/chain.d.ts.map +1 -1
  48. package/lib/chain/chain.js +32 -16
  49. package/lib/chain/chain.js.map +1 -1
  50. package/lib/chain/emitter.d.ts +2 -2
  51. package/lib/chain/emitter.d.ts.map +1 -1
  52. package/lib/chain/interface.d.ts +4 -6
  53. package/lib/chain/interface.d.ts.map +1 -1
  54. package/lib/chain/interface.js.map +1 -1
  55. package/lib/chain/options.d.ts.map +1 -1
  56. package/lib/chain/options.js.map +1 -1
  57. package/lib/chain/prepareNextSlot.js +3 -3
  58. package/lib/chain/prepareNextSlot.js.map +1 -1
  59. package/lib/chain/produceBlock/computeNewStateRoot.d.ts +10 -2
  60. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  61. package/lib/chain/produceBlock/computeNewStateRoot.js +24 -2
  62. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  63. package/lib/chain/produceBlock/produceBlockBody.d.ts +22 -7
  64. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  65. package/lib/chain/produceBlock/produceBlockBody.js +110 -10
  66. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  67. package/lib/chain/validation/attestation.d.ts.map +1 -1
  68. package/lib/chain/validation/attestation.js +4 -1
  69. package/lib/chain/validation/attestation.js.map +1 -1
  70. package/lib/chain/validation/attesterSlashing.js +1 -1
  71. package/lib/chain/validation/attesterSlashing.js.map +1 -1
  72. package/lib/chain/validation/dataColumnSidecar.d.ts +2 -2
  73. package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
  74. package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
  75. package/lib/chain/validation/payloadAttestationMessage.js +8 -1
  76. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  77. package/lib/chain/validation/proposerSlashing.js +1 -1
  78. package/lib/chain/validation/proposerSlashing.js.map +1 -1
  79. package/lib/chain/validation/syncCommitteeContributionAndProof.js +1 -1
  80. package/lib/db/beacon.d.ts +3 -1
  81. package/lib/db/beacon.d.ts.map +1 -1
  82. package/lib/db/beacon.js +5 -1
  83. package/lib/db/beacon.js.map +1 -1
  84. package/lib/db/buckets.d.ts +3 -1
  85. package/lib/db/buckets.d.ts.map +1 -1
  86. package/lib/db/buckets.js +2 -0
  87. package/lib/db/buckets.js.map +1 -1
  88. package/lib/db/interface.d.ts +3 -1
  89. package/lib/db/interface.d.ts.map +1 -1
  90. package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
  91. package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
  92. package/lib/db/repositories/dataColumnSidecar.d.ts +5 -3
  93. package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
  94. package/lib/db/repositories/dataColumnSidecar.js +14 -1
  95. package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
  96. package/lib/db/repositories/dataColumnSidecarArchive.d.ts +5 -3
  97. package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
  98. package/lib/db/repositories/dataColumnSidecarArchive.js +14 -1
  99. package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
  100. package/lib/db/repositories/executionPayloadEnvelope.d.ts +19 -0
  101. package/lib/db/repositories/executionPayloadEnvelope.d.ts.map +1 -0
  102. package/lib/db/repositories/executionPayloadEnvelope.js +22 -0
  103. package/lib/db/repositories/executionPayloadEnvelope.js.map +1 -0
  104. package/lib/db/repositories/executionPayloadEnvelopeArchive.d.ts +18 -0
  105. package/lib/db/repositories/executionPayloadEnvelopeArchive.d.ts.map +1 -0
  106. package/lib/db/repositories/executionPayloadEnvelopeArchive.js +28 -0
  107. package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -0
  108. package/lib/db/repositories/index.d.ts +2 -0
  109. package/lib/db/repositories/index.d.ts.map +1 -1
  110. package/lib/db/repositories/index.js +2 -0
  111. package/lib/db/repositories/index.js.map +1 -1
  112. package/lib/metrics/metrics/beacon.d.ts +1 -0
  113. package/lib/metrics/metrics/beacon.d.ts.map +1 -1
  114. package/lib/metrics/metrics/beacon.js +5 -0
  115. package/lib/metrics/metrics/beacon.js.map +1 -1
  116. package/lib/metrics/metrics/lodestar.d.ts +5 -0
  117. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  118. package/lib/metrics/metrics/lodestar.js +9 -0
  119. package/lib/metrics/metrics/lodestar.js.map +1 -1
  120. package/lib/monitoring/service.d.ts +2 -2
  121. package/lib/monitoring/service.d.ts.map +1 -1
  122. package/lib/monitoring/service.js +3 -2
  123. package/lib/monitoring/service.js.map +1 -1
  124. package/lib/network/gossip/interface.d.ts +3 -3
  125. package/lib/network/gossip/interface.d.ts.map +1 -1
  126. package/lib/network/gossip/topic.d.ts +113 -63
  127. package/lib/network/gossip/topic.d.ts.map +1 -1
  128. package/lib/network/gossip/topic.js +2 -2
  129. package/lib/network/gossip/topic.js.map +1 -1
  130. package/lib/network/interface.d.ts +3 -2
  131. package/lib/network/interface.d.ts.map +1 -1
  132. package/lib/network/network.d.ts +3 -2
  133. package/lib/network/network.d.ts.map +1 -1
  134. package/lib/network/network.js +10 -1
  135. package/lib/network/network.js.map +1 -1
  136. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  137. package/lib/network/processor/gossipHandlers.js +5 -1
  138. package/lib/network/processor/gossipHandlers.js.map +1 -1
  139. package/lib/node/nodejs.d.ts +3 -5
  140. package/lib/node/nodejs.d.ts.map +1 -1
  141. package/lib/node/nodejs.js +6 -4
  142. package/lib/node/nodejs.js.map +1 -1
  143. package/lib/util/blobs.d.ts +2 -2
  144. package/lib/util/blobs.d.ts.map +1 -1
  145. package/lib/util/blobs.js.map +1 -1
  146. package/lib/util/dataColumns.d.ts +11 -3
  147. package/lib/util/dataColumns.d.ts.map +1 -1
  148. package/lib/util/dataColumns.js +27 -0
  149. package/lib/util/dataColumns.js.map +1 -1
  150. package/lib/util/multifork.d.ts +8 -0
  151. package/lib/util/multifork.d.ts.map +1 -1
  152. package/lib/util/multifork.js +37 -0
  153. package/lib/util/multifork.js.map +1 -1
  154. package/package.json +15 -15
  155. package/src/api/impl/beacon/blocks/index.ts +145 -2
  156. package/src/api/impl/beacon/state/index.ts +8 -8
  157. package/src/api/impl/beacon/state/utils.ts +15 -29
  158. package/src/api/impl/debug/index.ts +8 -5
  159. package/src/api/impl/validator/index.ts +127 -5
  160. package/src/chain/archiveStore/archiveStore.ts +10 -0
  161. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +10 -11
  162. package/src/chain/archiveStore/historicalState/worker.ts +3 -3
  163. package/src/chain/archiveStore/utils/archivePayloads.ts +15 -0
  164. package/src/chain/bls/multithread/index.ts +7 -7
  165. package/src/chain/bls/multithread/jobItem.ts +3 -3
  166. package/src/chain/bls/singleThread.ts +5 -5
  167. package/src/chain/bls/utils.ts +8 -5
  168. package/src/chain/chain.ts +51 -26
  169. package/src/chain/emitter.ts +2 -2
  170. package/src/chain/interface.ts +4 -11
  171. package/src/chain/options.ts +1 -0
  172. package/src/chain/prepareNextSlot.ts +5 -5
  173. package/src/chain/produceBlock/computeNewStateRoot.ts +35 -3
  174. package/src/chain/produceBlock/produceBlockBody.ts +163 -13
  175. package/src/chain/validation/attestation.ts +4 -1
  176. package/src/chain/validation/attesterSlashing.ts +1 -1
  177. package/src/chain/validation/dataColumnSidecar.ts +2 -5
  178. package/src/chain/validation/payloadAttestationMessage.ts +9 -1
  179. package/src/chain/validation/proposerSlashing.ts +1 -1
  180. package/src/chain/validation/syncCommitteeContributionAndProof.ts +1 -1
  181. package/src/db/beacon.ts +8 -0
  182. package/src/db/buckets.ts +3 -0
  183. package/src/db/interface.ts +5 -0
  184. package/src/db/repositories/dataColumnSidecar.ts +18 -3
  185. package/src/db/repositories/dataColumnSidecarArchive.ts +18 -3
  186. package/src/db/repositories/executionPayloadEnvelope.ts +26 -0
  187. package/src/db/repositories/executionPayloadEnvelopeArchive.ts +32 -0
  188. package/src/db/repositories/index.ts +2 -0
  189. package/src/metrics/metrics/beacon.ts +5 -0
  190. package/src/metrics/metrics/lodestar.ts +9 -0
  191. package/src/monitoring/service.ts +3 -2
  192. package/src/network/gossip/interface.ts +3 -3
  193. package/src/network/gossip/topic.ts +2 -1
  194. package/src/network/interface.ts +4 -1
  195. package/src/network/network.ts +21 -3
  196. package/src/network/processor/gossipHandlers.ts +7 -1
  197. package/src/node/nodejs.ts +8 -9
  198. package/src/util/blobs.ts +3 -3
  199. package/src/util/dataColumns.ts +37 -1
  200. package/src/util/multifork.ts +45 -0
@@ -1,9 +1,17 @@
1
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
2
1
  import {routes} from "@lodestar/api";
3
2
  import {CheckpointWithHex, IForkChoice} from "@lodestar/fork-choice";
4
3
  import {GENESIS_SLOT} from "@lodestar/params";
5
- import {BeaconStateAllForks, CachedBeaconStateAllForks} from "@lodestar/state-transition";
6
- import {BLSPubkey, Epoch, RootHex, Slot, ValidatorIndex, getValidatorStatus, phase0} from "@lodestar/types";
4
+ import {BeaconStateAllForks, CachedBeaconStateAllForks, PubkeyCache} from "@lodestar/state-transition";
5
+ import {
6
+ BLSPubkey,
7
+ Epoch,
8
+ RootHex,
9
+ Slot,
10
+ ValidatorIndex,
11
+ getValidatorStatus,
12
+ mapToGeneralStatus,
13
+ phase0,
14
+ } from "@lodestar/types";
7
15
  import {fromHex} from "@lodestar/utils";
8
16
  import {IBeaconChain} from "../../../../chain/index.js";
9
17
  import {ApiError, ValidationError} from "../../errors.js";
@@ -65,28 +73,6 @@ export async function getStateResponseWithRegen(
65
73
  return res;
66
74
  }
67
75
 
68
- type GeneralValidatorStatus = "active" | "pending" | "exited" | "withdrawal";
69
-
70
- function mapToGeneralStatus(subStatus: routes.beacon.ValidatorStatus): GeneralValidatorStatus {
71
- switch (subStatus) {
72
- case "active_ongoing":
73
- case "active_exiting":
74
- case "active_slashed":
75
- return "active";
76
- case "pending_initialized":
77
- case "pending_queued":
78
- return "pending";
79
- case "exited_slashed":
80
- case "exited_unslashed":
81
- return "exited";
82
- case "withdrawal_possible":
83
- case "withdrawal_done":
84
- return "withdrawal";
85
- default:
86
- throw new Error(`Unknown substatus: ${subStatus}`);
87
- }
88
- }
89
-
90
76
  export function toValidatorResponse(
91
77
  index: ValidatorIndex,
92
78
  validator: phase0.Validator,
@@ -104,7 +90,7 @@ export function toValidatorResponse(
104
90
  export function filterStateValidatorsByStatus(
105
91
  statuses: string[],
106
92
  state: BeaconStateAllForks,
107
- pubkey2index: PubkeyIndexMap,
93
+ pubkeyCache: PubkeyCache,
108
94
  currentEpoch: Epoch
109
95
  ): routes.beacon.ValidatorResponse[] {
110
96
  const responses: routes.beacon.ValidatorResponse[] = [];
@@ -115,7 +101,7 @@ export function filterStateValidatorsByStatus(
115
101
  const validatorStatus = getValidatorStatus(validator, currentEpoch);
116
102
  const generalStatus = mapToGeneralStatus(validatorStatus);
117
103
 
118
- const resp = getStateValidatorIndex(validator.pubkey, state, pubkey2index);
104
+ const resp = getStateValidatorIndex(validator.pubkey, state, pubkeyCache);
119
105
  if (resp.valid && (statusSet.has(validatorStatus) || statusSet.has(generalStatus))) {
120
106
  responses.push(
121
107
  toValidatorResponse(resp.validatorIndex, validator, state.balances.get(resp.validatorIndex), currentEpoch)
@@ -132,7 +118,7 @@ type StateValidatorIndexResponse =
132
118
  export function getStateValidatorIndex(
133
119
  id: routes.beacon.ValidatorId | BLSPubkey,
134
120
  state: BeaconStateAllForks,
135
- pubkey2index: PubkeyIndexMap
121
+ pubkeyCache: PubkeyCache
136
122
  ): StateValidatorIndexResponse {
137
123
  if (typeof id === "string") {
138
124
  // mutate `id` and fallthrough to below
@@ -160,7 +146,7 @@ export function getStateValidatorIndex(
160
146
  }
161
147
 
162
148
  // typeof id === Uint8Array
163
- const validatorIndex = pubkey2index.get(id);
149
+ const validatorIndex = pubkeyCache.getIndex(id);
164
150
  if (validatorIndex === null) {
165
151
  return {valid: false, code: 404, reason: "Validator pubkey not found in state"};
166
152
  }
@@ -1,9 +1,10 @@
1
1
  import {routes} from "@lodestar/api";
2
2
  import {ApplicationMethods} from "@lodestar/api/server";
3
3
  import {ExecutionStatus} from "@lodestar/fork-choice";
4
- import {ZERO_HASH_HEX, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
5
- import {BeaconState, deneb, fulu, sszTypesFor} from "@lodestar/types";
4
+ import {ForkPostDeneb, ZERO_HASH_HEX, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
5
+ import {BeaconState, DataColumnSidecars, type SignedBeaconBlock, sszTypesFor} from "@lodestar/types";
6
6
  import {toRootHex} from "@lodestar/utils";
7
+ import {getBlobKzgCommitments} from "../../../util/dataColumns.js";
7
8
  import {isOptimisticBlock} from "../../../util/forkChoice.js";
8
9
  import {getStateSlotFromBytes} from "../../../util/multifork.js";
9
10
  import {getBlockResponse} from "../beacon/blocks/utils.js";
@@ -96,10 +97,10 @@ export function getDebugApi({
96
97
  const fork = config.getForkName(block.message.slot);
97
98
  const blockRoot = sszTypesFor(fork).BeaconBlock.hashTreeRoot(block.message);
98
99
 
99
- let dataColumnSidecars: fulu.DataColumnSidecars;
100
+ let dataColumnSidecars: DataColumnSidecars;
100
101
 
101
102
  const blobCount = isForkPostDeneb(fork)
102
- ? (block.message.body as deneb.BeaconBlockBody).blobKzgCommitments.length
103
+ ? getBlobKzgCommitments(fork, block as SignedBeaconBlock<ForkPostDeneb>).length
103
104
  : 0;
104
105
 
105
106
  if (isForkPostFulu(fork) && blobCount > 0) {
@@ -115,7 +116,9 @@ export function getDebugApi({
115
116
  }
116
117
 
117
118
  return {
118
- data: indices ? dataColumnSidecars.filter(({index}) => indices.includes(index)) : dataColumnSidecars,
119
+ data: (indices
120
+ ? dataColumnSidecars.filter(({index}) => indices.includes(index))
121
+ : dataColumnSidecars) as DataColumnSidecars,
119
122
  meta: {
120
123
  executionOptimistic,
121
124
  finalized,
@@ -1,8 +1,8 @@
1
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
2
1
  import {routes} from "@lodestar/api";
3
2
  import {ApplicationMethods} from "@lodestar/api/server";
4
3
  import {ExecutionStatus, ProtoBlock} from "@lodestar/fork-choice";
5
4
  import {
5
+ BUILDER_INDEX_SELF_BUILD,
6
6
  ForkName,
7
7
  ForkPostBellatrix,
8
8
  ForkPreGloas,
@@ -14,6 +14,7 @@ import {
14
14
  isForkPostBellatrix,
15
15
  isForkPostDeneb,
16
16
  isForkPostElectra,
17
+ isForkPostGloas,
17
18
  } from "@lodestar/params";
18
19
  import {
19
20
  CachedBeaconStateAllForks,
@@ -25,6 +26,7 @@ import {
25
26
  computeStartSlotAtEpoch,
26
27
  computeTimeAtSlot,
27
28
  createCachedBeaconState,
29
+ createPubkeyCache,
28
30
  getBlockRootAtSlot,
29
31
  getCurrentSlot,
30
32
  loadState,
@@ -45,6 +47,7 @@ import {
45
47
  Wei,
46
48
  bellatrix,
47
49
  getValidatorStatus,
50
+ gloas,
48
51
  phase0,
49
52
  ssz,
50
53
  } from "@lodestar/types";
@@ -69,7 +72,7 @@ import {
69
72
  } from "../../../chain/errors/index.js";
70
73
  import {ChainEvent, CommonBlockBody} from "../../../chain/index.js";
71
74
  import {PREPARE_NEXT_SLOT_BPS} from "../../../chain/prepareNextSlot.js";
72
- import {BlockType, ProduceFullDeneb} from "../../../chain/produceBlock/index.js";
75
+ import {BlockType, ProduceFullDeneb, ProduceFullGloas} from "../../../chain/produceBlock/index.js";
73
76
  import {RegenCaller} from "../../../chain/regen/index.js";
74
77
  import {CheckpointHex} from "../../../chain/stateCache/types.js";
75
78
  import {validateApiAggregateAndProof} from "../../../chain/validation/index.js";
@@ -901,6 +904,77 @@ export function getValidatorApi(
901
904
  return {data, meta};
902
905
  },
903
906
 
907
+ async produceBlockV4({slot, randaoReveal, graffiti, feeRecipient}) {
908
+ const fork = config.getForkName(slot);
909
+
910
+ if (!isForkPostGloas(fork)) {
911
+ throw new ApiError(400, `produceBlockV4 not supported for pre-gloas fork=${fork}`);
912
+ }
913
+
914
+ notWhileSyncing();
915
+ await waitForSlot(slot);
916
+
917
+ // TODO GLOAS: support producing blocks from builder bids
918
+ const source = ProducedBlockSource.engine;
919
+
920
+ // TODO GLOAS: needs to be updated after fork choice changes are merged
921
+ const parentBlock = chain.getProposerHead(slot);
922
+ const {blockRoot: parentBlockRootHex, slot: parentSlot} = parentBlock;
923
+ const parentBlockRoot = fromHex(parentBlockRootHex);
924
+ notOnOutOfRangeData(parentBlockRoot);
925
+ metrics?.blockProductionSlotDelta.set(slot - parentSlot);
926
+ metrics?.blockProductionRequests.inc({source});
927
+
928
+ const graffitiBytes = toGraffitiBytes(
929
+ graffiti ?? getDefaultGraffiti(getLodestarClientVersion(), chain.executionEngine.clientVersion, {})
930
+ );
931
+ const commonBlockBodyPromise = chain.produceCommonBlockBody({
932
+ slot,
933
+ parentBlock,
934
+ randaoReveal,
935
+ graffiti: graffitiBytes,
936
+ });
937
+
938
+ let timer: undefined | ((opts: {source: ProducedBlockSource}) => number);
939
+ try {
940
+ timer = metrics?.blockProductionTime.startTimer();
941
+ const {block, executionPayloadValue, consensusBlockValue} = await chain.produceBlock({
942
+ slot,
943
+ parentBlock,
944
+ randaoReveal,
945
+ graffiti: graffitiBytes,
946
+ feeRecipient,
947
+ commonBlockBodyPromise,
948
+ });
949
+
950
+ metrics?.blockProductionSuccess.inc({source});
951
+ metrics?.blockProductionNumAggregated.observe({source}, block.body.attestations.length);
952
+ metrics?.blockProductionConsensusBlockValue.observe({source}, Number(formatWeiToEth(consensusBlockValue)));
953
+ metrics?.blockProductionExecutionPayloadValue.observe({source}, Number(formatWeiToEth(executionPayloadValue)));
954
+
955
+ const blockRoot = toRootHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block));
956
+ logger.verbose("Produced block", {
957
+ slot,
958
+ executionPayloadValue,
959
+ consensusBlockValue,
960
+ root: blockRoot,
961
+ });
962
+ if (chain.opts.persistProducedBlocks) {
963
+ void chain.persistBlock(block, "produced_engine_block");
964
+ }
965
+
966
+ return {
967
+ data: block as gloas.BeaconBlock,
968
+ meta: {
969
+ version: fork,
970
+ consensusBlockValue,
971
+ },
972
+ };
973
+ } finally {
974
+ timer?.({source});
975
+ }
976
+ },
977
+
904
978
  async produceAttestationData({committeeIndex, slot}) {
905
979
  notWhileSyncing();
906
980
 
@@ -1049,8 +1123,7 @@ export function getValidatorApi(
1049
1123
  {
1050
1124
  config: chain.config,
1051
1125
  // Not required to compute proposers
1052
- pubkey2index: new PubkeyIndexMap(),
1053
- index2pubkey: [],
1126
+ pubkeyCache: createPubkeyCache(),
1054
1127
  },
1055
1128
  {skipSyncPubkeys: true, skipSyncCommitteeCache: true}
1056
1129
  );
@@ -1511,7 +1584,7 @@ export function getValidatorApi(
1511
1584
 
1512
1585
  const filteredRegistrations = registrations.filter((registration) => {
1513
1586
  const {pubkey} = registration.message;
1514
- const validatorIndex = chain.pubkey2index.get(pubkey);
1587
+ const validatorIndex = chain.pubkeyCache.getIndex(pubkey);
1515
1588
  if (validatorIndex === null) return false;
1516
1589
 
1517
1590
  const validator = headState.validators.getReadonly(validatorIndex);
@@ -1532,5 +1605,54 @@ export function getValidatorApi(
1532
1605
  count: filteredRegistrations.length,
1533
1606
  });
1534
1607
  },
1608
+
1609
+ async getExecutionPayloadEnvelope({slot, beaconBlockRoot}) {
1610
+ const fork = config.getForkName(slot);
1611
+
1612
+ if (!isForkPostGloas(fork)) {
1613
+ throw new ApiError(400, `getExecutionPayloadEnvelope not supported for pre-gloas fork=${fork}`);
1614
+ }
1615
+
1616
+ notWhileSyncing();
1617
+ await waitForSlot(slot);
1618
+
1619
+ const blockRootHex = toRootHex(beaconBlockRoot);
1620
+ const produceResult = chain.blockProductionCache.get(blockRootHex);
1621
+
1622
+ if (produceResult === undefined) {
1623
+ throw new ApiError(404, `No cached block production result found for block root ${blockRootHex}`);
1624
+ }
1625
+ if (!isForkPostGloas(produceResult.fork)) {
1626
+ throw Error(`Cached block production result is for pre-gloas fork=${produceResult.fork}`);
1627
+ }
1628
+ if (produceResult.type !== BlockType.Full) {
1629
+ throw Error("Cached block production result is not full block");
1630
+ }
1631
+
1632
+ const {executionPayload, executionRequests, envelopeStateRoot} = produceResult as ProduceFullGloas;
1633
+
1634
+ const envelope: gloas.ExecutionPayloadEnvelope = {
1635
+ payload: executionPayload,
1636
+ executionRequests: executionRequests,
1637
+ builderIndex: BUILDER_INDEX_SELF_BUILD,
1638
+ beaconBlockRoot,
1639
+ slot,
1640
+ stateRoot: envelopeStateRoot,
1641
+ };
1642
+
1643
+ logger.info("Produced execution payload envelope", {
1644
+ slot,
1645
+ blockRoot: blockRootHex,
1646
+ transactions: executionPayload.transactions.length,
1647
+ blockHash: toRootHex(executionPayload.blockHash),
1648
+ });
1649
+
1650
+ return {
1651
+ data: envelope,
1652
+ meta: {
1653
+ version: fork,
1654
+ },
1655
+ };
1656
+ },
1535
1657
  };
1536
1658
  }
@@ -1,5 +1,6 @@
1
1
  import {CheckpointWithHex} from "@lodestar/fork-choice";
2
2
  import {LoggerNode} from "@lodestar/logger/node";
3
+ import {ForkSeq} from "@lodestar/params";
3
4
  import {Checkpoint} from "@lodestar/types/phase0";
4
5
  import {callFnWhenAwait} from "@lodestar/utils";
5
6
  import {IBeaconDb} from "../../db/index.js";
@@ -13,6 +14,7 @@ import {HistoricalStateRegen} from "./historicalState/historicalStateRegen.js";
13
14
  import {ArchiveMode, ArchiveStoreOpts, StateArchiveStrategy} from "./interface.js";
14
15
  import {FrequencyStateArchiveStrategy} from "./strategies/frequencyStateArchiveStrategy.js";
15
16
  import {archiveBlocks} from "./utils/archiveBlocks.js";
17
+ import {archiveExecutionPayloadEnvelopes} from "./utils/archivePayloads.js";
16
18
  import {pruneHistory} from "./utils/pruneHistory.js";
17
19
  import {updateBackfillRange} from "./utils/updateBackfillRange.js";
18
20
 
@@ -27,6 +29,7 @@ type ArchiveStoreInitOpts = ArchiveStoreOpts & {dbName: string; anchorState: {fi
27
29
 
28
30
  export enum ArchiveStoreTask {
29
31
  ArchiveBlocks = "archive_blocks",
32
+ ArchivePayloads = "archive_payloads",
30
33
  PruneHistory = "prune_history",
31
34
  OnFinalizedCheckpoint = "on_finalized_checkpoint",
32
35
  MaybeArchiveState = "maybe_archive_state",
@@ -189,6 +192,7 @@ export class ArchiveStore {
189
192
  private processFinalizedCheckpoint = async (finalized: CheckpointWithHex): Promise<void> => {
190
193
  try {
191
194
  const finalizedEpoch = finalized.epoch;
195
+ const finalizedFork = this.chain.config.getForkSeqAtEpoch(finalizedEpoch);
192
196
  this.logger.verbose("Start processing finalized checkpoint", {epoch: finalizedEpoch, rootHex: finalized.rootHex});
193
197
 
194
198
  let timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
@@ -206,6 +210,12 @@ export class ArchiveStore {
206
210
  );
207
211
  timer?.({source: ArchiveStoreTask.ArchiveBlocks});
208
212
 
213
+ if (finalizedFork >= ForkSeq.gloas) {
214
+ timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
215
+ await archiveExecutionPayloadEnvelopes(this.chain, finalized);
216
+ timer?.({source: ArchiveStoreTask.ArchivePayloads});
217
+ }
218
+
209
219
  if (this.opts.pruneHistory) {
210
220
  timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
211
221
  await pruneHistory(
@@ -1,10 +1,10 @@
1
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
2
1
  import {BeaconConfig} from "@lodestar/config";
3
2
  import {
4
3
  BeaconStateAllForks,
5
4
  CachedBeaconStateAllForks,
6
5
  DataAvailabilityStatus,
7
6
  ExecutionPayloadStatus,
7
+ PubkeyCache,
8
8
  createCachedBeaconState,
9
9
  stateTransition,
10
10
  } from "@lodestar/state-transition";
@@ -15,16 +15,16 @@ import {HistoricalStateRegenMetrics} from "./metrics.js";
15
15
  import {RegenErrorType} from "./types.js";
16
16
 
17
17
  /**
18
- * Populate a PubkeyIndexMap with any new entries based on a BeaconState
18
+ * Populate a PubkeyCache with any new entries based on a BeaconState
19
19
  */
20
- export function syncPubkeyCache(state: BeaconStateAllForks, pubkey2index: PubkeyIndexMap): void {
20
+ export function syncPubkeyCache(state: BeaconStateAllForks, pubkeyCache: PubkeyCache): void {
21
21
  // Get the validators sub tree once for all the loop
22
22
  const validators = state.validators;
23
23
 
24
24
  const newCount = state.validators.length;
25
- for (let i = pubkey2index.size; i < newCount; i++) {
25
+ for (let i = pubkeyCache.size; i < newCount; i++) {
26
26
  const pubkey = validators.getReadonly(i).pubkey;
27
- pubkey2index.set(pubkey, i);
27
+ pubkeyCache.set(i, pubkey);
28
28
  }
29
29
  }
30
30
 
@@ -35,7 +35,7 @@ export async function getNearestState(
35
35
  slot: number,
36
36
  config: BeaconConfig,
37
37
  db: IBeaconDb,
38
- pubkey2index: PubkeyIndexMap
38
+ pubkeyCache: PubkeyCache
39
39
  ): Promise<CachedBeaconStateAllForks> {
40
40
  const stateBytesArr = await db.stateArchive.binaries({limit: 1, lte: slot, reverse: true});
41
41
  if (!stateBytesArr.length) {
@@ -44,14 +44,13 @@ export async function getNearestState(
44
44
 
45
45
  const stateBytes = stateBytesArr[0];
46
46
  const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
47
- syncPubkeyCache(state, pubkey2index);
47
+ syncPubkeyCache(state, pubkeyCache);
48
48
 
49
49
  return createCachedBeaconState(
50
50
  state,
51
51
  {
52
52
  config,
53
- pubkey2index,
54
- index2pubkey: [],
53
+ pubkeyCache,
55
54
  },
56
55
  {
57
56
  skipSyncPubkeys: true,
@@ -66,13 +65,13 @@ export async function getHistoricalState(
66
65
  slot: number,
67
66
  config: BeaconConfig,
68
67
  db: IBeaconDb,
69
- pubkey2index: PubkeyIndexMap,
68
+ pubkeyCache: PubkeyCache,
70
69
  metrics?: HistoricalStateRegenMetrics
71
70
  ): Promise<Uint8Array> {
72
71
  const regenTimer = metrics?.regenTime.startTimer();
73
72
 
74
73
  const loadStateTimer = metrics?.loadStateTime.startTimer();
75
- let state = await getNearestState(slot, config, db, pubkey2index).catch((e) => {
74
+ let state = await getNearestState(slot, config, db, pubkeyCache).catch((e) => {
76
75
  metrics?.regenErrorCount.inc({reason: RegenErrorType.loadState});
77
76
  throw e;
78
77
  });
@@ -1,9 +1,9 @@
1
1
  import worker from "node:worker_threads";
2
- import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
3
2
  import {Transfer, expose} from "@chainsafe/threads/worker";
4
3
  import {chainConfigFromJson, createBeaconConfig} from "@lodestar/config";
5
4
  import {LevelDbController} from "@lodestar/db/controller/level";
6
5
  import {getNodeLogger} from "@lodestar/logger/node";
6
+ import {createPubkeyCache} from "@lodestar/state-transition";
7
7
  import {BeaconDb} from "../../../db/index.js";
8
8
  import {RegistryMetricCreator, collectNodeJSMetrics} from "../../../metrics/index.js";
9
9
  import {JobFnQueue} from "../../../util/queue/fnQueue.js";
@@ -52,7 +52,7 @@ const queue = new JobFnQueue(
52
52
  queueMetrics
53
53
  );
54
54
 
55
- const pubkey2index = new PubkeyIndexMap();
55
+ const pubkeyCache = createPubkeyCache();
56
56
 
57
57
  const api: HistoricalStateWorkerApi = {
58
58
  async close() {
@@ -65,7 +65,7 @@ const api: HistoricalStateWorkerApi = {
65
65
  historicalStateRegenMetrics?.regenRequestCount.inc();
66
66
 
67
67
  const stateBytes = await queue.push<Uint8Array>(() =>
68
- getHistoricalState(slot, config, db, pubkey2index, historicalStateRegenMetrics)
68
+ getHistoricalState(slot, config, db, pubkeyCache, historicalStateRegenMetrics)
69
69
  );
70
70
  const result = Transfer(stateBytes, [stateBytes.buffer]) as unknown as Uint8Array;
71
71
 
@@ -0,0 +1,15 @@
1
+ import {CheckpointWithHex} from "@lodestar/fork-choice";
2
+ import {IBeaconChain} from "../../interface.js";
3
+
4
+ /**
5
+ * Archives execution payload envelopes from hot DB to archive DB after finalization.
6
+ */
7
+ export async function archiveExecutionPayloadEnvelopes(
8
+ chain: IBeaconChain,
9
+ _finalized: CheckpointWithHex
10
+ ): Promise<void> {
11
+ const finalizedBlock = chain.forkChoice.getFinalizedBlock();
12
+ if (!finalizedBlock) return;
13
+
14
+ // TODO GLOAS: Implement payload envelope archival after epbs fork choice changes are merged
15
+ }
@@ -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;