@lodestar/beacon-node 1.42.0-dev.7e96447c23 → 1.42.0-dev.84f3b9f030

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 (122) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +13 -1
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
  5. package/lib/chain/archiveStore/archiveStore.js +1 -0
  6. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  7. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +3 -3
  8. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  9. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +6 -4
  10. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  11. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts +2 -2
  12. package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
  13. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
  14. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  15. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
  16. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  17. package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/worker.js +1 -4
  19. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  20. package/lib/chain/archiveStore/interface.d.ts +1 -0
  21. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  22. package/lib/chain/blocks/importBlock.d.ts.map +1 -1
  23. package/lib/chain/blocks/importBlock.js +17 -17
  24. package/lib/chain/blocks/importBlock.js.map +1 -1
  25. package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
  26. package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
  27. package/lib/chain/blocks/importExecutionPayload.js +76 -48
  28. package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
  29. package/lib/chain/blocks/index.d.ts.map +1 -1
  30. package/lib/chain/blocks/index.js +2 -1
  31. package/lib/chain/blocks/index.js.map +1 -1
  32. package/lib/chain/blocks/types.d.ts +20 -14
  33. package/lib/chain/blocks/types.d.ts.map +1 -1
  34. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +2 -2
  35. package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
  36. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +1 -1
  37. package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
  38. package/lib/chain/chain.d.ts +1 -0
  39. package/lib/chain/chain.d.ts.map +1 -1
  40. package/lib/chain/chain.js +14 -0
  41. package/lib/chain/chain.js.map +1 -1
  42. package/lib/chain/interface.d.ts +1 -0
  43. package/lib/chain/interface.d.ts.map +1 -1
  44. package/lib/chain/options.d.ts +1 -0
  45. package/lib/chain/options.d.ts.map +1 -1
  46. package/lib/chain/options.js +1 -0
  47. package/lib/chain/options.js.map +1 -1
  48. package/lib/network/gossip/topic.d.ts +2 -729
  49. package/lib/network/gossip/topic.d.ts.map +1 -1
  50. package/lib/network/interface.d.ts +3 -1
  51. package/lib/network/interface.d.ts.map +1 -1
  52. package/lib/network/libp2p/index.d.ts.map +1 -1
  53. package/lib/network/libp2p/index.js +5 -0
  54. package/lib/network/libp2p/index.js.map +1 -1
  55. package/lib/network/network.d.ts +3 -1
  56. package/lib/network/network.d.ts.map +1 -1
  57. package/lib/network/network.js +6 -0
  58. package/lib/network/network.js.map +1 -1
  59. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  60. package/lib/network/processor/gossipHandlers.js +15 -8
  61. package/lib/network/processor/gossipHandlers.js.map +1 -1
  62. package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
  63. package/lib/network/reqresp/ReqRespBeaconNode.js +9 -0
  64. package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
  65. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts +8 -0
  66. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -0
  67. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +69 -0
  68. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -0
  69. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts +6 -0
  70. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -0
  71. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +28 -0
  72. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -0
  73. package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
  74. package/lib/network/reqresp/handlers/index.js +11 -1
  75. package/lib/network/reqresp/handlers/index.js.map +1 -1
  76. package/lib/network/reqresp/protocols.d.ts +2 -0
  77. package/lib/network/reqresp/protocols.d.ts.map +1 -1
  78. package/lib/network/reqresp/protocols.js +10 -0
  79. package/lib/network/reqresp/protocols.js.map +1 -1
  80. package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
  81. package/lib/network/reqresp/rateLimit.js +8 -0
  82. package/lib/network/reqresp/rateLimit.js.map +1 -1
  83. package/lib/network/reqresp/score.d.ts.map +1 -1
  84. package/lib/network/reqresp/score.js +2 -0
  85. package/lib/network/reqresp/score.js.map +1 -1
  86. package/lib/network/reqresp/types.d.ts +8 -2
  87. package/lib/network/reqresp/types.d.ts.map +1 -1
  88. package/lib/network/reqresp/types.js +7 -1
  89. package/lib/network/reqresp/types.js.map +1 -1
  90. package/lib/util/types.d.ts +2 -0
  91. package/lib/util/types.d.ts.map +1 -1
  92. package/lib/util/types.js +1 -0
  93. package/lib/util/types.js.map +1 -1
  94. package/package.json +16 -16
  95. package/src/api/impl/beacon/blocks/index.ts +15 -1
  96. package/src/chain/archiveStore/archiveStore.ts +1 -0
  97. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +6 -5
  98. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +2 -1
  99. package/src/chain/archiveStore/historicalState/types.ts +2 -0
  100. package/src/chain/archiveStore/historicalState/worker.ts +1 -5
  101. package/src/chain/archiveStore/interface.ts +1 -0
  102. package/src/chain/blocks/importBlock.ts +18 -17
  103. package/src/chain/blocks/importExecutionPayload.ts +84 -53
  104. package/src/chain/blocks/index.ts +2 -1
  105. package/src/chain/blocks/types.ts +25 -14
  106. package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +4 -4
  107. package/src/chain/chain.ts +18 -0
  108. package/src/chain/interface.ts +1 -0
  109. package/src/chain/options.ts +2 -0
  110. package/src/network/interface.ts +14 -1
  111. package/src/network/libp2p/index.ts +5 -0
  112. package/src/network/network.ts +29 -1
  113. package/src/network/processor/gossipHandlers.ts +16 -8
  114. package/src/network/reqresp/ReqRespBeaconNode.ts +13 -0
  115. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +94 -0
  116. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +43 -0
  117. package/src/network/reqresp/handlers/index.ts +12 -0
  118. package/src/network/reqresp/protocols.ts +12 -0
  119. package/src/network/reqresp/rateLimit.ts +18 -0
  120. package/src/network/reqresp/score.ts +2 -0
  121. package/src/network/reqresp/types.ts +13 -0
  122. package/src/util/types.ts +6 -0
