@lodestar/beacon-node 1.44.0-dev.1070262602 → 1.44.0-dev.1557420d0a

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 (50) hide show
  1. package/lib/api/impl/debug/index.d.ts.map +1 -1
  2. package/lib/api/impl/debug/index.js +69 -12
  3. package/lib/api/impl/debug/index.js.map +1 -1
  4. package/lib/api/impl/validator/index.d.ts.map +1 -1
  5. package/lib/api/impl/validator/index.js +21 -9
  6. package/lib/api/impl/validator/index.js.map +1 -1
  7. package/lib/chain/errors/payloadAttestation.d.ts +6 -0
  8. package/lib/chain/errors/payloadAttestation.d.ts.map +1 -1
  9. package/lib/chain/errors/payloadAttestation.js +1 -0
  10. package/lib/chain/errors/payloadAttestation.js.map +1 -1
  11. package/lib/chain/prepareNextSlot.js +1 -1
  12. package/lib/chain/prepareNextSlot.js.map +1 -1
  13. package/lib/chain/produceBlock/produceBlockBody.js +3 -3
  14. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  15. package/lib/chain/validation/executionPayloadBid.js +22 -5
  16. package/lib/chain/validation/executionPayloadBid.js.map +1 -1
  17. package/lib/chain/validation/payloadAttestationMessage.js +10 -0
  18. package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
  19. package/lib/network/gossip/topic.d.ts +749 -2
  20. package/lib/network/gossip/topic.d.ts.map +1 -1
  21. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
  22. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +5 -0
  23. package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
  24. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -1
  25. package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
  26. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +3 -3
  27. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
  28. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts +2 -1
  29. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
  30. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +15 -1
  31. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  32. package/lib/network/reqresp/handlers/index.js +2 -2
  33. package/lib/network/reqresp/handlers/index.js.map +1 -1
  34. package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
  35. package/lib/network/reqresp/utils/dataColumnResponseValidation.js +8 -0
  36. package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
  37. package/package.json +14 -16
  38. package/src/api/impl/debug/index.ts +73 -12
  39. package/src/api/impl/validator/index.ts +23 -14
  40. package/src/chain/errors/payloadAttestation.ts +2 -0
  41. package/src/chain/prepareNextSlot.ts +1 -1
  42. package/src/chain/produceBlock/produceBlockBody.ts +3 -3
  43. package/src/chain/validation/executionPayloadBid.ts +23 -5
  44. package/src/chain/validation/payloadAttestationMessage.ts +11 -0
  45. package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +6 -0
  46. package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -1
  47. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +3 -3
  48. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +20 -1
  49. package/src/network/reqresp/handlers/index.ts +2 -2
  50. package/src/network/reqresp/utils/dataColumnResponseValidation.ts +8 -0
@@ -70,6 +70,17 @@ async function validatePayloadAttestationMessage(
70
70
  });
71
71
  }
72
72
 
73
+ // [IGNORE] The block referenced by `data.beacon_block_root` is at slot `data.slot`,
74
+ // i.e. the block has `block.slot == data.slot`.
75
+ if (block.slot !== data.slot) {
76
+ throw new PayloadAttestationError(GossipAction.IGNORE, {
77
+ code: PayloadAttestationErrorCode.INVALID_BLOCK_SLOT,
78
+ blockRoot: toRootHex(data.beaconBlockRoot),
79
+ blockSlot: block.slot,
80
+ slot: data.slot,
81
+ });
82
+ }
83
+
73
84
  // [REJECT] The message's block `data.beacon_block_root` passes validation.
74
85
  // TODO GLOAS: implement this. Technically if we cannot get proto block from fork choice,
75
86
  // it is possible that the block didn't pass the validation
@@ -1,5 +1,6 @@
1
1
  import {PeerId} from "@libp2p/interface";
2
2
  import {ChainConfig} from "@lodestar/config";
3
+ import {PayloadStatus} from "@lodestar/fork-choice";
3
4
  import {ForkSeq, GENESIS_SLOT} from "@lodestar/params";
4
5
  import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
5
6
  import {computeEpochAtSlot} from "@lodestar/state-transition";
