@lodestar/beacon-node 1.41.0-rc.2 → 1.42.0-dev.1d50253953

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 (225) 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 +5 -1
  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 +3 -3
  24. package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
  25. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  26. package/lib/chain/blocks/importBlock.js +29 -9
  27. package/lib/chain/blocks/importBlock.js.map +1 -1
  28. package/lib/chain/blocks/importExecutionPayload.d.ts +48 -0
  29. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -0
  30. package/lib/chain/blocks/importExecutionPayload.js +159 -0
  31. package/lib/chain/blocks/importExecutionPayload.js.map +1 -0
  32. package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts +3 -0
  33. package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts.map +1 -0
  34. package/lib/chain/blocks/payloadEnvelopeInput/index.js +3 -0
  35. package/lib/chain/blocks/payloadEnvelopeInput/index.js.map +1 -0
  36. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +80 -0
  37. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -0
  38. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +248 -0
  39. package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -0
  40. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +29 -0
  41. package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -0
  42. package/lib/chain/blocks/payloadEnvelopeInput/types.js +11 -0
  43. package/lib/chain/blocks/payloadEnvelopeInput/types.js.map +1 -0
  44. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +15 -0
  45. package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -0
  46. package/lib/chain/blocks/payloadEnvelopeProcessor.js +46 -0
  47. package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -0
  48. package/lib/chain/blocks/types.d.ts +7 -0
  49. package/lib/chain/blocks/types.d.ts.map +1 -1
  50. package/lib/chain/blocks/verifyBlocksSignatures.js +1 -1
  51. package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
  52. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +12 -0
  53. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -0
  54. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +40 -0
  55. package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -0
  56. package/lib/chain/chain.d.ts +10 -5
  57. package/lib/chain/chain.d.ts.map +1 -1
  58. package/lib/chain/chain.js +44 -10
  59. package/lib/chain/chain.js.map +1 -1
  60. package/lib/chain/errors/executionPayloadEnvelope.d.ts +12 -2
  61. package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
  62. package/lib/chain/errors/executionPayloadEnvelope.js +3 -1
  63. package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
  64. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  65. package/lib/chain/forkChoice/index.js +0 -10
  66. package/lib/chain/forkChoice/index.js.map +1 -1
  67. package/lib/chain/interface.d.ts +8 -5
  68. package/lib/chain/interface.d.ts.map +1 -1
  69. package/lib/chain/opPools/utils.js +1 -1
  70. package/lib/chain/opPools/utils.js.map +1 -1
  71. package/lib/chain/prepareNextSlot.d.ts.map +1 -1
  72. package/lib/chain/prepareNextSlot.js +6 -2
  73. package/lib/chain/prepareNextSlot.js.map +1 -1
  74. package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
  75. package/lib/chain/produceBlock/computeNewStateRoot.js +6 -1
  76. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  77. package/lib/chain/produceBlock/produceBlockBody.js +1 -1
  78. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  79. package/lib/chain/regen/errors.d.ts +11 -1
  80. package/lib/chain/regen/errors.d.ts.map +1 -1
  81. package/lib/chain/regen/errors.js +2 -0
  82. package/lib/chain/regen/errors.js.map +1 -1
  83. package/lib/chain/regen/interface.d.ts +14 -6
  84. package/lib/chain/regen/interface.d.ts.map +1 -1
  85. package/lib/chain/regen/interface.js +2 -0
  86. package/lib/chain/regen/interface.js.map +1 -1
  87. package/lib/chain/regen/queued.d.ts +11 -6
  88. package/lib/chain/regen/queued.d.ts.map +1 -1
  89. package/lib/chain/regen/queued.js +40 -8
  90. package/lib/chain/regen/queued.js.map +1 -1
  91. package/lib/chain/regen/regen.d.ts +5 -0
  92. package/lib/chain/regen/regen.d.ts.map +1 -1
  93. package/lib/chain/regen/regen.js +33 -6
  94. package/lib/chain/regen/regen.js.map +1 -1
  95. package/lib/chain/seenCache/index.d.ts +1 -1
  96. package/lib/chain/seenCache/index.d.ts.map +1 -1
  97. package/lib/chain/seenCache/index.js +1 -1
  98. package/lib/chain/seenCache/index.js.map +1 -1
  99. package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
  100. package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
  101. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +38 -0
  102. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -0
  103. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +76 -0
  104. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -0
  105. package/lib/chain/stateCache/datastore/db.d.ts +4 -5
  106. package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
  107. package/lib/chain/stateCache/datastore/db.js +32 -10
  108. package/lib/chain/stateCache/datastore/db.js.map +1 -1
  109. package/lib/chain/stateCache/datastore/file.d.ts +1 -1
  110. package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
  111. package/lib/chain/stateCache/datastore/file.js +5 -5
  112. package/lib/chain/stateCache/datastore/file.js.map +1 -1
  113. package/lib/chain/stateCache/datastore/types.d.ts +1 -1
  114. package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
  115. package/lib/chain/stateCache/fifoBlockStateCache.d.ts +7 -4
  116. package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
  117. package/lib/chain/stateCache/fifoBlockStateCache.js +8 -3
  118. package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
  119. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +33 -14
  120. package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
  121. package/lib/chain/stateCache/persistentCheckpointsCache.js +217 -119
  122. package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
  123. package/lib/chain/stateCache/types.d.ts +15 -8
  124. package/lib/chain/stateCache/types.d.ts.map +1 -1
  125. package/lib/chain/stateCache/types.js.map +1 -1
  126. package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
  127. package/lib/chain/validation/executionPayloadEnvelope.js +30 -19
  128. package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
  129. package/lib/chain/validation/lightClientFinalityUpdate.js +1 -1
  130. package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
  131. package/lib/chain/validation/lightClientOptimisticUpdate.js +1 -1
  132. package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
  133. package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
  134. package/lib/chain/validation/voluntaryExit.js +2 -2
  135. package/lib/chain/validation/voluntaryExit.js.map +1 -1
  136. package/lib/chain/validatorMonitor.d.ts +2 -1
  137. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  138. package/lib/chain/validatorMonitor.js +4 -1
  139. package/lib/chain/validatorMonitor.js.map +1 -1
  140. package/lib/execution/engine/interface.d.ts +2 -2
  141. package/lib/metrics/metrics/lodestar.d.ts +28 -0
  142. package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
  143. package/lib/metrics/metrics/lodestar.js +74 -0
  144. package/lib/metrics/metrics/lodestar.js.map +1 -1
  145. package/lib/network/network.js +2 -2
  146. package/lib/network/network.js.map +1 -1
  147. package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
  148. package/lib/network/processor/extractSlotRootFns.js +14 -4
  149. package/lib/network/processor/extractSlotRootFns.js.map +1 -1
  150. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  151. package/lib/network/processor/gossipHandlers.js +31 -3
  152. package/lib/network/processor/gossipHandlers.js.map +1 -1
  153. package/lib/network/reqresp/ReqRespBeaconNode.d.ts +1 -1
  154. package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
  155. package/lib/sync/backfill/backfill.d.ts +1 -1
  156. package/lib/sync/backfill/backfill.js +1 -1
  157. package/lib/sync/constants.d.ts +1 -1
  158. package/lib/sync/constants.js +1 -1
  159. package/lib/util/sszBytes.d.ts +4 -1
  160. package/lib/util/sszBytes.d.ts.map +1 -1
  161. package/lib/util/sszBytes.js +69 -12
  162. package/lib/util/sszBytes.js.map +1 -1
  163. package/package.json +15 -15
  164. package/src/api/impl/beacon/blocks/index.ts +36 -17
  165. package/src/api/impl/beacon/state/utils.ts +2 -2
  166. package/src/api/impl/validator/index.ts +7 -3
  167. package/src/chain/archiveStore/archiveStore.ts +0 -10
  168. package/src/chain/archiveStore/interface.ts +4 -4
  169. package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +8 -5
  170. package/src/chain/archiveStore/utils/archiveBlocks.ts +59 -1
  171. package/src/chain/blocks/blockInput/types.ts +3 -3
  172. package/src/chain/blocks/importBlock.ts +47 -8
  173. package/src/chain/blocks/importExecutionPayload.ts +241 -0
  174. package/src/chain/blocks/payloadEnvelopeInput/index.ts +2 -0
  175. package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +336 -0
  176. package/src/chain/blocks/payloadEnvelopeInput/types.ts +33 -0
  177. package/src/chain/blocks/payloadEnvelopeProcessor.ts +61 -0
  178. package/src/chain/blocks/types.ts +8 -0
  179. package/src/chain/blocks/verifyBlocksSignatures.ts +1 -1
  180. package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +55 -0
  181. package/src/chain/chain.ts +60 -15
  182. package/src/chain/errors/executionPayloadEnvelope.ts +6 -2
  183. package/src/chain/forkChoice/index.ts +0 -10
  184. package/src/chain/interface.ts +8 -5
  185. package/src/chain/opPools/utils.ts +1 -1
  186. package/src/chain/prepareNextSlot.ts +6 -2
  187. package/src/chain/produceBlock/computeNewStateRoot.ts +6 -1
  188. package/src/chain/produceBlock/produceBlockBody.ts +1 -1
  189. package/src/chain/regen/errors.ts +6 -1
  190. package/src/chain/regen/interface.ts +14 -6
  191. package/src/chain/regen/queued.ts +48 -12
  192. package/src/chain/regen/regen.ts +37 -7
  193. package/src/chain/seenCache/index.ts +1 -1
  194. package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
  195. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +106 -0
  196. package/src/chain/stateCache/datastore/db.ts +33 -10
  197. package/src/chain/stateCache/datastore/file.ts +6 -5
  198. package/src/chain/stateCache/datastore/types.ts +3 -2
  199. package/src/chain/stateCache/fifoBlockStateCache.ts +10 -4
  200. package/src/chain/stateCache/persistentCheckpointsCache.ts +248 -139
  201. package/src/chain/stateCache/types.ts +18 -8
  202. package/src/chain/validation/executionPayloadEnvelope.ts +38 -25
  203. package/src/chain/validation/lightClientFinalityUpdate.ts +1 -1
  204. package/src/chain/validation/lightClientOptimisticUpdate.ts +1 -1
  205. package/src/chain/validation/voluntaryExit.ts +2 -1
  206. package/src/chain/validatorMonitor.ts +11 -1
  207. package/src/execution/engine/interface.ts +2 -2
  208. package/src/metrics/metrics/lodestar.ts +77 -0
  209. package/src/network/network.ts +2 -2
  210. package/src/network/processor/extractSlotRootFns.ts +18 -5
  211. package/src/network/processor/gossipHandlers.ts +37 -1
  212. package/src/network/reqresp/ReqRespBeaconNode.ts +1 -1
  213. package/src/sync/backfill/backfill.ts +1 -1
  214. package/src/sync/constants.ts +1 -1
  215. package/src/util/sszBytes.ts +90 -10
  216. package/lib/chain/archiveStore/utils/archivePayloads.d.ts +0 -7
  217. package/lib/chain/archiveStore/utils/archivePayloads.d.ts.map +0 -1
  218. package/lib/chain/archiveStore/utils/archivePayloads.js +0 -10
  219. package/lib/chain/archiveStore/utils/archivePayloads.js.map +0 -1
  220. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts +0 -15
  221. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts.map +0 -1
  222. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js +0 -28
  223. package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js.map +0 -1
  224. package/src/chain/archiveStore/utils/archivePayloads.ts +0 -15
  225. package/src/chain/seenCache/seenExecutionPayloadEnvelope.ts +0 -34