@@ -38,7 +38,12 @@ import {
38
38
  import {BlockInputSource} from "../chain/blocks/blockInput/types.js";
39
39
  import {CustodyConfig} from "../util/dataColumns.js";
40
40
  import {PeerIdStr} from "../util/peerId.js";
41
- import {BeaconBlocksByRootRequest, BlobSidecarsByRootRequest, DataColumnSidecarsByRootRequest} from "../util/types.js";
41
+ import {
42
+ BeaconBlocksByRootRequest,
43
+ BlobSidecarsByRootRequest,
44
+ DataColumnSidecarsByRootRequest,
45
+ ExecutionPayloadEnvelopesByRootRequest,
46
+ } from "../util/types.js";
42
47
  import {INetworkCorePublic} from "./core/types.js";
43
48
  import {INetworkEventBus} from "./events.js";
44
49
  import {GossipType} from "./gossip/interface.js";
@@ -82,6 +87,14 @@ export interface INetwork extends INetworkCorePublic {
82
87
  peerId: PeerIdStr,
83
88
  request: DataColumnSidecarsByRootRequest
84
89
  ): Promise<fulu.DataColumnSidecar[]>;
90
+ sendExecutionPayloadEnvelopesByRange(
91
+ peerId: PeerIdStr,
92
+ request: gloas.ExecutionPayloadEnvelopesByRangeRequest
93
+ ): Promise<gloas.SignedExecutionPayloadEnvelope[]>;
94
+ sendExecutionPayloadEnvelopesByRoot(
95
+ peerId: PeerIdStr,
96
+ request: ExecutionPayloadEnvelopesByRootRequest
97
+ ): Promise<gloas.SignedExecutionPayloadEnvelope[]>;
85
98
 
86
99
  // Gossip
87
100
  publishBeaconBlock(signedBlock: SignedBeaconBlock): Promise<number>;
@@ -88,6 +88,9 @@ export async function createNodeJsLibp2p(
88
88
  );
89
89
  }
