@lodestar/beacon-node 1.41.0 → 1.42.0-dev.4118b5b440

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 (252) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +35 -16
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/utils.d.ts +2 -2
  5. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  6. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  7. package/lib/api/impl/validator/index.d.ts.map +1 -1
  8. package/lib/api/impl/validator/index.js +6 -2
  9. package/lib/api/impl/validator/index.js.map +1 -1
  10. package/lib/chain/archiveStore/archiveStore.d.ts +0 -1
  11. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  12. package/lib/chain/archiveStore/archiveStore.js +0 -9
  13. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  14. package/lib/chain/archiveStore/interface.d.ts +4 -4
  15. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  16. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
  17. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +4 -1
  19. package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
  20. package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
  21. package/lib/chain/archiveStore/utils/archiveBlocks.js +38 -0
  22. package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
  23. package/lib/chain/blocks/blockInput/types.d.ts +4 -3
  24. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  25. package/lib/chain/blocks/blockInput/types.js +1 -0
  26. package/lib/chain/blocks/blockInput/types.js.map +1 -1
  27. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  28. package/lib/chain/blocks/importBlock.js +29 -9
  29. package/lib/chain/blocks/importBlock.js.map +1 -1
  30. package/lib/chain/blocks/importExecutionPayload.d.ts +48 -0
  31. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -0
  32. package/lib/chain/blocks/importExecutionPayload.js +159 -0
  33. package/lib/chain/blocks/importExecutionPayload.js.map +1 -0
  34. package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts +3 -0
  35. package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts.map +1 -0
  36. package/lib/chain/blocks/payloadEnvelopeInput/index.js +3 -0
  37. package/lib/chain/blocks/payloadEnvelopeInput/index.js.map +1 -0
  38. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +80 -0
  39. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -0
  40. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +248 -0
  41. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -0
  42. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +29 -0
  43. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -0
  44. package/lib/chain/blocks/payloadEnvelopeInput/types.js +11 -0
  45. package/lib/chain/blocks/payloadEnvelopeInput/types.js.map +1 -0
  46. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +15 -0
  47. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -0
  48. package/lib/chain/blocks/payloadEnvelopeProcessor.js +46 -0
  49. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -0
  50. package/lib/chain/blocks/types.d.ts +7 -0
  51. package/lib/chain/blocks/types.d.ts.map +1 -1
  52. package/lib/chain/blocks/verifyBlocksSignatures.js +1 -1
  53. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  54. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +12 -0
  55. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -0
  56. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +40 -0
  57. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -0
  58. package/lib/chain/chain.d.ts +10 -5
  59. package/lib/chain/chain.d.ts.map +1 -1
  60. package/lib/chain/chain.js +44 -10
  61. package/lib/chain/chain.js.map +1 -1
  62. package/lib/chain/errors/executionPayloadEnvelope.d.ts +12 -2
  63. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  64. package/lib/chain/errors/executionPayloadEnvelope.js +3 -1
  65. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  66. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  67. package/lib/chain/forkChoice/index.js +0 -10
  68. package/lib/chain/forkChoice/index.js.map +1 -1
  69. package/lib/chain/interface.d.ts +8 -5
  70. package/lib/chain/interface.d.ts.map +1 -1
  71. package/lib/chain/opPools/utils.js +1 -1
  72. package/lib/chain/opPools/utils.js.map +1 -1
  73. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  74. package/lib/chain/prepareNextSlot.js +6 -2
  75. package/lib/chain/prepareNextSlot.js.map +1 -1
  76. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  77. package/lib/chain/produceBlock/computeNewStateRoot.js +6 -1
  78. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  79. package/lib/chain/produceBlock/produceBlockBody.js +1 -1
  80. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  81. package/lib/chain/regen/errors.d.ts +11 -1
  82. package/lib/chain/regen/errors.d.ts.map +1 -1
  83. package/lib/chain/regen/errors.js +2 -0
  84. package/lib/chain/regen/errors.js.map +1 -1
  85. package/lib/chain/regen/interface.d.ts +14 -6
  86. package/lib/chain/regen/interface.d.ts.map +1 -1
  87. package/lib/chain/regen/interface.js +2 -0
  88. package/lib/chain/regen/interface.js.map +1 -1
  89. package/lib/chain/regen/queued.d.ts +11 -6
  90. package/lib/chain/regen/queued.d.ts.map +1 -1
  91. package/lib/chain/regen/queued.js +40 -8
  92. package/lib/chain/regen/queued.js.map +1 -1
  93. package/lib/chain/regen/regen.d.ts +5 -0
  94. package/lib/chain/regen/regen.d.ts.map +1 -1
  95. package/lib/chain/regen/regen.js +33 -6
  96. package/lib/chain/regen/regen.js.map +1 -1
  97. package/lib/chain/seenCache/index.d.ts +1 -1
  98. package/lib/chain/seenCache/index.d.ts.map +1 -1
  99. package/lib/chain/seenCache/index.js +1 -1
  100. package/lib/chain/seenCache/index.js.map +1 -1
  101. package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
  102. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  103. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +38 -0
  104. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -0
  105. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +76 -0
  106. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -0
  107. package/lib/chain/stateCache/datastore/db.d.ts +4 -5
  108. package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
  109. package/lib/chain/stateCache/datastore/db.js +32 -10
  110. package/lib/chain/stateCache/datastore/db.js.map +1 -1
  111. package/lib/chain/stateCache/datastore/file.d.ts +1 -1
  112. package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
  113. package/lib/chain/stateCache/datastore/file.js +5 -5
  114. package/lib/chain/stateCache/datastore/file.js.map +1 -1
  115. package/lib/chain/stateCache/datastore/types.d.ts +1 -1
  116. package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
  117. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +7 -4
  118. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  119. package/lib/chain/stateCache/fifoBlockStateCache.js +8 -3
  120. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  121. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +33 -14
  122. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  123. package/lib/chain/stateCache/persistentCheckpointsCache.js +217 -119
  124. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  125. package/lib/chain/stateCache/types.d.ts +15 -8
  126. package/lib/chain/stateCache/types.d.ts.map +1 -1
  127. package/lib/chain/stateCache/types.js.map +1 -1
  128. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  129. package/lib/chain/validation/executionPayloadEnvelope.js +30 -19
  130. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  131. package/lib/chain/validation/lightClientFinalityUpdate.js +1 -1
  132. package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
  133. package/lib/chain/validation/lightClientOptimisticUpdate.js +1 -1
  134. package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
  135. package/lib/chain/validation/syncCommittee.d.ts +2 -2
  136. package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
  137. package/lib/chain/validation/syncCommittee.js +12 -11
  138. package/lib/chain/validation/syncCommittee.js.map +1 -1
  139. package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
  140. package/lib/chain/validation/voluntaryExit.js +2 -2
  141. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  142. package/lib/chain/validatorMonitor.d.ts +2 -1
  143. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  144. package/lib/chain/validatorMonitor.js +4 -1
  145. package/lib/chain/validatorMonitor.js.map +1 -1
  146. package/lib/execution/engine/interface.d.ts +2 -2
  147. package/lib/metrics/metrics/lodestar.d.ts +40 -4
  148. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  149. package/lib/metrics/metrics/lodestar.js +93 -15
  150. package/lib/metrics/metrics/lodestar.js.map +1 -1
  151. package/lib/network/gossip/encoding.d.ts.map +1 -1
  152. package/lib/network/gossip/encoding.js +15 -0
  153. package/lib/network/gossip/encoding.js.map +1 -1
  154. package/lib/network/interface.d.ts +1 -1
  155. package/lib/network/interface.d.ts.map +1 -1
  156. package/lib/network/network.d.ts +1 -1
  157. package/lib/network/network.d.ts.map +1 -1
  158. package/lib/network/network.js +4 -4
  159. package/lib/network/network.js.map +1 -1
  160. package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
  161. package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
  162. package/lib/network/processor/extractSlotRootFns.js +15 -5
  163. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  164. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  165. package/lib/network/processor/gossipHandlers.js +39 -9
  166. package/lib/network/processor/gossipHandlers.js.map +1 -1
  167. package/lib/network/processor/index.d.ts +12 -7
  168. package/lib/network/processor/index.d.ts.map +1 -1
  169. package/lib/network/processor/index.js +99 -78
  170. package/lib/network/processor/index.js.map +1 -1
  171. package/lib/network/reqresp/ReqRespBeaconNode.d.ts +1 -1
  172. package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
  173. package/lib/sync/backfill/backfill.d.ts +1 -1
  174. package/lib/sync/backfill/backfill.js +1 -1
  175. package/lib/sync/constants.d.ts +1 -1
  176. package/lib/sync/constants.js +1 -1
  177. package/lib/sync/unknownBlock.d.ts +3 -9
  178. package/lib/sync/unknownBlock.d.ts.map +1 -1
  179. package/lib/sync/unknownBlock.js +8 -41
  180. package/lib/sync/unknownBlock.js.map +1 -1
  181. package/lib/util/sszBytes.d.ts +4 -1
  182. package/lib/util/sszBytes.d.ts.map +1 -1
  183. package/lib/util/sszBytes.js +69 -12
  184. package/lib/util/sszBytes.js.map +1 -1
  185. package/package.json +15 -15
  186. package/src/api/impl/beacon/blocks/index.ts +36 -17
  187. package/src/api/impl/beacon/state/utils.ts +2 -2
  188. package/src/api/impl/validator/index.ts +8 -4
  189. package/src/chain/archiveStore/archiveStore.ts +0 -10
  190. package/src/chain/archiveStore/interface.ts +4 -4
  191. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +8 -5
  192. package/src/chain/archiveStore/utils/archiveBlocks.ts +59 -1
  193. package/src/chain/blocks/blockInput/types.ts +4 -3
  194. package/src/chain/blocks/importBlock.ts +47 -8
  195. package/src/chain/blocks/importExecutionPayload.ts +241 -0
  196. package/src/chain/blocks/payloadEnvelopeInput/index.ts +2 -0
  197. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +336 -0
  198. package/src/chain/blocks/payloadEnvelopeInput/types.ts +33 -0
  199. package/src/chain/blocks/payloadEnvelopeProcessor.ts +61 -0
  200. package/src/chain/blocks/types.ts +8 -0
  201. package/src/chain/blocks/verifyBlocksSignatures.ts +1 -1
  202. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +55 -0
  203. package/src/chain/chain.ts +60 -15
  204. package/src/chain/errors/executionPayloadEnvelope.ts +6 -2
  205. package/src/chain/forkChoice/index.ts +0 -10
  206. package/src/chain/interface.ts +8 -5
  207. package/src/chain/opPools/utils.ts +1 -1
  208. package/src/chain/prepareNextSlot.ts +6 -2
  209. package/src/chain/produceBlock/computeNewStateRoot.ts +6 -1
  210. package/src/chain/produceBlock/produceBlockBody.ts +1 -1
  211. package/src/chain/regen/errors.ts +6 -1
  212. package/src/chain/regen/interface.ts +14 -6
  213. package/src/chain/regen/queued.ts +48 -12
  214. package/src/chain/regen/regen.ts +37 -7
  215. package/src/chain/seenCache/index.ts +1 -1
  216. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
  217. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +106 -0
  218. package/src/chain/stateCache/datastore/db.ts +33 -10
  219. package/src/chain/stateCache/datastore/file.ts +6 -5
  220. package/src/chain/stateCache/datastore/types.ts +3 -2
  221. package/src/chain/stateCache/fifoBlockStateCache.ts +10 -4
  222. package/src/chain/stateCache/persistentCheckpointsCache.ts +248 -139
  223. package/src/chain/stateCache/types.ts +18 -8
  224. package/src/chain/validation/executionPayloadEnvelope.ts +38 -25
  225. package/src/chain/validation/lightClientFinalityUpdate.ts +1 -1
  226. package/src/chain/validation/lightClientOptimisticUpdate.ts +1 -1
  227. package/src/chain/validation/syncCommittee.ts +15 -14
  228. package/src/chain/validation/voluntaryExit.ts +2 -1
  229. package/src/chain/validatorMonitor.ts +11 -1
  230. package/src/execution/engine/interface.ts +2 -2
  231. package/src/metrics/metrics/lodestar.ts +100 -19
  232. package/src/network/gossip/encoding.ts +16 -0
  233. package/src/network/interface.ts +1 -1
  234. package/src/network/network.ts +4 -4
  235. package/src/network/processor/extractSlotRootFns.ts +19 -6
  236. package/src/network/processor/gossipHandlers.ts +45 -8
  237. package/src/network/processor/index.ts +110 -89
  238. package/src/network/reqresp/ReqRespBeaconNode.ts +1 -1
  239. package/src/sync/backfill/backfill.ts +1 -1
  240. package/src/sync/constants.ts +1 -1
  241. package/src/sync/unknownBlock.ts +10 -50
  242. package/src/util/sszBytes.ts +90 -10
  243. package/lib/chain/archiveStore/utils/archivePayloads.d.ts +0 -7
  244. package/lib/chain/archiveStore/utils/archivePayloads.d.ts.map +0 -1
  245. package/lib/chain/archiveStore/utils/archivePayloads.js +0 -10
  246. package/lib/chain/archiveStore/utils/archivePayloads.js.map +0 -1
  247. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts +0 -15
  248. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts.map +0 -1
  249. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js +0 -28
  250. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js.map +0 -1
  251. package/src/chain/archiveStore/utils/archivePayloads.ts +0 -15
  252. package/src/chain/seenCache/seenExecutionPayloadEnvelope.ts +0 -34