@@ -1,14 +1,15 @@
1
- import {PublicKey} from "@chainsafe/blst";
1
+ import {PayloadStatus} from "@lodestar/fork-choice";
2
2
  import {
3
+ BeaconStateView,
3
4
  CachedBeaconStateGloas,
4
5
  computeStartSlotAtEpoch,
5
- createSingleSignatureSetFromComponents,
6
- getExecutionPayloadEnvelopeSigningRoot,
6
+ getExecutionPayloadEnvelopeSignatureSet,
7
7
  } from "@lodestar/state-transition";
8
8
  import {gloas} from "@lodestar/types";
9
9
  import {toRootHex} from "@lodestar/utils";
10
10
  import {ExecutionPayloadEnvelopeError, ExecutionPayloadEnvelopeErrorCode, GossipAction} from "../errors/index.js";
11
11
  import {IBeaconChain} from "../index.js";
12
+ import {RegenCaller} from "../regen/index.js";
12
13
 
13
14
  export async function validateApiExecutionPayloadEnvelope(
14
15
  chain: IBeaconChain,
@@ -47,7 +48,9 @@ async function validateExecutionPayloadEnvelope(
47
48
 
48
49
  // [IGNORE] The node has not seen another valid
49
50
  // `SignedExecutionPayloadEnvelope` for this block root from this builder.
50
- if (chain.seenExecutionPayloadEnvelopes.isKnown(blockRootHex)) {
51
+ const envelopeBlock = chain.forkChoice.getBlockHex(blockRootHex, PayloadStatus.FULL);
52
+ const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
53
+ if (envelopeBlock || payloadInput?.hasPayloadEnvelope()) {
51
54
  throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
52
55
  code: ExecutionPayloadEnvelopeErrorCode.ENVELOPE_ALREADY_KNOWN,
53
56
  blockRoot: blockRootHex,
@@ -55,6 +58,14 @@ async function validateExecutionPayloadEnvelope(
55
58
  });
56
59
  }
57
60
 
61
+ if (!payloadInput) {
62
+ // PayloadEnvelopeInput should have been created during block import
63
+ throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
64
+ code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING,
65
+ blockRoot: blockRootHex,
66
+ });
67
+ }
68
+
58
69
  // [IGNORE] The envelope is from a slot greater than or equal to the latest finalized slot -- i.e. validate that `envelope.slot >= compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)`