90
90
  if (networkOpts.quic) {
91
+ const quicMultiaddrs = localMultiaddrs.filter((ma) => ma.includes("/quic-v1"));
92
+ const hasIpv4Quic = quicMultiaddrs.some((ma) => ma.includes("/ip4/"));
93
+ const hasIpv6Quic = quicMultiaddrs.some((ma) => ma.includes("/ip6/"));
91
94
  transports.unshift(
92
95
  quic({
93
96
  handshakeTimeout: 5_000,
@@ -96,6 +99,8 @@ export async function createNodeJsLibp2p(
96
99
  maxConcurrentStreamLimit: 256,
97
100
  maxStreamData: 10_000_000,
98
101
  maxConnectionData: 15_000_000,
102
+ ipv4: hasIpv4Quic,
103
+ ipv6: hasIpv6Quic,
99
104
  })
100
105
  );
101
106
  }
@@ -40,7 +40,12 @@ import {IClock} from "../util/clock.js";
40
40
  import {CustodyConfig} from "../util/dataColumns.js";
41
41
  import {PeerIdStr, peerIdToString} from "../util/peerId.js";
42
42
  import {promiseAllMaybeAsync} from "../util/promises.js";
43
- import {BeaconBlocksByRootRequest, BlobSidecarsByRootRequest, DataColumnSidecarsByRootRequest} from "../util/types.js";
43
+ import {
44
+ BeaconBlocksByRootRequest,
45
+ BlobSidecarsByRootRequest,
46
+ DataColumnSidecarsByRootRequest,
47
+ ExecutionPayloadEnvelopesByRootRequest,
48
+ } from "../util/types.js";
44
49
  import {INetworkCore, NetworkCore, WorkerNetworkCore} from "./core/index.js";
45
50
  import {INetworkEventBus, NetworkEvent, NetworkEventBus, NetworkEventData} from "./events.js";
46
51
  import {getActiveForkBoundaries} from "./forks.js";
@@ -636,6 +641,29 @@ export class Network implements INetwork {
636
641
  );
637
642
  }
638
643
 
644
+ async sendExecutionPayloadEnvelopesByRange(
645
+ peerId: PeerIdStr,
646
+ request: gloas.ExecutionPayloadEnvelopesByRangeRequest
647
+ ): Promise<gloas.SignedExecutionPayloadEnvelope[]> {
648
+ return collectMaxResponseTyped(
649
+ this.sendReqRespRequest(peerId, ReqRespMethod.ExecutionPayloadEnvelopesByRange, [Version.V1], request),
650
+ request.count,
651
+ responseSszTypeByMethod[ReqRespMethod.ExecutionPayloadEnvelopesByRange]
652
+ );
653
+ }
654
+
655
+ async sendExecutionPayloadEnvelopesByRoot(
656
+ peerId: PeerIdStr,
657
+ request: ExecutionPayloadEnvelopesByRootRequest
658
+ ): Promise<gloas.SignedExecutionPayloadEnvelope[]> {
659
+ return collectMaxResponseTyped(
660
+ this.sendReqRespRequest(peerId, ReqRespMethod.ExecutionPayloadEnvelopesByRoot, [Version.V1], request),
661
+ request.length,
662
+ responseSszTypeByMethod[ReqRespMethod.ExecutionPayloadEnvelopesByRoot],
663
+ this.chain.serializedCache
664
+ );
665
+ }
666
+
639
667
  private sendReqRespRequest<Req>(
640
668
  peerId: PeerIdStr,
641
669
  method: ReqRespMethod,
@@ -841,16 +841,17 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
841
841
  seenTimestampSec,
842
842
  }: GossipHandlerParamGeneric<GossipType.execution_payload>) => {
843
843
  const {serializedData} = gossipData;
844
- const executionPayloadEnvelope = sszDeserialize(topic, serializedData);
844
+ const signedEnvelope = sszDeserialize(topic, serializedData);
845
+ const envelope = signedEnvelope.message;
845
846
  // TODO GLOAS: handle BLOCK_ROOT_UNKNOWN error to trigger sync
846
- await validateGossipExecutionPayloadEnvelope(chain, executionPayloadEnvelope);
847
+ await validateGossipExecutionPayloadEnvelope(chain, signedEnvelope);
847
848
 
848
- const slot = executionPayloadEnvelope.message.slot;
849
+ const slot = envelope.slot;
849
850
  const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
850
851
  metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
851
- chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, executionPayloadEnvelope);
852
+ chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, signedEnvelope);
852
853
 