@@ -104,6 +105,11 @@ export async function* onDataColumnSidecarsByRange(
104
105
 
105
106
  // Must include only columns in the range requested
106
107
  if (block.slot > archiveMaxSlot && block.slot >= startSlot && block.slot < endSlot) {
108
+ // Post-gloas, columns exist only for FULL blocks (pre-gloas blocks are always FULL)
109
+ if (block.payloadStatus !== PayloadStatus.FULL) {
110
+ continue;
111
+ }
112
+
107
113
  // Note: Here the forkChoice head may change due to a re-org, so the headChain reflects the canonical chain
108
114
  // at the time of the start of the request. Spec is clear the chain of columns must be consistent, but on
109
115
  // re-org there's no need to abort the request
@@ -30,7 +30,7 @@ export async function* onDataColumnSidecarsByRoot(
30
30
  const {blockRoot, columns: requestedColumns} = dataColumnsByRootIdentifier;
31
31
  const availableColumns = validateRequestedDataColumns(chain, requestedColumns);
32
32
  if (availableColumns.length === 0) {
33
- return;
33
+ continue;
34
34
  }
35
35
 
36
36
  const blockRootHex = toRootHex(blockRoot);
@@ -20,9 +20,9 @@ export async function* onExecutionPayloadEnvelopesByRange(
20
20
  }
21
21
 
22
22
  const finalized = db.executionPayloadEnvelopeArchive;
23
- const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
24
- // The current finalized block's envelope is still in the hot db; archive migration happens
25
- // in the next finalization run (see migrateExecutionPayloadEnvelopesFromHotToColdDb).
23
+ // Use the finalized block's actual slot as the checkpoint epoch-boundary slot may be skipped
24
+ const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
25
+ // The finalized block's envelope stays in the hot db until the next finalization run
26
26
  const archiveMaxSlot = finalizedSlot - 1;
27
27
 
28
28
  // Finalized range of envelopes
@@ -1,14 +1,18 @@
1
+ import {PeerId} from "@libp2p/interface";
1
2
  import {ResponseOutgoing} from "@lodestar/reqresp";
2
3
  import {computeEpochAtSlot} from "@lodestar/state-transition";
3
4
  import {toRootHex} from "@lodestar/utils";
4
5
  import {IBeaconChain} from "../../../chain/index.js";
5
6
  import {IBeaconDb} from "../../../db/index.js";
6
7
  import {ExecutionPayloadEnvelopesByRootRequest} from "../../../util/types.js";
8
+ import {prettyPrintPeerId} from "../../util.js";
7
9
 
8
10
  export async function* onExecutionPayloadEnvelopesByRoot(
9
11
  requestBody: ExecutionPayloadEnvelopesByRootRequest,
10
12
  chain: IBeaconChain,
11
- db: IBeaconDb
13
+ db: IBeaconDb,
14
+ peerId: PeerId,
15
+ peerClient: string
12
16
  ): AsyncIterable<ResponseOutgoing> {
13
17
  // The gloas req/resp spec uses MIN_EPOCHS_FOR_BLOCK_REQUESTS to define the minimum range peers MUST serve.
14
18
  // Archival nodes may still serve older retained payloads to allow genesis sync.
@@ -20,6 +24,14 @@ export async function* onExecutionPayloadEnvelopesByRoot(
20
24
  const slot = block ? block.slot : await db.blockArchive.getSlotByRoot(root);
21
25
 
22
26
  if (slot === null) {
27
+ chain.logger.debug(
28
+ "Cannot serve ExecutionPayloadEnvelopesByRoot: block root not in fork choice or block archive",
29
+ {
30
+ root: rootHex,
31
+ peer: prettyPrintPeerId(peerId),
32
+ client: peerClient,
33
+ }
34
+ );
23
35
  continue;
24
36
  }
25
37
 
@@ -29,6 +41,13 @@ export async function* onExecutionPayloadEnvelopesByRoot(
29
41
  data: envelopeBytes,
30
42
  boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot)),
31
43
  };
44
+ } else {
45
+ chain.logger.debug("Cannot serve ExecutionPayloadEnvelopesByRoot: envelope not found", {
46
+ slot,
47
+ root: rootHex,
48
+ peer: prettyPrintPeerId(peerId),
49
+ client: peerClient,
50
+ });
32
51
  }
33
52
  }
34
53
  }
@@ -70,9 +70,9 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
70
70
  return onDataColumnSidecarsByRoot(body, chain, db, peerId, peerClient);
71
71
  },
72
72
 
73
- [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: (req) => {
73
+ [ReqRespMethod.ExecutionPayloadEnvelopesByRoot]: (req, peerId, peerClient) => {
74
74
  const body = ExecutionPayloadEnvelopesByRootRequestType(chain.config).deserialize(req.data);
75
- return onExecutionPayloadEnvelopesByRoot(body, chain, db);
75
+ return onExecutionPayloadEnvelopesByRoot(body, chain, db, peerId, peerClient);
76
76
  },
77
77
  [ReqRespMethod.ExecutionPayloadEnvelopesByRange]: (req) => {
78
78
  const body = ssz.gloas.ExecutionPayloadEnvelopesByRangeRequest.deserialize(req.data);
@@ -1,4 +1,5 @@
1
1
  import {LogData} from "@lodestar/logger";
2
+ import {ForkSeq} from "@lodestar/params";
2
3
  import {RespStatus, ResponseError} from "@lodestar/reqresp";
3
4
  import {ColumnIndex, Slot} from "@lodestar/types";
4
5
  import {prettyBytes, prettyPrintIndices, toRootHex} from "@lodestar/utils";
@@ -38,6 +39,13 @@ export async function handleColumnSidecarUnavailability({
38
39
 
39
40
  chain.logger.debug("dataColumnSidecar requested unavailable", logData);
40
41
 
42
+ // Post-gloas, columns exist only for FULL blocks; a finalized block is FULL if its envelope was
43
+ // archived. Bid blobsCount is unreliable here since an EMPTY block's bid may still commit to blobs
44
+ if (blockRoot === undefined && chain.config.getForkSeq(slot) >= ForkSeq.gloas) {
45
+ const envelopeBytes = await db.executionPayloadEnvelopeArchive.getBinary(slot);
46
+ if (!envelopeBytes) return;
47
+ }
48
+
41
49
  const blockBytes = blockRoot ? await db.block.getBinary(blockRoot) : await db.blockArchive.getBinary(slot);
42
50
  if (!blockBytes) {
43
51
  chain.logger.verbose(