@@ -3,11 +3,12 @@ import {PrivateKey} from "@libp2p/interface";
3
3
  import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
4
4
  import {BeaconConfig} from "@lodestar/config";
5
5
  import {
6
- CheckpointWithHex,
7
6
  CheckpointWithPayloadStatus,
8
7
  IForkChoice,
8
+ PayloadStatus,
9
9
  ProtoBlock,
10
10
  UpdateHeadOpt,
11
+ getCheckpointPayloadStatus,
11
12
  } from "@lodestar/fork-choice";
12
13
  import {LoggerNode} from "@lodestar/logger/node";
13
14
  import {
@@ -83,7 +84,10 @@ import {CheckpointBalancesCache} from "./balancesCache.js";
83
84
  import {BeaconProposerCache} from "./beaconProposerCache.js";
84
85
  import {IBlockInput, isBlockInputBlobs, isBlockInputColumns} from "./blocks/blockInput/index.js";
85
86
  import {BlockProcessor, ImportBlockOpts} from "./blocks/index.js";
87
+ import {PayloadEnvelopeProcessor} from "./blocks/payloadEnvelopeProcessor.js";
88
+ import {ImportPayloadOpts} from "./blocks/types.js";
86
89
  import {persistBlockInput} from "./blocks/writeBlockInputToDb.js";
90
+ import {persistPayloadEnvelopeInput} from "./blocks/writePayloadEnvelopeInputToDb.js";
87
91
  import {BlsMultiThreadWorkerPool, BlsSingleThreadVerifier, IBlsVerifier} from "./bls/index.js";
88
92
  import {ColumnReconstructionTracker} from "./ColumnReconstructionTracker.js";
89
93
  import {ChainEvent, ChainEventEmitter} from "./emitter.js";
@@ -108,13 +112,14 @@ import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produ
108
112
  import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js";
109
113
  import {ReprocessController} from "./reprocess.js";
110
114
  import {
115
+ PayloadEnvelopeInput,
111
116
  SeenAggregators,
112
117
  SeenAttesters,
113
118
  SeenBlockProposers,
114
119
  SeenContributionAndProof,
115
120
  SeenExecutionPayloadBids,
116
- SeenExecutionPayloadEnvelopes,
117
121
  SeenPayloadAttesters,
122
+ SeenPayloadEnvelopeInput,
118
123
  SeenSyncCommitteeMessages,
119
124
  } from "./seenCache/index.js";
120
125
  import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
@@ -126,7 +131,7 @@ import {DbCPStateDatastore, checkpointToDatastoreKey} from "./stateCache/datasto
126
131
  import {FileCPStateDatastore} from "./stateCache/datastore/file.js";
127
132
  import {CPStateDatastore} from "./stateCache/datastore/types.js";
128
133
  import {FIFOBlockStateCache} from "./stateCache/fifoBlockStateCache.js";
129
- import {PersistentCheckpointStateCache} from "./stateCache/persistentCheckpointsCache.js";
134
+ import {PersistentCheckpointStateCache, fcCheckpointToHexPayload} from "./stateCache/persistentCheckpointsCache.js";
130
135
  import {CheckpointStateCache} from "./stateCache/types.js";
131
136
  import {ValidatorMonitor} from "./validatorMonitor.js";
132
137
 
@@ -147,6 +152,13 @@ const DEFAULT_MAX_CACHED_PRODUCED_RESULTS = 4;
147
152
  */
148
153
  const DEFAULT_MAX_PENDING_UNFINALIZED_BLOCK_WRITES = 16;
149
154
 
155
+ /**
156
+ * The maximum number of pending unfinalized payload envelope writes to the database before backpressure is applied.
157
+ * Payload envelope write queue entries hold references to payload inputs (including columns),
158
+ * keeping them in memory. Keep moderate to avoid OOM during sync.
159
+ */
160
+ const DEFAULT_MAX_PENDING_UNFINALIZED_PAYLOAD_ENVELOPE_WRITES = 16;
161
+
150
162
  export class BeaconChain implements IBeaconChain {
151
163
  readonly genesisTime: UintNum64;
152
164
  readonly genesisValidatorsRoot: Root;
@@ -171,6 +183,7 @@ export class BeaconChain implements IBeaconChain {
171
183
  readonly reprocessController: ReprocessController;
172
184
  readonly archiveStore: ArchiveStore;
173
185
  readonly unfinalizedBlockWrites: JobItemQueue<[IBlockInput], void>;
186
+ readonly unfinalizedPayloadEnvelopeWrites: JobItemQueue<[PayloadEnvelopeInput], void>;
174
187
 
175
188
  // Ops pool
176
189
  readonly attestationPool: AttestationPool;
@@ -186,13 +199,13 @@ export class BeaconChain implements IBeaconChain {
186
199
  readonly seenAggregators = new SeenAggregators();
187
200
  readonly seenPayloadAttesters = new SeenPayloadAttesters();
188
201
  readonly seenAggregatedAttestations: SeenAggregatedAttestations;
189
- readonly seenExecutionPayloadEnvelopes = new SeenExecutionPayloadEnvelopes();
190
202
  readonly seenExecutionPayloadBids = new SeenExecutionPayloadBids();
191
203
  readonly seenBlockProposers = new SeenBlockProposers();
192
204
  readonly seenSyncCommitteeMessages = new SeenSyncCommitteeMessages();
193
205
  readonly seenContributionAndProof: SeenContributionAndProof;
194
206
  readonly seenAttestationDatas: SeenAttestationDatas;
195
207
  readonly seenBlockInputCache: SeenBlockInput;
208
+ readonly seenPayloadEnvelopeInputCache: SeenPayloadEnvelopeInput;
196
209
  // Seen cache for liveness checks
197
210
  readonly seenBlockAttesters = new SeenBlockAttesters();
198
211
 
@@ -220,6 +233,7 @@ export class BeaconChain implements IBeaconChain {
220
233
  readonly opts: IChainOptions;
221
234
 
222
235
  protected readonly blockProcessor: BlockProcessor;
236
+ protected readonly payloadEnvelopeProcessor: PayloadEnvelopeProcessor;
223
237
  protected readonly db: IBeaconDb;
224
238
  // this is only available if nHistoricalStates is enabled
225
239
  private readonly cpStateDatastore?: CPStateDatastore;
@@ -333,6 +347,13 @@ export class BeaconChain implements IBeaconChain {
333
347
  metrics,
334
348
  logger,
335
349
  });
350
+ this.seenPayloadEnvelopeInputCache = new SeenPayloadEnvelopeInput({
351
+ chainEvents: emitter,
352
+ signal,
353
+ serializedCache: this.serializedCache,
354
+ metrics,
355
+ logger,
356
+ });
336
357
 
337
358
  this._earliestAvailableSlot = anchorState.slot;
338
359
 
@@ -375,7 +396,8 @@ export class BeaconChain implements IBeaconChain {
375
396
  const {checkpoint} = computeAnchorCheckpoint(config, anchorState);
376
397
  blockStateCache.add(anchorState);
377
398
  blockStateCache.setHeadState(anchorState);
378
- checkpointStateCache.add(checkpoint, anchorState);
399
+ const payloadPresent = getCheckpointPayloadStatus(anchorState, checkpoint.epoch) === PayloadStatus.FULL;
400
+ checkpointStateCache.add(checkpoint, anchorState, payloadPresent);
379
401
 
380
402
  const forkChoice = initializeForkChoice(
381
403
  config,
@@ -409,6 +431,7 @@ export class BeaconChain implements IBeaconChain {
409
431
  this.reprocessController = new ReprocessController(this.metrics);
410
432
 
411
433
  this.blockProcessor = new BlockProcessor(this, metrics, opts, signal);
434
+ this.payloadEnvelopeProcessor = new PayloadEnvelopeProcessor(this, metrics, signal);
412
435
 
413
436
  this.forkChoice = forkChoice;
414
437
  this.clock = clock;
@@ -445,6 +468,15 @@ export class BeaconChain implements IBeaconChain {
445
468
  metrics?.unfinalizedBlockWritesQueue
446
469
  );
447
470
 
471
+ this.unfinalizedPayloadEnvelopeWrites = new JobItemQueue(
472
+ persistPayloadEnvelopeInput.bind(this),
473
+ {
474
+ maxLength: DEFAULT_MAX_PENDING_UNFINALIZED_PAYLOAD_ENVELOPE_WRITES,
475
+ signal,
476
+ },
477
+ metrics?.unfinalizedPayloadEnvelopeWritesQueue
478
+ );
479
+
448
480
  // always run PrepareNextSlotScheduler except for fork_choice spec tests
449
481
  if (!opts?.disablePrepareNextSlot) {
450
482
  new PrepareNextSlotScheduler(this, this.config, metrics, this.logger, signal);
@@ -475,6 +507,7 @@ export class BeaconChain implements IBeaconChain {
475
507
  // we can abort any ongoing unfinalized block writes.
476
508
  // TODO: persist fork choice to disk and allow unfinalized block writes to complete.
477
509
  this.unfinalizedBlockWrites.dropAllJobs();
510
+ this.unfinalizedPayloadEnvelopeWrites.dropAllJobs();
478
511
 
479
512
  this.abortController.abort();
480
513
  }
@@ -648,15 +681,18 @@ export class BeaconChain implements IBeaconChain {
648
681
  return this.cpStateDatastore.readLatestSafe();
649
682
  }
650
683
 
651
- const persistedKey = checkpointToDatastoreKey(checkpoint);
684
+ // TODO GLOAS: Need to revisit the design of this api. Currently we just retrieve FULL state of the checkpoint for backwards compatibility.
685
+ // because pre-gloas we always store FULL checkpoint state.
686
+ const persistedKey = checkpointToDatastoreKey(checkpoint, true);
652
687
  return this.cpStateDatastore.read(persistedKey);
653
688
  }
654
689
 
655
690
  getStateByCheckpoint(
656
- checkpoint: CheckpointWithHex
691
+ checkpoint: CheckpointWithPayloadStatus
657
692
  ): {state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null {
658
693
  // finalized or justified checkpoint states maynot be available with PersistentCheckpointStateCache, use getCheckpointStateOrBytes() api to get Uint8Array
659
- const cachedStateCtx = this.regen.getCheckpointStateSync(checkpoint);
694
+ const checkpointHexPayload = fcCheckpointToHexPayload(checkpoint);
695
+ const cachedStateCtx = this.regen.getCheckpointStateSync(checkpointHexPayload);
660
696
  if (cachedStateCtx) {
661
697
  const block = this.forkChoice.getBlockDefaultStatus(cachedStateCtx.latestBlockHeader.hashTreeRoot());
662
698
  const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
@@ -671,9 +707,10 @@ export class BeaconChain implements IBeaconChain {
671
707
  }
672
708
 
673
709
  async getStateOrBytesByCheckpoint(
674
- checkpoint: CheckpointWithHex
710
+ checkpoint: CheckpointWithPayloadStatus
675
711
  ): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
676
- const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpoint);
712
+ const checkpointHexPayload = fcCheckpointToHexPayload(checkpoint);
713
+ const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpointHexPayload);
677
714
  if (cachedStateCtx) {
678
715
  const block = this.forkChoice.getBlockDefaultStatus(checkpoint.root);
679
716
  const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
@@ -1004,6 +1041,10 @@ export class BeaconChain implements IBeaconChain {
1004
1041
  return this.blockProcessor.processBlocksJob(blocks, opts);
1005
1042
  }
1006
1043
 
1044
+ async processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void> {
1045
+ return this.payloadEnvelopeProcessor.processPayloadEnvelopeJob(payloadInput, opts);
1046
+ }
1047
+
1007
1048
  getStatus(): Status {
1008
1049
  const head = this.forkChoice.getHead();
1009
1050
  const finalizedCheckpoint = this.forkChoice.getFinalizedCheckpoint();
@@ -1236,7 +1277,8 @@ export class BeaconChain implements IBeaconChain {
1236
1277
  checkpoint: CheckpointWithPayloadStatus,
1237
1278
  blockState: CachedBeaconStateAllForks
1238
1279
  ): {state: CachedBeaconStateAllForks; stateId: string; shouldWarn: boolean} {
1239
- const state = this.regen.getCheckpointStateSync(checkpoint);
1280
+ const checkpointHexPayload = fcCheckpointToHexPayload(checkpoint);
1281
+ const state = this.regen.getCheckpointStateSync(checkpointHexPayload);
1240
1282
  if (state) {
1241
1283
  return {state, stateId: "checkpoint_state", shouldWarn: false};
1242
1284
  }
@@ -1363,6 +1405,10 @@ export class BeaconChain implements IBeaconChain {
1363
1405
  private onClockEpoch(epoch: Epoch): void {
1364
1406
  this.metrics?.clockEpoch.set(epoch);
1365
1407
 
1408
+ if (epoch === this.config.GLOAS_FORK_EPOCH) {
1409
+ this.regen.upgradeForGloas(epoch);
1410
+ }
1411
+
1366
1412
  this.seenAttesters.prune(epoch);
1367
1413
  this.seenAggregators.prune(epoch);
1368
1414
  this.seenPayloadAttesters.prune(epoch);
@@ -1376,7 +1422,7 @@ export class BeaconChain implements IBeaconChain {
1376
1422
  this.seenContributionAndProof.prune(head.slot);
1377
1423
  }
1378
1424
 
1379
- private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithHex): void {
1425
+ private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithPayloadStatus): void {
1380
1426
  this.logger.verbose("Fork choice justified", {epoch: cp.epoch, root: cp.rootHex});
1381
1427
  }
1382
1428
 
@@ -1387,11 +1433,10 @@ export class BeaconChain implements IBeaconChain {
1387
1433
  });
1388
1434
  }
1389
1435
 
1390
- private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithHex): Promise<void> {
1436
+ private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithPayloadStatus): Promise<void> {
1391
1437
  this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
1392
1438
  const finalizedSlot = computeStartSlotAtEpoch(cp.epoch);
1393
1439
  this.seenBlockProposers.prune(finalizedSlot);
1394
- this.seenExecutionPayloadEnvelopes.prune(finalizedSlot);
1395
1440
 
1396
1441
  // Update validator custody to account for effective balance changes
1397
1442
  await this.updateValidatorsCustodyRequirement(cp);
@@ -1429,7 +1474,7 @@ export class BeaconChain implements IBeaconChain {
1429
1474
  }
1430
1475
  }
1431
1476
 
1432
- private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithHex): Promise<void> {
1477
+ private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithPayloadStatus): Promise<void> {
1433
1478
  if (this.custodyConfig.targetCustodyGroupCount === this.config.NUMBER_OF_CUSTODY_GROUPS) {
1434
1479
  // Custody requirements can only be increased, we can disable dynamic custody updates
1435
1480
  // if the node already maintains custody of all custody groups in case it is configured
@@ -4,17 +4,21 @@ import {GossipActionError} from "./gossipValidation.js";
4
4
  export enum ExecutionPayloadEnvelopeErrorCode {
5
5
  BELONG_TO_FINALIZED_BLOCK = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BELONG_TO_FINALIZED_BLOCK",
6
6
  BLOCK_ROOT_UNKNOWN = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_ROOT_UNKNOWN",
7
+ PARENT_UNKNOWN = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_PARENT_UNKNOWN",
8
+ UNKNOWN_BLOCK_STATE = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_UNKNOWN_BLOCK_STATE",
7
9
  ENVELOPE_ALREADY_KNOWN = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_ALREADY_KNOWN",
8
10
  INVALID_BLOCK = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_BLOCK",
9
11
  SLOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_SLOT_MISMATCH",
10
12
  BUILDER_INDEX_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BUILDER_INDEX_MISMATCH",
11
13
  BLOCK_HASH_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_HASH_MISMATCH",
12
14
  INVALID_SIGNATURE = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_SIGNATURE",
13
- CACHE_FAIL = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_CACHE_FAIL",
15
+ PAYLOAD_ENVELOPE_INPUT_MISSING = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_PAYLOAD_ENVELOPE_INPUT_MISSING",
14
16
  }
15
17
  export type ExecutionPayloadEnvelopeErrorType =
16
18
  | {code: ExecutionPayloadEnvelopeErrorCode.BELONG_TO_FINALIZED_BLOCK; envelopeSlot: Slot; finalizedSlot: Slot}
17
19
  | {code: ExecutionPayloadEnvelopeErrorCode.BLOCK_ROOT_UNKNOWN; blockRoot: RootHex}
20
+ | {code: ExecutionPayloadEnvelopeErrorCode.PARENT_UNKNOWN; parentRoot: RootHex; slot: Slot}
21
+ | {code: ExecutionPayloadEnvelopeErrorCode.UNKNOWN_BLOCK_STATE; blockRoot: RootHex; slot: Slot}
18
22
  | {
19
23
  code: ExecutionPayloadEnvelopeErrorCode.ENVELOPE_ALREADY_KNOWN;
20
24
  blockRoot: RootHex;
@@ -33,6 +37,6 @@ export type ExecutionPayloadEnvelopeErrorType =
33
37
  bidBlockHash: RootHex | null;
34
38
  }
35
39
  | {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
36
- | {code: ExecutionPayloadEnvelopeErrorCode.CACHE_FAIL; blockRoot: RootHex};
40
+ | {code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; blockRoot: RootHex};
37
41
 
38
42
  export class ExecutionPayloadEnvelopeError extends GossipActionError<ExecutionPayloadEnvelopeErrorType> {}
@@ -158,10 +158,6 @@ export function initializeForkChoiceFromFinalizedState(
158
158
 
159
159
  dataAvailabilityStatus: DataAvailabilityStatus.PreData,
160
160
  payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
161
- builderIndex: isForkPostGloas ? (state as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex : null,
162
- blockHashFromBid: isForkPostGloas
163
- ? toRootHex((state as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash)
164
- : null,
165
161
  parentBlockHash: isForkPostGloas ? toRootHex((state as CachedBeaconStateGloas).latestBlockHash) : null,
166
162
  },
167
163
  currentSlot
@@ -255,12 +251,6 @@ export function initializeForkChoiceFromUnfinalizedState(
255
251
 
256
252
  dataAvailabilityStatus: DataAvailabilityStatus.PreData,
257
253
  payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL, // TODO GLOAS: Post-gloas how do we know if the checkpoint payload is FULL or EMPTY?
258
- builderIndex: isForkPostGloas
259
- ? (unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex
260
- : null,
261
- blockHashFromBid: isForkPostGloas
262
- ? toRootHex((unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash)
263
- : null,
264
254
  parentBlockHash: isForkPostGloas ? toRootHex((unfinalizedState as CachedBeaconStateGloas).latestBlockHash) : null,
265
255
  };
266
256
 
@@ -1,6 +1,6 @@
1
1
  import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
2
2
  import {BeaconConfig} from "@lodestar/config";
3
- import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
3
+ import {CheckpointWithHex, CheckpointWithPayloadStatus, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
4
4
  import {BeaconStateAllForks, CachedBeaconStateAllForks, EpochShuffling, PubkeyCache} from "@lodestar/state-transition";
5
5
  import {
6
6
  BeaconBlock,
@@ -32,7 +32,7 @@ import {IArchiveStore} from "./archiveStore/interface.js";
32
32
  import {CheckpointBalancesCache} from "./balancesCache.js";
33
33
  import {BeaconProposerCache, ProposerPreparationData} from "./beaconProposerCache.js";
34
34
  import {IBlockInput} from "./blocks/blockInput/index.js";
35
- import {ImportBlockOpts} from "./blocks/types.js";
35
+ import {ImportBlockOpts, ImportPayloadOpts} from "./blocks/types.js";
36
36
  import {IBlsVerifier} from "./bls/index.js";
37
37
  import {ColumnReconstructionTracker} from "./ColumnReconstructionTracker.js";
38
38
  import {ChainEventEmitter} from "./emitter.js";
@@ -58,7 +58,6 @@ import {
58
58
  SeenBlockProposers,
59
59
  SeenContributionAndProof,
60
60
  SeenExecutionPayloadBids,
61
- SeenExecutionPayloadEnvelopes,
62
61
  SeenPayloadAttesters,
63
62
  SeenSyncCommitteeMessages,
64
63
  } from "./seenCache/index.js";
@@ -66,6 +65,7 @@ import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
66
65
  import {SeenAttestationDatas} from "./seenCache/seenAttestationData.js";
67
66
  import {SeenBlockAttesters} from "./seenCache/seenBlockAttesters.js";
68
67
  import {SeenBlockInput} from "./seenCache/seenGossipBlockInput.js";
68
+ import {PayloadEnvelopeInput, SeenPayloadEnvelopeInput} from "./seenCache/seenPayloadEnvelopeInput.js";
69
69
  import {ShufflingCache} from "./shufflingCache.js";
70
70
  import {ValidatorMonitor} from "./validatorMonitor.js";
71
71
 
@@ -128,13 +128,13 @@ export interface IBeaconChain {
128
128
  readonly seenAggregators: SeenAggregators;
129
129
  readonly seenPayloadAttesters: SeenPayloadAttesters;
130
130
  readonly seenAggregatedAttestations: SeenAggregatedAttestations;
131
- readonly seenExecutionPayloadEnvelopes: SeenExecutionPayloadEnvelopes;
132
131
  readonly seenExecutionPayloadBids: SeenExecutionPayloadBids;
133
132
  readonly seenBlockProposers: SeenBlockProposers;
134
133
  readonly seenSyncCommitteeMessages: SeenSyncCommitteeMessages;
135
134
  readonly seenContributionAndProof: SeenContributionAndProof;
136
135
  readonly seenAttestationDatas: SeenAttestationDatas;
137
136
  readonly seenBlockInputCache: SeenBlockInput;
137
+ readonly seenPayloadEnvelopeInputCache: SeenPayloadEnvelopeInput;
138
138
  // Seen cache for liveness checks
139
139
  readonly seenBlockAttesters: SeenBlockAttesters;
140
140
 
@@ -192,7 +192,7 @@ export interface IBeaconChain {
192
192
  ): {state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null;
193
193
  /** Return state bytes by checkpoint */
194
194
  getStateOrBytesByCheckpoint(
195
- checkpoint: CheckpointWithHex
195
+ checkpoint: CheckpointWithPayloadStatus
196
196
  ): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>;
197
197
 
198
198
  /**
@@ -242,6 +242,9 @@ export interface IBeaconChain {
242
242
  /** Process a chain of blocks until complete */
243
243
  processChainSegment(blocks: IBlockInput[], opts?: ImportBlockOpts): Promise<void>;
244
244
 
245
+ /** Process execution payload envelope: verify, import to fork choice, and persist to DB */
246
+ processExecutionPayload(payloadInput: PayloadEnvelopeInput, opts?: ImportPayloadOpts): Promise<void>;
247
+
245
248
  getStatus(): Status;
246
249
 
247
250
  recomputeForkChoiceHead(caller: ForkchoiceCaller): ProtoBlock;
@@ -41,7 +41,7 @@ export function isValidBlsToExecutionChangeForBlockInclusion(
41
41
  state: CachedBeaconStateAllForks,
42
42
  signedBLSToExecutionChange: capella.SignedBLSToExecutionChange
43
43
  ): boolean {
44
- // For each condition from https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md#new-process_bls_to_execution_change
44
+ // For each condition from https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/capella/beacon-chain.md#new-process_bls_to_execution_change
45
45
  //
46
46
  // 1. assert address_change.validator_index < len(state.validators):
47
47
  // If valid before will always be valid in the future, no need to check
@@ -1,6 +1,6 @@
1
1
  import {routes} from "@lodestar/api";
2
2
  import {ChainForkConfig} from "@lodestar/config";
3
- import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
3
+ import {PayloadStatus, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
4
4
  import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix} from "@lodestar/params";
5
5
  import {
6
6
  CachedBeaconStateAllForks,
@@ -211,7 +211,11 @@ export class PrepareNextSlotScheduler {
211
211
  // + if next slot is a skipped slot, it'd help getting target checkpoint state faster to validate attestations
212
212
  if (isEpochTransition) {
213
213
  this.metrics?.precomputeNextEpochTransition.count.inc({result: "success"}, 1);
214
- const previousHits = this.chain.regen.updatePreComputedCheckpoint(headRoot, nextEpoch);
214
+ // Determine payloadPresent from head block's payload status
215
+ // Pre-Gloas: payloadStatus is always FULL → payloadPresent = true
216
+ // Post-Gloas: FULL → true, EMPTY → false, PENDING → false (conservative, treat as block state)
217
+ const payloadPresent = headBlock.payloadStatus === PayloadStatus.FULL;
218
+ const previousHits = this.chain.regen.updatePreComputedCheckpoint(headRoot, nextEpoch, payloadPresent);
215
219
  if (previousHits === 0) {
216
220
  this.metrics?.precomputeNextEpochTransition.waste.inc();
217
221
  }
@@ -73,7 +73,12 @@ export function computeEnvelopeStateRoot(
73
73
  };
74
74
 
75
75
  const processEnvelopeTimer = metrics?.blockPayload.executionPayloadEnvelopeProcessingTime.startTimer();
76
- const postEnvelopeState = processExecutionPayloadEnvelope(postBlockState, signedEnvelope, false, {
76
+ const postEnvelopeState = processExecutionPayloadEnvelope(postBlockState, signedEnvelope, {
77
+ // Signature is zero-ed (G2_POINT_AT_INFINITY), skip verification
78
+ verifySignature: false,
79
+ // State root is being computed here, the envelope doesn't have it yet
80
+ verifyStateRoot: false,
81
+ // Preserve cache in source state, since the resulting state is not added to the state cache
77
82
  dontTransferCache: true,
78
83
  });
79
84
  processEnvelopeTimer?.();
@@ -441,7 +441,7 @@ export async function produceBlockBody<T extends BlockType>(
441
441
  parentBlockRoot: toRootHex(parentBlockRoot),
442
442
  feeRecipient,
443
443
  });
444
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/validator.md#constructing-the-beaconblockbody
444
+ // https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/deneb/validator.md#constructing-the-beaconblockbody
445
445
  const prepareRes = await prepareExecutionPayload(
446
446
  this,
447
447
  this.logger,
@@ -1,3 +1,4 @@
1
+ import {PayloadStatus} from "@lodestar/fork-choice";
1
2
  import {Root, RootHex, Slot} from "@lodestar/types";
2
3
 
3
4
  export enum RegenErrorCode {
@@ -9,6 +10,8 @@ export enum RegenErrorCode {
9
10
  BLOCK_NOT_IN_DB = "REGEN_ERROR_BLOCK_NOT_IN_DB",
10
11
  STATE_TRANSITION_ERROR = "REGEN_ERROR_STATE_TRANSITION_ERROR",
11
12
  INVALID_STATE_ROOT = "REGEN_ERROR_INVALID_STATE_ROOT",
13
+ UNEXPECTED_PAYLOAD_STATUS = "REGEN_ERROR_UNEXPECTED_PAYLOAD_STATUS",
14
+ INTERNAL_ERROR = "REGEN_ERROR_INTERNAL_ERROR",
12
15
  }
13
16
 
14
17
  export type RegenErrorType =
@@ -19,7 +22,9 @@ export type RegenErrorType =
19
22
  | {code: RegenErrorCode.TOO_MANY_BLOCK_PROCESSED; stateRoot: RootHex | Root}
20
23
  | {code: RegenErrorCode.BLOCK_NOT_IN_DB; blockRoot: RootHex | Root}
21
24
  | {code: RegenErrorCode.STATE_TRANSITION_ERROR; error: Error}
22
- | {code: RegenErrorCode.INVALID_STATE_ROOT; slot: Slot; expected: RootHex; actual: RootHex};
25
+ | {code: RegenErrorCode.INVALID_STATE_ROOT; slot: Slot; expected: RootHex; actual: RootHex}
26
+ | {code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS; blockRoot: RootHex | Root; payloadStatus: PayloadStatus}
27
+ | {code: RegenErrorCode.INTERNAL_ERROR; message: string};
23
28
 
24
29
  export class RegenError extends Error {
25
30
  type: RegenErrorType;
@@ -2,15 +2,17 @@ import {routes} from "@lodestar/api";
2
2
  import {ProtoBlock} from "@lodestar/fork-choice";
3
3
  import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
4
4
  import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
5
- import {CheckpointHex} from "../stateCache/types.js";
5
+ import {CheckpointHexPayload} from "../stateCache/types.js";
6
6
 
7
7
  export enum RegenCaller {
8
8
  getDuties = "getDuties",
9
9
  processBlock = "processBlock",
10
10
  produceBlock = "produceBlock",
11
11
  validateGossipBlock = "validateGossipBlock",
12
+ validateGossipPayloadEnvelope = "validateGossipPayloadEnvelope",
12
13
  validateGossipBlob = "validateGossipBlob",
13
14
  validateGossipDataColumn = "validateGossipDataColumn",
15
+ validateGossipExecutionPayloadEnvelope = "validateGossipExecutionPayloadEnvelope",
14
16
  precomputeEpoch = "precomputeEpoch",
15
17
  predictProposerHead = "predictProposerHead",
16
18
  produceAttestationData = "produceAttestationData",
@@ -38,15 +40,21 @@ export interface IStateRegenerator extends IStateRegeneratorInternal {
38
40
  dumpCacheSummary(): routes.lodestar.StateCacheItem[];
39
41
  getStateSync(stateRoot: RootHex): CachedBeaconStateAllForks | null;
40
42
  getPreStateSync(block: BeaconBlock): CachedBeaconStateAllForks | null;
41
- getCheckpointStateOrBytes(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | Uint8Array | null>;
42
- getCheckpointStateSync(cp: CheckpointHex): CachedBeaconStateAllForks | null;
43
+ getCheckpointStateOrBytes(cp: CheckpointHexPayload): Promise<CachedBeaconStateAllForks | Uint8Array | null>;
44
+ getCheckpointStateSync(cp: CheckpointHexPayload): CachedBeaconStateAllForks | null;
43
45
  getClosestHeadState(head: ProtoBlock): CachedBeaconStateAllForks | null;
44
46
  pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void;
45
47
  pruneOnFinalized(finalizedEpoch: Epoch): void;
46
- processState(blockRootHex: RootHex, postState: CachedBeaconStateAllForks): void;
47
- addCheckpointState(cp: phase0.Checkpoint, item: CachedBeaconStateAllForks): void;
48
+ processBlockState(blockRootHex: RootHex, postState: CachedBeaconStateAllForks): void;
49
+ processPayloadState(payloadState: CachedBeaconStateAllForks): void;
50
+ /**
51
+ * payloadPresent is true if this is payload state, false if block state.
52
+ * payloadPresent is always true for pre-gloas.
53
+ */
54
+ addCheckpointState(cp: phase0.Checkpoint, item: CachedBeaconStateAllForks, payloadPresent: boolean): void;
48
55
  updateHeadState(newHead: ProtoBlock, maybeHeadState: CachedBeaconStateAllForks): void;
49
- updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null;
56
+ updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch, payloadPresent: boolean): number | null;
57
+ upgradeForGloas(epoch: Epoch): void;
50
58
  }
51
59
 
52
60
  /**
@@ -1,11 +1,11 @@
1
1
  import {routes} from "@lodestar/api";
2
- import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
2
+ import {IForkChoice, PayloadStatus, ProtoBlock} from "@lodestar/fork-choice";
3
3
  import {CachedBeaconStateAllForks, computeEpochAtSlot} from "@lodestar/state-transition";
4
4
  import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lodestar/types";
5
- import {Logger, toRootHex} from "@lodestar/utils";
5
+ import {Logger, fromHex, toRootHex} from "@lodestar/utils";
6
6
  import {Metrics} from "../../metrics/index.js";
7
7
  import {JobItemQueue} from "../../util/queue/index.js";
8
- import {BlockStateCache, CheckpointHex, CheckpointStateCache} from "../stateCache/types.js";
8
+ import {BlockStateCache, CheckpointHexPayload, CheckpointStateCache} from "../stateCache/types.js";
9
9
  import {RegenError, RegenErrorCode} from "./errors.js";
10
10
  import {
11
11
  IStateRegenerator,
@@ -104,9 +104,19 @@ export class QueuedStateRegenerator implements IStateRegenerator {
104
104
  const parentEpoch = computeEpochAtSlot(parentBlock.slot);
105
105
  const blockEpoch = computeEpochAtSlot(block.slot);
106
106
 
107
+ // Convert PayloadStatus to payloadPresent boolean
108
+ if (parentBlock.payloadStatus === PayloadStatus.PENDING) {
109
+ throw new RegenError({
110
+ code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS,
111
+ blockRoot: block.parentRoot,
112
+ payloadStatus: parentBlock.payloadStatus,
113
+ });
114
+ }
115
+ const payloadPresent = parentBlock.payloadStatus === PayloadStatus.FULL;
116
+
107
117
  // Check the checkpoint cache (if the pre-state is a checkpoint state)
108
118
  if (parentEpoch < blockEpoch) {
109
- const checkpointState = this.checkpointStateCache.getLatest(parentRoot, blockEpoch);
119
+ const checkpointState = this.checkpointStateCache.getLatest(parentRoot, blockEpoch, payloadPresent);
110
120
  if (checkpointState && computeEpochAtSlot(checkpointState.slot) === blockEpoch) {
111
121
  return checkpointState;
112
122
  }
@@ -125,14 +135,14 @@ export class QueuedStateRegenerator implements IStateRegenerator {
125
135
  return null;
126
136
  }
127
137
 
128
- async getCheckpointStateOrBytes(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | Uint8Array | null> {
138
+ async getCheckpointStateOrBytes(cp: CheckpointHexPayload): Promise<CachedBeaconStateAllForks | Uint8Array | null> {
129
139
  return this.checkpointStateCache.getStateOrBytes(cp);
130
140
  }
131
141
 
132
142
  /**
133
143
  * Get checkpoint state from cache
134
144
  */
135
- getCheckpointStateSync(cp: CheckpointHex): CachedBeaconStateAllForks | null {
145
+ getCheckpointStateSync(cp: CheckpointHexPayload): CachedBeaconStateAllForks | null {
136
146
  return this.checkpointStateCache.get(cp);
137
147
  }
138
148
 
@@ -140,7 +150,19 @@ export class QueuedStateRegenerator implements IStateRegenerator {
140
150
  * Get state closest to head
141
151
  */
142
152
  getClosestHeadState(head: ProtoBlock): CachedBeaconStateAllForks | null {
143
- return this.checkpointStateCache.getLatest(head.blockRoot, Infinity) || this.blockStateCache.get(head.stateRoot);
153
+ // Convert PayloadStatus to payloadPresent boolean
154
+ if (head.payloadStatus === PayloadStatus.PENDING) {
155
+ throw new RegenError({
156
+ code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS,
157
+ blockRoot: fromHex(head.blockRoot),
158
+ payloadStatus: head.payloadStatus,
159
+ });
160
+ }
161
+ const payloadPresent = head.payloadStatus === PayloadStatus.FULL;
162
+ return (
163
+ this.checkpointStateCache.getLatest(head.blockRoot, Infinity, payloadPresent) ||
164
+ this.blockStateCache.get(head.stateRoot)
165
+ );
144
166
  }
145
167
 
146
168
  pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void {
@@ -153,15 +175,24 @@ export class QueuedStateRegenerator implements IStateRegenerator {
153
175
  this.blockStateCache.deleteAllBeforeEpoch(finalizedEpoch);
154
176
  }
155
177
 
156
- processState(blockRootHex: RootHex, postState: CachedBeaconStateAllForks): void {
178
+ processBlockState(blockRootHex: RootHex, postState: CachedBeaconStateAllForks): void {
157
179
  this.blockStateCache.add(postState);
158
180
  this.checkpointStateCache.processState(blockRootHex, postState).catch((e) => {
159
181
  this.logger.debug("Error processing block state", {blockRootHex, slot: postState.slot}, e);
160
182
  });
161
183
  }
162
184
 
163
- addCheckpointState(cp: phase0.Checkpoint, item: CachedBeaconStateAllForks): void {
164
- this.checkpointStateCache.add(cp, item);
185
+ /**
186
+ * Process payload state for caching after importing execution payload.
187
+ */
188
+ processPayloadState(payloadState: CachedBeaconStateAllForks): void {
189
+ // Add payload state to block state cache (keyed by payload state root)
190
+ this.blockStateCache.add(payloadState);
191
+ }
192
+
193
+ // TODO GLOAS: This should also be called when importing execution payload after we implement it
194
+ addCheckpointState(cp: phase0.Checkpoint, item: CachedBeaconStateAllForks, payloadPresent: boolean): void {
195
+ this.checkpointStateCache.add(cp, item, payloadPresent);
165
196
  }
166
197
 
167
198
  updateHeadState(newHead: ProtoBlock, maybeHeadState: CachedBeaconStateAllForks): void {
@@ -197,8 +228,13 @@ export class QueuedStateRegenerator implements IStateRegenerator {
197
228
  }
198
229
  }
199
230
 
200
- updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null {
201
- return this.checkpointStateCache.updatePreComputedCheckpoint(rootHex, epoch);
231
+ updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch, payloadPresent: boolean): number | null {
232
+ return this.checkpointStateCache.updatePreComputedCheckpoint(rootHex, epoch, payloadPresent);
233
+ }
234
+
235
+ upgradeForGloas(epoch: Epoch): void {
236
+ this.logger.verbose("Upgrading block state cache for Gloas fork", {epoch});
237
+ this.blockStateCache.upgradeToGloas();
202
238
  }
203
239
 
204
240
  /**