853
- const blockRootHex = toRootHex(executionPayloadEnvelope.message.beaconBlockRoot);
854
+ const blockRootHex = toRootHex(envelope.beaconBlockRoot);
854
855
  const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
855
856
 
856
857
  if (!payloadInput) {
@@ -861,16 +862,23 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
861
862
  });
862
863
  }
863
864
 
864
- chain.serializedCache.set(executionPayloadEnvelope, serializedData);
865
+ chain.serializedCache.set(signedEnvelope, serializedData);
865
866
 
866
867
  payloadInput.addPayloadEnvelope({
867
- envelope: executionPayloadEnvelope,
868
+ envelope: signedEnvelope,
868
869
  source: PayloadEnvelopeInputSource.gossip,
869
870
  seenTimestampSec,
870
871
  peerIdStr,
871
872
  });
872
873
 
873
- // TODO GLOAS: Emit execution_payload_gossip event for gossip receipt.
874
+ chain.emitter.emit(routes.events.EventType.executionPayloadGossip, {
875
+ slot,
876
+ builderIndex: envelope.builderIndex,
877
+ blockHash: toRootHex(envelope.payload.blockHash),
878
+ blockRoot: blockRootHex,
879
+ stateRoot: toRootHex(envelope.stateRoot),
880
+ });
881
+
874
882
  chain.processExecutionPayload(payloadInput, {validSignature: true}).catch((e) => {
875
883
  chain.logger.debug("Error processing execution payload from gossip", {slot, root: blockRootHex}, e as Error);
876
884
  });
@@ -297,6 +297,19 @@ export class ReqRespBeaconNode extends ReqResp {
297
297
  );
298
298
  }
299
299
 
300
+ if (ForkSeq[fork] >= ForkSeq.gloas) {
301
+ protocolsAtFork.push(
302
+ [
303
+ protocols.ExecutionPayloadEnvelopesByRoot(fork, this.config),
304
+ this.getHandler(ReqRespMethod.ExecutionPayloadEnvelopesByRoot),
305
+ ],
306
+ [
307
+ protocols.ExecutionPayloadEnvelopesByRange(fork, this.config),
308
+ this.getHandler(ReqRespMethod.ExecutionPayloadEnvelopesByRange),
309
+ ]
310
+ );
311
+ }
312
+
300
313
  return protocolsAtFork;
301
314
  }
302
315
 