59
70
  const finalizedCheckpoint = chain.forkChoice.getFinalizedCheckpoint();
60
71
  const finalizedSlot = computeStartSlotAtEpoch(finalizedCheckpoint.epoch);
@@ -79,45 +90,47 @@ async function validateExecutionPayloadEnvelope(
79
90
  });
80
91
  }
81
92
 
82
- if (block.builderIndex == null || block.blockHashFromBid == null) {
83
- // This indicates this block is a pre-gloas block which is wrong
84
- throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
85
- code: ExecutionPayloadEnvelopeErrorCode.CACHE_FAIL,
86
- blockRoot: blockRootHex,
87
- });
88
- }
89
-
90
93
  // [REJECT] `envelope.builder_index == bid.builder_index`
91
- if (envelope.builderIndex !== block.builderIndex) {
94
+ if (envelope.builderIndex !== payloadInput.getBuilderIndex()) {
92
95
  throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
93
96
  code: ExecutionPayloadEnvelopeErrorCode.BUILDER_INDEX_MISMATCH,
94
97
  envelopeBuilderIndex: envelope.builderIndex,
95
- bidBuilderIndex: block.builderIndex,
98
+ bidBuilderIndex: payloadInput.getBuilderIndex(),
96
99
  });
97
100
  }
98
101
 
99
102
  // [REJECT] `payload.block_hash == bid.block_hash`
100
- if (toRootHex(payload.blockHash) !== block.blockHashFromBid) {
103
+ if (toRootHex(payload.blockHash) !== payloadInput.getBlockHashHex()) {
101
104
  throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
102
105
  code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH,
103
106
  envelopeBlockHash: toRootHex(payload.blockHash),
104
- bidBlockHash: block.blockHashFromBid,
107
+ bidBlockHash: payloadInput.getBlockHashHex(),
105
108
  });
106
109
  }
107
110
 
108
- // [REJECT] `signed_execution_payload_envelope.signature` is valid with respect to the builder's public key.
109
- const state = chain.getHeadState() as CachedBeaconStateGloas;
110
- const signatureSet = createSingleSignatureSetFromComponents(
111
- PublicKey.fromBytes(state.builders.getReadonly(envelope.builderIndex).pubkey),
112
- getExecutionPayloadEnvelopeSigningRoot(chain.config, envelope),
113
- executionPayloadEnvelope.signature
111
+ // Get the post block state which is the pre-payload state to verify the builder's signature.
112
+ const blockState = await chain.regen
113
+ .getState(block.stateRoot, RegenCaller.validateGossipPayloadEnvelope)
114
+ .catch(() => {
115
+ throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
116
+ code: ExecutionPayloadEnvelopeErrorCode.UNKNOWN_BLOCK_STATE,
117
+ blockRoot: blockRootHex,
118
+ slot: envelope.slot,
119
+ });
120
+ });
121
+
122
+ const state = blockState as CachedBeaconStateGloas;
123
+ const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
124
+ chain.config,
125
+ chain.pubkeyCache,
126
+ new BeaconStateView(state),
127
+ executionPayloadEnvelope,
128
+ payloadInput.proposerIndex
114
129
  );
115
130
 
116
- if (!(await chain.bls.verifySignatureSets([signatureSet]))) {
131
+ if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
117
132
  throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
118
133
  code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE,
119
134
  });
120
135
  }
121
-
122
- chain.seenExecutionPayloadEnvelopes.add(blockRootHex, envelope.slot);
123
136
  }
@@ -6,7 +6,7 @@ import {LightClientError, LightClientErrorCode} from "../errors/lightClientError
6
6
  import {IBeaconChain} from "../interface.js";
7
7
  import {updateReceivedTooEarly} from "./lightClientOptimisticUpdate.js";
8
8
 
9
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#light_client_finality_update
9
+ // https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#light_client_finality_update
10
10
  export function validateLightClientFinalityUpdate(
11
11
  config: ChainForkConfig,
12
12
  chain: IBeaconChain,
@@ -6,7 +6,7 @@ import {GossipAction} from "../errors/index.js";
6
6
  import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js";
7
7
  import {IBeaconChain} from "../interface.js";
8
8
 
9
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update
9
+ // https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update
10
10
  export function validateLightClientOptimisticUpdate(
11
11
  config: ChainForkConfig,
12
12
  chain: IBeaconChain,
@@ -1,4 +1,5 @@
1
1
  import {
2
+ BeaconStateView,
2
3
  VoluntaryExitValidity,
3
4
  getVoluntaryExitSignatureSet,
4
5
  getVoluntaryExitValidity,
@@ -59,7 +60,7 @@ async function validateVoluntaryExit(
59
60
  });
60
61
  }
61
62
 
62
- const signatureSet = getVoluntaryExitSignatureSet(chain.config, state.slot, voluntaryExit);
63
+ const signatureSet = getVoluntaryExitSignatureSet(chain.config, new BeaconStateView(state), voluntaryExit);
63
64
  if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
64
65
  throw new VoluntaryExitError(GossipAction.REJECT, {
65
66
  code: VoluntaryExitErrorCode.INVALID_SIGNATURE,
@@ -23,6 +23,7 @@ import {
23
23
  ValidatorIndex,
24
24
  altair,
25
25
  deneb,
26
+ gloas,
26
27
  } from "@lodestar/types";
27
28
  import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, prettyPrintIndices, toRootHex} from "@lodestar/utils";
28
29
  import {GENESIS_SLOT} from "../constants/constants.js";
@@ -61,6 +62,11 @@ export type ValidatorMonitor = {
61
62
  ): void;
62
63
  registerBeaconBlock(src: OpSource, delaySec: Seconds, block: BeaconBlock): void;
63
64
  registerBlobSidecar(src: OpSource, seenTimestampSec: Seconds, blob: deneb.BlobSidecar): void;
65
+ registerExecutionPayloadEnvelope(
66
+ src: OpSource,
67
+ delaySec: Seconds,
68
+ envelope: gloas.SignedExecutionPayloadEnvelope
69
+ ): void;
64
70
  registerImportedBlock(block: BeaconBlock, data: {proposerBalanceDelta: number}): void;
65
71
  onPoolSubmitUnaggregatedAttestation(
66
72
  seenTimestampSec: number,
@@ -450,6 +456,10 @@ export function createValidatorMonitor(
450
456
  //TODO: freetheblobs
451
457
  },
452
458
 
459
+ registerExecutionPayloadEnvelope(_src, _delaySec, _envelope) {
460
+ // TODO GLOAS: implement execution payload envelope monitoring
461
+ },
462
+
453
463
  registerImportedBlock(block, {proposerBalanceDelta}) {
454
464
  const validator = validators.get(block.proposerIndex);
455
465
  if (validator) {
@@ -889,7 +899,7 @@ function renderAttestationSummary(
889
899
  summary: AttestationSummary | undefined,
890
900
  flags: ParticipationFlags
891
901
  ): string {
892
- // Reference https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices
902
+ // Reference https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices
893
903
  //
894
904
  // is_matching_source = data.source == justified_checkpoint
895
905
  // is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch)
@@ -128,7 +128,7 @@ export interface IExecutionEngine {
128
128
  * corresponding state, up to and including finalized_block_hash.
129
129
  *
130
130
  * The call of the notify_forkchoice_updated function maps on the POS_FORKCHOICE_UPDATED event defined in the EIP-3675.
131
- * https://github.com/ethereum/consensus-specs/blob/dev/specs/merge/fork-choice.md#notify_forkchoice_updated
131
+ * https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/merge/fork-choice.md#notify_forkchoice_updated
132
132
  *
133
133
  * Should be called in response to fork-choice head and finalized events
134
134
  */
@@ -145,7 +145,7 @@ export interface IExecutionEngine {
145
145
  * since the corresponding call to prepare_payload method.
146
146
  *
147
147
  * Required for block producing
148
- * https://github.com/ethereum/consensus-specs/blob/dev/specs/merge/validator.md#get_payload
148
+ * https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/merge/validator.md#get_payload
149
149
  */
150
150
  getPayload(
151
151
  fork: ForkName,
@@ -3,6 +3,7 @@ import {NotReorgedReason} from "@lodestar/fork-choice";
3
3
  import {ArchiveStoreTask} from "../../chain/archiveStore/archiveStore.js";
4
4
  import {FrequencyStateArchiveStep} from "../../chain/archiveStore/strategies/frequencyStateArchiveStrategy.js";
5
5
  import {BlockInputSource} from "../../chain/blocks/blockInput/index.js";
6
+ import {PayloadEnvelopeInputSource} from "../../chain/blocks/payloadEnvelopeInput/index.js";
6
7
  import {JobQueueItemType} from "../../chain/bls/index.js";
7
8
  import {AttestationErrorCode, BlockErrorCode} from "../../chain/errors/index.js";
8
9
  import {
@@ -237,6 +238,56 @@ export function createLodestarMetrics(
237
238
  }),
238
239
  },
239
240
 
241
+ payloadEnvelopeProcessorQueue: {
242
+ length: register.gauge({
243
+ name: "lodestar_payload_envelope_processor_queue_length",
244
+ help: "Count of total payload envelope processor queue length",
245
+ }),
246
+ droppedJobs: register.gauge({
247
+ name: "lodestar_payload_envelope_processor_queue_dropped_jobs_total",
248
+ help: "Count of total payload envelope processor queue dropped jobs",
249
+ }),
250
+ jobTime: register.histogram({
251
+ name: "lodestar_payload_envelope_processor_queue_job_time_seconds",
252
+ help: "Time to process payload envelope processor queue job in seconds",
253
+ buckets: [0.01, 0.1, 1, 4, 12],
254
+ }),
255
+ jobWaitTime: register.histogram({
256
+ name: "lodestar_payload_envelope_processor_queue_job_wait_time_seconds",
257
+ help: "Time from job added to the payload envelope processor queue to starting in seconds",
258
+ buckets: [0.01, 0.1, 1, 4, 12],
259
+ }),
260
+ concurrency: register.gauge({
261
+ name: "lodestar_payload_envelope_processor_queue_concurrency",
262
+ help: "Current concurrency of payload envelope processor queue",
263
+ }),
264
+ },
265
+
266
+ unfinalizedPayloadEnvelopeWritesQueue: {
267
+ length: register.gauge({
268
+ name: "lodestar_unfinalized_payload_envelope_writes_queue_length",
269
+ help: "Count of total unfinalized payload envelope writes queue length",
270
+ }),
271
+ droppedJobs: register.gauge({
272
+ name: "lodestar_unfinalized_payload_envelope_writes_queue_dropped_jobs_total",
273
+ help: "Count of total unfinalized payload envelope writes queue dropped jobs",
274
+ }),
275
+ jobTime: register.histogram({
276
+ name: "lodestar_unfinalized_payload_envelope_writes_queue_job_time_seconds",
277
+ help: "Time to process unfinalized payload envelope writes queue job in seconds",
278
+ buckets: [0.01, 0.1, 1, 4, 12],
279
+ }),
280
+ jobWaitTime: register.histogram({
281
+ name: "lodestar_unfinalized_payload_envelope_writes_queue_job_wait_time_seconds",
282
+ help: "Time from job added to the unfinalized payload envelope writes queue to starting in seconds",
283
+ buckets: [0.01, 0.1, 1, 4, 12],
284
+ }),
285
+ concurrency: register.gauge({
286
+ name: "lodestar_unfinalized_payload_envelope_writes_queue_concurrency",
287
+ help: "Current concurrency of unfinalized payload envelope writes queue",
288
+ }),
289
+ },
290
+
240
291
  engineHttpProcessorQueue: {
241
292
  length: register.gauge({
242
293
  name: "lodestar_engine_http_processor_queue_length",
@@ -925,6 +976,18 @@ export function createLodestarMetrics(
925
976
  labelNames: ["reason"],
926
977
  }),
927
978
  },
979
+ importPayload: {
980
+ bySource: register.gauge<{source: PayloadEnvelopeInputSource}>({
981
+ name: "lodestar_import_payload_by_source_total",
982
+ help: "Total number of imported execution payload envelopes by source",
983
+ labelNames: ["source"],
984
+ }),
985
+ columnsBySource: register.gauge<{source: PayloadEnvelopeInputSource}>({
986
+ name: "lodestar_import_payload_columns_by_source_total",
987
+ help: "Total number of payload-attached columns (sampled columns for Gloas) by source",
988
+ labelNames: ["source"],
989
+ }),
990
+ },
928
991
  engineNotifyNewPayloadResult: register.gauge<{result: ExecutionPayloadStatus}>({
929
992
  name: "lodestar_execution_engine_notify_new_payload_result_total",
930
993
  help: "The total result of calling notifyNewPayload execution engine api",
@@ -1495,6 +1558,20 @@ export function createLodestarMetrics(
1495
1558
  help: "Number of BlockInputs created via a data column being seen first",
1496
1559
  }),
1497
1560
  },
1561
+ payloadEnvelopeInput: {
1562
+ count: register.gauge({
1563
+ name: "lodestar_seen_payload_envelope_input_cache_size",
1564
+ help: "Number of cached PayloadEnvelopeInputs",
1565
+ }),
1566
+ serializedObjectRefs: register.gauge({
1567
+ name: "lodestar_seen_payload_envelope_input_cache_serialized_object_refs",
1568
+ help: "Number of serialized-cache object refs retained by cached PayloadEnvelopeInputs",
1569
+ }),
1570
+ created: register.counter({
1571
+ name: "lodestar_seen_payload_envelope_input_cache_items_created_total",
1572
+ help: "Number of PayloadEnvelopeInputs created",
1573
+ }),
1574
+ },
1498
1575
  },
1499
1576
 
1500
1577
  processFinalizedCheckpoint: {
@@ -721,7 +721,7 @@ export class Network implements INetwork {
721
721
 
722
722
  try {
723
723
  // messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
724
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
724
+ // https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
725
725
  await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
726
726
  await this.publishLightClientFinalityUpdate(finalityUpdate);
727
727
  } catch (e) {
@@ -738,7 +738,7 @@ export class Network implements INetwork {
738
738
 
739
739
  try {
740
740
  // messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
741
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
741
+ // https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
742
742
  await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
743
743
  await this.publishLightClientOptimisticUpdate(optimisticUpdate);
744
744
  } catch (e) {
@@ -1,11 +1,14 @@
1
- import {ForkName} from "@lodestar/params";
1
+ import {ForkName, isForkPostGloas} from "@lodestar/params";
2
2
  import {SlotOptionalRoot, SlotRootHex} from "@lodestar/types";
3
3
  import {
4
+ getBeaconBlockRootFromDataColumnSidecarSerialized,
5
+ getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized,
4
6
  getBlockRootFromBeaconAttestationSerialized,
5
7
  getBlockRootFromSignedAggregateAndProofSerialized,
6
8
  getSlotFromBeaconAttestationSerialized,
7
9
  getSlotFromBlobSidecarSerialized,
8
10
  getSlotFromDataColumnSidecarSerialized,
11
+ getSlotFromExecutionPayloadEnvelopeSerialized,
9
12
  getSlotFromSignedAggregateAndProofSerialized,
10
13
  getSlotFromSignedBeaconBlockSerialized,
11
14
  } from "../../util/sszBytes.js";
@@ -52,13 +55,23 @@ export function createExtractBlockSlotRootFns(): ExtractSlotRootFns {
52
55
  }
53
56
  return {slot};
54
57
  },
55
- [GossipType.data_column_sidecar]: (data: Uint8Array): SlotOptionalRoot | null => {
56
- const slot = getSlotFromDataColumnSidecarSerialized(data);
57
-
58
+ [GossipType.data_column_sidecar]: (data: Uint8Array, fork: ForkName): SlotOptionalRoot | null => {
59
+ const slot = getSlotFromDataColumnSidecarSerialized(data, fork);
58
60
  if (slot === null) {
59
61
  return null;
60
62
  }
61
- return {slot};
63
+
64
+ const root = isForkPostGloas(fork) ? getBeaconBlockRootFromDataColumnSidecarSerialized(data) : null;
65
+ return root !== null ? {slot, root} : {slot};
66
+ },
67
+ [GossipType.execution_payload]: (data: Uint8Array): SlotRootHex | null => {
68
+ const slot = getSlotFromExecutionPayloadEnvelopeSerialized(data);
69
+ const root = getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized(data);
70
+
71
+ if (slot === null || root === null) {
72
+ return null;
73
+ }
74
+ return {slot, root};
62
75
  },
63
76
  };
64
77
  }
@@ -30,6 +30,7 @@ import {
30
30
  IBlockInput,
31
31
  isBlockInputColumns,
32
32
  } from "../../chain/blocks/blockInput/index.js";
33
+ import {PayloadEnvelopeInputSource} from "../../chain/blocks/payloadEnvelopeInput/index.js";
33
34
  import {BlobSidecarValidation} from "../../chain/blocks/types.js";
34
35
  import {ChainEvent} from "../../chain/emitter.js";
35
36
  import {
@@ -42,6 +43,8 @@ import {
42
43
  BlockGossipError,
43
44
  DataColumnSidecarErrorCode,
44
45
  DataColumnSidecarGossipError,
46
+ ExecutionPayloadEnvelopeError,
47
+ ExecutionPayloadEnvelopeErrorCode,
45
48
  GossipAction,
46
49
  GossipActionError,
47
50
  SyncCommitteeError,
@@ -616,6 +619,13 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
616
619
  });
617
620
  });
618
621
  }
622
+
623
+ // TODO GLOAS: In Gloas, also add column to PayloadEnvelopeInput and notify the payload processor:
624
+ // const payloadInput = chain.seenPayloadEnvelopeInput.get(blockRootHex);
625
+ // if (payloadInput) {
626
+ // payloadInput.addColumn({columnSidecar, source: BlockInputSource.gossip, seenTimestampSec, peerIdStr});
627
+ // chain.processExecutionPayload(payloadInput, {validSignature: true});
628
+ // }
619
629
  },
620
630
 
621
631
  [GossipType.beacon_aggregate_and_proof]: async ({
@@ -826,17 +836,43 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
826
836
  [GossipType.execution_payload]: async ({
827
837
  gossipData,
828
838
  topic,
839
+ peerIdStr,
829
840
  seenTimestampSec,
830
841
  }: GossipHandlerParamGeneric<GossipType.execution_payload>) => {
831
842
  const {serializedData} = gossipData;
832
843
  const executionPayloadEnvelope = sszDeserialize(topic, serializedData);
844
+ // TODO GLOAS: handle BLOCK_ROOT_UNKNOWN error to trigger sync
833
845
  await validateGossipExecutionPayloadEnvelope(chain, executionPayloadEnvelope);
834
846
 
835
847
  const slot = executionPayloadEnvelope.message.slot;
836
848
  const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
837
849
  metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
850
+ chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, executionPayloadEnvelope);
851
+
852
+ const blockRootHex = toRootHex(executionPayloadEnvelope.message.beaconBlockRoot);
853
+ const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
854
+
855
+ if (!payloadInput) {
856
+ // This shouldn't happen because beacon block should have been imported and thus payload input should have been created.
857
+ throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
858
+ code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING,
859
+ blockRoot: blockRootHex,
860
+ });
861
+ }
838
862
 
839
- // TODO GLOAS: Handle valid envelope. Need an import flow that calls `processExecutionPayloadEnvelope` and fork choice
863
+ chain.serializedCache.set(executionPayloadEnvelope, serializedData);
864
+
865
+ payloadInput.addPayloadEnvelope({
866
+ envelope: executionPayloadEnvelope,
867
+ source: PayloadEnvelopeInputSource.gossip,
868
+ seenTimestampSec,
869
+ peerIdStr,
870
+ });
871
+
872
+ // TODO GLOAS: Emit execution_payload_gossip event for gossip receipt.
873
+ chain.processExecutionPayload(payloadInput, {validSignature: true}).catch((e) => {
874
+ chain.logger.debug("Error processing execution payload from gossip", {slot, root: blockRootHex}, e as Error);
875
+ });
840
876
  },
841
877
  [GossipType.payload_attestation_message]: async ({
842
878
  gossipData,
@@ -58,7 +58,7 @@ export type ReqRespBeaconNodeOpts = ReqRespOpts & {disableLightClientServer?: bo
58
58
  * Implementation of Ethereum Consensus p2p Req/Resp domain.
59
59
  * For the spec that this code is based on, see:
60
60
  * https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#the-reqresp-domain
61
- * https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#the-reqresp-domain
61
+ * https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#the-reqresp-domain
62
62
  */
63
63
  export class ReqRespBeaconNode extends ReqResp {
64
64
  private readonly metadataController: MetadataController;
@@ -127,7 +127,7 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
127
127
  private wsValidated = false;
128
128
 
129
129
  /**
130
- * From https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/weak-subjectivity.md
130
+ * From https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/phase0/weak-subjectivity.md
131
131
  *
132
132
  *
133
133
  * If
@@ -59,7 +59,7 @@ export const BATCH_BUFFER_SIZE = Math.ceil(10 / EPOCHS_PER_BATCH);
59
59
 
60
60
  /**
61
61
  * Maximum number of concurrent requests to perform with a SyncChain.
62
- * This is according to the spec https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md
62
+ * This is according to the spec https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/phase0/p2p-interface.md
63
63
  */
64
64
  export const MAX_CONCURRENT_REQUESTS = 2;
65
65
 
@@ -8,6 +8,7 @@ import {
8
8
  ForkSeq,
9
9
  MAX_COMMITTEES_PER_SLOT,
10
10
  isForkPostElectra,
11
+ isForkPostGloas,
11
12
  } from "@lodestar/params";
12
13
  import {BLSSignature, CommitteeIndex, RootHex, Slot, ValidatorIndex, ssz} from "@lodestar/types";
13
14
 
@@ -398,23 +399,102 @@ export function getSlotFromBlobSidecarSerialized(data: Uint8Array): Slot | null
398
399
  }
399
400
 
400
401
  /**
402
+ * Pre-Gloas DataColumnSidecar:
401
403
  * {
402
- index: ColumnIndex [ fixed - 8 bytes],
403
- column: DataColumn BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_CELL * <some non fixed length>,
404
- kzgCommitments: denebSsz.BlobKzgCommitments,
405
- kzgProofs: denebSsz.KZGProofs,
406
- signedBlockHeader: phase0Ssz.SignedBeaconBlockHeader,
407
- kzgCommitmentsInclusionProof: KzgCommitmentsInclusionProof,
404
+ * index: ColumnIndex [fixed - 8 bytes],
405
+ * column: DataColumn (offset - 4 bytes),
406
+ * kzgCommitments: (offset - 4 bytes),
407
+ * kzgProofs: (offset - 4 bytes),
408
+ * signedBlockHeader: (offset - 4 bytes) -> slot at variable offset after fixed header
409
+ * kzgCommitmentsInclusionProof: (offset - 4 bytes),
410
+ * }
411
+ * Post-Gloas DataColumnSidecar:
412
+ * {
413
+ * index: ColumnIndex [8 bytes],
414
+ * column: DataColumn (offset - 4 bytes),
415
+ * kzgProofs: (offset - 4 bytes),
416
+ * slot: Slot [8 bytes] - at offset 16,
417
+ * beaconBlockRoot: Root [32 bytes] - at offset 24,
418
+ * }
419
+ */
420
+ const SLOT_BYTES_POSITION_IN_SIGNED_DATA_COLUMN_SIDECAR_PRE_GLOAS = 20;
421
+ const SLOT_BYTES_POSITION_IN_SIGNED_DATA_COLUMN_SIDECAR_POST_GLOAS = 16;
422
+ const BEACON_BLOCK_ROOT_POSITION_IN_GLOAS_DATA_COLUMN_SIDECAR = 24;
423
+
424
+ export function getSlotFromDataColumnSidecarSerialized(data: Uint8Array, fork: ForkName): Slot | null {
425
+ const offset = isForkPostGloas(fork)
426
+ ? SLOT_BYTES_POSITION_IN_SIGNED_DATA_COLUMN_SIDECAR_POST_GLOAS
427
+ : SLOT_BYTES_POSITION_IN_SIGNED_DATA_COLUMN_SIDECAR_PRE_GLOAS;
428
+
429
+ if (data.length < offset + SLOT_SIZE) {
430
+ return null;
408
431
  }
432
+
433
+ return getSlotFromOffset(data, offset);
434
+ }
435
+
436
+ export function getBeaconBlockRootFromDataColumnSidecarSerialized(data: Uint8Array): RootHex | null {
437
+ if (data.length < BEACON_BLOCK_ROOT_POSITION_IN_GLOAS_DATA_COLUMN_SIDECAR + ROOT_SIZE) {
438
+ return null;
439
+ }
440
+
441
+ blockRootBuf.set(
442
+ data.subarray(
443
+ BEACON_BLOCK_ROOT_POSITION_IN_GLOAS_DATA_COLUMN_SIDECAR,
444
+ BEACON_BLOCK_ROOT_POSITION_IN_GLOAS_DATA_COLUMN_SIDECAR + ROOT_SIZE
445
+ )
446
+ );
447
+ return "0x" + blockRootBuf.toString("hex");
448
+ }
449
+
450
+ /**
451
+ * SignedExecutionPayloadEnvelope SSZ Layout:
452
+ * ├─ 4 bytes: message offset (points to byte 100)
453
+ * ├─ 96 bytes: signature
454
+ * └─ ExecutionPayloadEnvelope (starts at byte 100):
455
+ * ├─ 4 bytes: payload offset
456
+ * ├─ 4 bytes: executionRequests offset
457
+ * ├─ 8 bytes: builderIndex (offset 108-115)
458
+ * ├─ 32 bytes: beaconBlockRoot (offset 116-147)
459
+ * ├─ 8 bytes: slot (offset 148-155)
460
+ * └─ 32 bytes: stateRoot (offset 156-187)
409
461
  */
462
+ const SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MESSAGE_OFFSET = 4;
463
+ const SIGNED_EXECUTION_PAYLOAD_ENVELOPE_SIGNATURE_SIZE = 96;
464
+ const EXECUTION_PAYLOAD_ENVELOPE_PAYLOAD_OFFSET = 4;
465
+ const EXECUTION_PAYLOAD_ENVELOPE_REQUESTS_OFFSET = 4;
466
+ const EXECUTION_PAYLOAD_ENVELOPE_BUILDER_INDEX_SIZE = 8;
467
+
468
+ const BEACON_BLOCK_ROOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE =
469
+ SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MESSAGE_OFFSET +
470
+ SIGNED_EXECUTION_PAYLOAD_ENVELOPE_SIGNATURE_SIZE +
471
+ EXECUTION_PAYLOAD_ENVELOPE_PAYLOAD_OFFSET +
472
+ EXECUTION_PAYLOAD_ENVELOPE_REQUESTS_OFFSET +
473
+ EXECUTION_PAYLOAD_ENVELOPE_BUILDER_INDEX_SIZE; // 116
474
+
475
+ const SLOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE =
476
+ BEACON_BLOCK_ROOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + ROOT_SIZE; // 148
477
+
478
+ export function getSlotFromExecutionPayloadEnvelopeSerialized(data: Uint8Array): Slot | null {
479
+ if (data.length < SLOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + SLOT_SIZE) {
480
+ return null;
481
+ }
410
482
 
411
- const SLOT_BYTES_POSITION_IN_SIGNED_DATA_COLUMN_SIDECAR = 20;
412
- export function getSlotFromDataColumnSidecarSerialized(data: Uint8Array): Slot | null {
413
- if (data.length < SLOT_BYTES_POSITION_IN_SIGNED_DATA_COLUMN_SIDECAR + SLOT_SIZE) {
483
+ return getSlotFromOffset(data, SLOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE);
484
+ }
485
+
486
+ export function getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized(data: Uint8Array): RootHex | null {
487
+ if (data.length < BEACON_BLOCK_ROOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + ROOT_SIZE) {
414
488
  return null;
415
489
  }
416
490
 
417
- return getSlotFromOffset(data, SLOT_BYTES_POSITION_IN_SIGNED_DATA_COLUMN_SIDECAR);
491
+ blockRootBuf.set(
492
+ data.subarray(
493
+ BEACON_BLOCK_ROOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE,
494
+ BEACON_BLOCK_ROOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + ROOT_SIZE
495
+ )
496
+ );
497
+ return "0x" + blockRootBuf.toString("hex");
418
498
  }
419
499
 
420
500
  /**
@@ -1,7 +0,0 @@
1
- import { CheckpointWithHex } from "@lodestar/fork-choice";
2
- import { IBeaconChain } from "../../interface.js";
3
- /**
4
- * Archives execution payload envelopes from hot DB to archive DB after finalization.
5
- */
6
- export declare function archiveExecutionPayloadEnvelopes(chain: IBeaconChain, _finalized: CheckpointWithHex): Promise<void>;
7
- //# sourceMappingURL=archivePayloads.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"archivePayloads.d.ts","sourceRoot":"","sources":["../../../../src/chain/archiveStore/utils/archivePayloads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAEhD;;GAEG;AACH,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,iBAAiB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAKf"}
@@ -1,10 +0,0 @@
1
- /**
2
- * Archives execution payload envelopes from hot DB to archive DB after finalization.
3
- */
4
- export async function archiveExecutionPayloadEnvelopes(chain, _finalized) {
5
- const finalizedBlock = chain.forkChoice.getFinalizedBlock();
6
- if (!finalizedBlock)
7
- return;
8
- // TODO GLOAS: Implement payload envelope archival after epbs fork choice changes are merged
9
- }
10
- //# sourceMappingURL=archivePayloads.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"archivePayloads.js","sourceRoot":"","sources":["../../../../src/chain/archiveStore/utils/archivePayloads.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,KAAmB,EACnB,UAA6B,EACd;IACf,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;IAC5D,IAAI,CAAC,cAAc;QAAE,OAAO;IAE5B,4FAA4F;AAFhE,CAG7B"}
@@ -1,15 +0,0 @@
1
- import { RootHex, Slot } from "@lodestar/types";
2
- /**
3
- * Cache to prevent processing multiple execution payload envelopes for the same block root.
4
- * Only one builder qualifies to submit an execution payload for a given slot.
5
- * We only keep track of envelopes of unfinalized slots.
6
- * [IGNORE] The node has not seen another valid `SignedExecutionPayloadEnvelope` for this block root.
7
- */
8
- export declare class SeenExecutionPayloadEnvelopes {
9
- private readonly slotByBlockRoot;
10
- private finalizedSlot;
11
- isKnown(blockRoot: RootHex): boolean;
12
- add(blockRoot: RootHex, slot: Slot): void;
13
- prune(finalizedSlot: Slot): void;
14
- }
15
- //# sourceMappingURL=seenExecutionPayloadEnvelope.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seenExecutionPayloadEnvelope.d.ts","sourceRoot":"","sources":["../../../src/chain/seenCache/seenExecutionPayloadEnvelope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAE9C;;;;;GAKG;AACH,qBAAa,6BAA6B;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4B;IAC5D,OAAO,CAAC,aAAa,CAAW;IAEhC,OAAO,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAEnC;IAED,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAMxC;IAED,KAAK,CAAC,aAAa,EAAE,IAAI,GAAG,IAAI,CAQ/B;CACF"}