@@ -0,0 +1,94 @@
1
+ import {ChainConfig} from "@lodestar/config";
2
+ import {PayloadStatus} from "@lodestar/fork-choice";
3
+ import {GENESIS_SLOT} from "@lodestar/params";
4
+ import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
5
+ import {computeEpochAtSlot} from "@lodestar/state-transition";
6
+ import {gloas} from "@lodestar/types";
7
+ import {IBeaconChain} from "../../../chain/index.js";
8
+ import {IBeaconDb} from "../../../db/index.js";
9
+
10
+ export async function* onExecutionPayloadEnvelopesByRange(
11
+ request: gloas.ExecutionPayloadEnvelopesByRangeRequest,
12
+ chain: IBeaconChain,
13
+ db: IBeaconDb
14
+ ): AsyncIterable<ResponseOutgoing> {
15
+ const {startSlot, count} = validateExecutionPayloadEnvelopesByRangeRequest(chain.config, request);
16
+ const endSlot = startSlot + count;
17
+
18
+ if (startSlot < chain.earliestAvailableSlot) {
19
+ return;
20
+ }
21
+
22
+ const finalized = db.executionPayloadEnvelopeArchive;
23
+ const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
24
+
25
+ // Finalized range of envelopes
26
+ if (startSlot <= finalizedSlot) {
27
+ for await (const {key, value: envelopeBytes} of finalized.binaryEntriesStream({
28
+ gte: startSlot,
29
+ lt: endSlot,
30
+ })) {
31
+ const slot = finalized.decodeKey(key);
32
+ yield {
33
+ data: envelopeBytes,
34
+ boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot)),
35
+ };
36
+ }
37
+ }
38
+
39
+ // Non-finalized range of envelopes
40
+ if (endSlot > finalizedSlot) {
41
+ const headBlock = chain.forkChoice.getHead();
42
+ const headRoot = headBlock.blockRoot;
43
+ const headChain = chain.forkChoice.getAllAncestorBlocks(headRoot, headBlock.payloadStatus);
44
+
45
+ // Iterate head chain with ascending block numbers
46
+ for (let i = headChain.length - 1; i >= 0; i--) {
47
+ const block = headChain[i];
48
+
49
+ if (block.slot >= startSlot && block.slot < endSlot) {
50
+ // Skip EMPTY blocks
51
+ if (block.payloadStatus !== PayloadStatus.FULL) {
52
+ continue;
53
+ }
54
+
55
+ const envelopeBytes = await chain.getSerializedExecutionPayloadEnvelope(block.slot, block.blockRoot);
56
+ if (!envelopeBytes) {
57
+ throw new ResponseError(
58
+ RespStatus.SERVER_ERROR,
59
+ `No envelope for root ${block.blockRoot} slot ${block.slot}, startSlot=${startSlot} endSlot=${endSlot} finalizedSlot=${finalizedSlot}`
60
+ );
61
+ }
62
+
63
+ yield {
64
+ data: envelopeBytes,
65
+ boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
66
+ };
67
+ } else if (block.slot >= endSlot) {
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ export function validateExecutionPayloadEnvelopesByRangeRequest(
75
+ config: ChainConfig,
76
+ request: gloas.ExecutionPayloadEnvelopesByRangeRequest
77
+ ): gloas.ExecutionPayloadEnvelopesByRangeRequest {
78
+ const {startSlot} = request;
79
+ let {count} = request;
80
+
81
+ if (count < 1) {
82
+ throw new ResponseError(RespStatus.INVALID_REQUEST, "count < 1");
83
+ }
84
+ // TODO: validate against MIN_EPOCHS_FOR_BLOCK_REQUESTS
85
+ if (startSlot < GENESIS_SLOT) {
86
+ throw new ResponseError(RespStatus.INVALID_REQUEST, "startSlot < genesis");
87
+ }
88
+
89
+ if (count > config.MAX_REQUEST_BLOCKS_DENEB) {
90
+ count = config.MAX_REQUEST_BLOCKS_DENEB;
91
+ }
92
+
93
+ return {startSlot, count};
94
+ }
@@ -0,0 +1,43 @@
1
+ import {ResponseOutgoing} from "@lodestar/reqresp";
2
+ import {computeEpochAtSlot} from "@lodestar/state-transition";
3
+ import {toRootHex} from "@lodestar/utils";
4
+ import {IBeaconChain} from "../../../chain/index.js";
5
+ import {IBeaconDb} from "../../../db/index.js";
6
+ import {ExecutionPayloadEnvelopesByRootRequest} from "../../../util/types.js";
7
+
8
+ export async function* onExecutionPayloadEnvelopesByRoot(
9
+ requestBody: ExecutionPayloadEnvelopesByRootRequest,
10
+ chain: IBeaconChain,
11
+ db: IBeaconDb
12
+ ): AsyncIterable<ResponseOutgoing> {
13
+ // Spec: [max(GLOAS_FORK_EPOCH, current_epoch - MIN_EPOCHS_FOR_BLOCK_REQUESTS), current_epoch]
14
+ const currentEpoch = chain.clock.currentEpoch;
15
+ const minimumRequestEpoch = Math.max(
16
+ currentEpoch - chain.config.MIN_EPOCHS_FOR_BLOCK_REQUESTS,
17
+ chain.config.GLOAS_FORK_EPOCH
18
+ );
19
+
20
+ for (const root of requestBody) {
21
+ const rootHex = toRootHex(root);
22
+ const block = chain.forkChoice.getBlockHexDefaultStatus(rootHex);
23
+ // If the block is not in fork choice, it may be finalized. Attempt to find its slot in block archive
24
+ const slot = block ? block.slot : await db.blockArchive.getSlotByRoot(root);
25
+
26
+ if (slot === null) {
27
+ continue;
28
+ }
29
+
30
+ const requestedEpoch = computeEpochAtSlot(slot);
31
+ if (requestedEpoch < minimumRequestEpoch) {
32
+ continue;
33
+ }
34
+
35
+ const envelopeBytes = await chain.getSerializedExecutionPayloadEnvelope(slot, rootHex);
36
+ if (envelopeBytes) {
37
+ yield {
38
+ data: envelopeBytes,
39
+ boundary: chain.config.getForkBoundaryAtEpoch(requestedEpoch),
40
+ };
41
+ }
42
+ }
43
+ }
@@ -6,6 +6,7 @@ import {
6
6
  BeaconBlocksByRootRequestType,
7
7
  BlobSidecarsByRootRequestType,
8
8
  DataColumnSidecarsByRootRequestType,
9
+ ExecutionPayloadEnvelopesByRootRequestType,
9
10
  } from "../../../util/types.js";
10
11
  import {GetReqRespHandlerFn, ReqRespMethod} from "../types.js";
11
12
  import {onBeaconBlocksByRange} from "./beaconBlocksByRange.js";
@@ -14,6 +15,8 @@ import {onBlobSidecarsByRange} from "./blobSidecarsByRange.js";
14
15
  import {onBlobSidecarsByRoot} from "./blobSidecarsByRoot.js";
15
16
  import {onDataColumnSidecarsByRange} from "./dataColumnSidecarsByRange.js";
16
17
  import {onDataColumnSidecarsByRoot} from "./dataColumnSidecarsByRoot.js";
18
+ import {onExecutionPayloadEnvelopesByRange} from "./executionPayloadEnvelopesByRange.js";
19
+ import {onExecutionPayloadEnvelopesByRoot} from "./executionPayloadEnvelopesByRoot.js";
17
20
  import {onLightClientBootstrap} from "./lightClientBootstrap.js";
18
21
  import {onLightClientFinalityUpdate} from "./lightClientFinalityUpdate.js";
19
22
  import {onLightClientOptimisticUpdate} from "./lightClientOptimisticUpdate.js";
@@ -62,6 +65,15 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
62
65
  return onDataColumnSidecarsByRoot(body, chain, db, peerId, peerClient);
63
66
  },
64
67
 
68
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: (req) => {
69
+ const body = ExecutionPayloadEnvelopesByRootRequestType(chain.config).deserialize(req.data);
70
+ return onExecutionPayloadEnvelopesByRoot(body, chain, db);
71
+ },
72
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: (req) => {
73
+ const body = ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest.deserialize(req.data);
74
+ return onExecutionPayloadEnvelopesByRange(body, chain, db);
75
+ },
76
+
65
77
  [ReqRespMethod.LightClientBootstrap]: (req) => {
66
78
  const body = ssz.Root.deserialize(req.data);
67
79
  return onLightClientBootstrap(body, chain);
@@ -94,6 +94,18 @@ export const DataColumnSidecarsByRoot = toProtocol({
94
94
  contextBytesType: ContextBytesType.ForkDigest,
95
95
  });
96
96
 
97
+ export const ExecutionPayloadEnvelopesByRoot = toProtocol({
98
+ method: ReqRespMethod.ExecutionPayloadEnvelopesByRoot,
99
+ version: Version.V1,
100
+ contextBytesType: ContextBytesType.ForkDigest,
101
+ });
102
+
103
+ export const ExecutionPayloadEnvelopesByRange = toProtocol({
104
+ method: ReqRespMethod.ExecutionPayloadEnvelopesByRange,
105
+ version: Version.V1,
106
+ contextBytesType: ContextBytesType.ForkDigest,
107
+ });
108
+
97
109
  export const LightClientBootstrap = toProtocol({
98
110
  method: ReqRespMethod.LightClientBootstrap,
99
111
  version: Version.V1,
@@ -73,6 +73,24 @@ export const rateLimitQuotas: (fork: ForkName, config: BeaconConfig) => Record<R
73
73
  req.reduce((total, item) => total + item.columns.length, 0)
74
74
  ),
75
75
  },
76
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: {
77
+ byPeer: {quota: config.MAX_REQUEST_PAYLOADS, quotaTimeMs: 10_000},
78
+ getRequestCount: getRequestCountFn(
79
+ fork,
80
+ config,
81
+ ReqRespMethod.ExecutionPayloadEnvelopesByRoot,
82
+ (req) => req.length
83
+ ),
84
+ },
85
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: {
86
+ byPeer: {quota: config.MAX_REQUEST_BLOCKS_DENEB, quotaTimeMs: 10_000},
87
+ getRequestCount: getRequestCountFn(
88
+ fork,
89
+ config,
90
+ ReqRespMethod.ExecutionPayloadEnvelopesByRange,
91
+ (req) => req.count
92
+ ),
93
+ },
76
94
  [ReqRespMethod.LightClientBootstrap]: {
77
95
  // As similar in the nature of `Status` protocol so we use the same rate limits.
78
96
  byPeer: {quota: 5, quotaTimeMs: 15_000},
@@ -46,6 +46,8 @@ export function onOutgoingReqRespError(e: RequestError, method: ReqRespMethod):
46
46
  return PeerAction.LowToleranceError;
47
47
  case ReqRespMethod.BeaconBlocksByRange:
48
48
  case ReqRespMethod.BeaconBlocksByRoot:
49
+ case ReqRespMethod.ExecutionPayloadEnvelopesByRoot:
50
+ case ReqRespMethod.ExecutionPayloadEnvelopesByRange:
49
51
  return PeerAction.MidToleranceError;
50
52
  default:
51
53
  return null;
@@ -14,6 +14,7 @@ import {
14
14
  altair,
15
15
  deneb,
16
16
  fulu,
17
+ gloas,
17
18
  phase0,
18
19
  ssz,
19
20
  sszTypesFor,
@@ -25,6 +26,8 @@ import {
25
26
  BlobSidecarsByRootRequestType,
26
27
  DataColumnSidecarsByRootRequest,
27
28
  DataColumnSidecarsByRootRequestType,
29
+ ExecutionPayloadEnvelopesByRootRequest,
30
+ ExecutionPayloadEnvelopesByRootRequestType,
28
31
  } from "../../util/types.js";
29
32
 
30
33
  export type ProtocolNoHandler = Omit<Protocol, "handler">;
@@ -42,6 +45,8 @@ export enum ReqRespMethod {
42
45
  BlobSidecarsByRoot = "blob_sidecars_by_root",
43
46
  DataColumnSidecarsByRange = "data_column_sidecars_by_range",
44
47
  DataColumnSidecarsByRoot = "data_column_sidecars_by_root",
48
+ ExecutionPayloadEnvelopesByRoot = "execution_payload_envelopes_by_root",
49
+ ExecutionPayloadEnvelopesByRange = "execution_payload_envelopes_by_range",
45
50
  LightClientBootstrap = "light_client_bootstrap",
46
51
  LightClientUpdatesByRange = "light_client_updates_by_range",
47
52
  LightClientFinalityUpdate = "light_client_finality_update",
@@ -60,6 +65,8 @@ export type RequestBodyByMethod = {
60
65
  [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequest;
61
66
  [ReqRespMethod.DataColumnSidecarsByRange]: fulu.DataColumnSidecarsByRangeRequest;
62
67
  [ReqRespMethod.DataColumnSidecarsByRoot]: DataColumnSidecarsByRootRequest;
68
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: ExecutionPayloadEnvelopesByRootRequest;
69
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: gloas.ExecutionPayloadEnvelopesByRangeRequest;
63
70
  [ReqRespMethod.LightClientBootstrap]: Root;
64
71
  [ReqRespMethod.LightClientUpdatesByRange]: altair.LightClientUpdatesByRange;
65
72
  [ReqRespMethod.LightClientFinalityUpdate]: null;
@@ -78,6 +85,8 @@ type ResponseBodyByMethod = {
78
85
  [ReqRespMethod.BlobSidecarsByRoot]: deneb.BlobSidecar;
79
86
  [ReqRespMethod.DataColumnSidecarsByRange]: fulu.DataColumnSidecar;
80
87
  [ReqRespMethod.DataColumnSidecarsByRoot]: fulu.DataColumnSidecar;
88
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: gloas.SignedExecutionPayloadEnvelope;
89
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: gloas.SignedExecutionPayloadEnvelope;
81
90
 
82
91
  [ReqRespMethod.LightClientBootstrap]: LightClientBootstrap;
83
92
  [ReqRespMethod.LightClientUpdatesByRange]: LightClientUpdate;
@@ -105,6 +114,8 @@ export const requestSszTypeByMethod: (
105
114
  [ReqRespMethod.BlobSidecarsByRoot]: BlobSidecarsByRootRequestType(fork, config),
106
115
  [ReqRespMethod.DataColumnSidecarsByRange]: ssz.fulu.DataColumnSidecarsByRangeRequest,
107
116
  [ReqRespMethod.DataColumnSidecarsByRoot]: DataColumnSidecarsByRootRequestType(config),
117
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: ExecutionPayloadEnvelopesByRootRequestType(config),
118
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest,
108
119
 
109
120
  [ReqRespMethod.LightClientBootstrap]: ssz.Root,
110
121
  [ReqRespMethod.LightClientUpdatesByRange]: ssz.altair.LightClientUpdatesByRange,
@@ -137,6 +148,8 @@ export const responseSszTypeByMethod: {[K in ReqRespMethod]: ResponseTypeGetter<
137
148
  [ReqRespMethod.LightClientFinalityUpdate]: (fork) => sszTypesFor(onlyPostAltairFork(fork)).LightClientFinalityUpdate,
138
149
  [ReqRespMethod.DataColumnSidecarsByRange]: () => ssz.fulu.DataColumnSidecar,
139
150
  [ReqRespMethod.DataColumnSidecarsByRoot]: () => ssz.fulu.DataColumnSidecar,
151
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: () => ssz.gloas.SignedExecutionPayloadEnvelope,
152
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: () => ssz.gloas.SignedExecutionPayloadEnvelope,
140
153
  [ReqRespMethod.LightClientOptimisticUpdate]: (fork) =>
141
154
  sszTypesFor(onlyPostAltairFork(fork)).LightClientOptimisticUpdate,
142
155
  };
package/src/util/types.ts CHANGED
@@ -29,3 +29,9 @@ export type BlobSidecarsByRootRequest = ValueOf<ReturnType<typeof BlobSidecarsBy
29
29
  export const DataColumnSidecarsByRootRequestType = (config: BeaconConfig) =>
30
30
  new ListCompositeType(ssz.fulu.DataColumnsByRootIdentifier, config.MAX_REQUEST_BLOCKS_DENEB);
31
31
  export type DataColumnSidecarsByRootRequest = ValueOf<ReturnType<typeof DataColumnSidecarsByRootRequestType>>;
32
+
33
+ export const ExecutionPayloadEnvelopesByRootRequestType = (config: BeaconConfig) =>
34
+ new ListCompositeType(ssz.Root, config.MAX_REQUEST_PAYLOADS);
35
+ export type ExecutionPayloadEnvelopesByRootRequest = ValueOf<
36
+ ReturnType<typeof ExecutionPayloadEnvelopesByRootRequestType>
37
+ >;