@lodestar/beacon-node 1.42.0-dev.b10dfaca8d → 1.42.0-dev.bc0be71fb0
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.
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +24 -12
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +2 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +5 -5
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +2 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +14 -12
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -0
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +3 -3
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +6 -4
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts +2 -2
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +1 -4
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +1 -0
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +5 -5
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +4 -4
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +30 -18
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +10 -8
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +76 -48
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +2 -1
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +14 -6
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +33 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/types.d.ts +20 -14
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +2 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +55 -20
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +29 -7
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +12 -3
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +31 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js +7 -0
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/options.d.ts +1 -0
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +1 -0
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +2 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts +11 -4
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +184 -5
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/db/buckets.d.ts +2 -2
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +2 -2
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.js +4 -2
- package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +4 -2
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +20 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +33 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/interface.d.ts +3 -2
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +22 -11
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts +3 -2
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +3 -0
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js +7 -2
- package/lib/network/options.js.map +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
- package/lib/network/processor/extractSlotRootFns.js +25 -5
- package/lib/network/processor/extractSlotRootFns.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +256 -73
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +11 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +234 -22
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/types.d.ts +3 -3
- package/lib/network/reqresp/types.d.ts.map +1 -1
- package/lib/network/reqresp/types.js +9 -3
- package/lib/network/reqresp/types.js.map +1 -1
- package/lib/sync/unknownBlock.js +2 -2
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +3 -3
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +4 -2
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts +3 -3
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +10 -5
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/blobs.d.ts +3 -3
- package/lib/util/blobs.d.ts.map +1 -1
- package/lib/util/blobs.js +21 -10
- package/lib/util/blobs.js.map +1 -1
- package/lib/util/dataColumns.d.ts +18 -11
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +51 -17
- package/lib/util/dataColumns.js.map +1 -1
- package/lib/util/execution.d.ts +6 -2
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js +49 -25
- package/lib/util/execution.js.map +1 -1
- package/lib/util/sszBytes.d.ts +25 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +189 -2
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -16
- package/src/api/impl/beacon/blocks/index.ts +32 -15
- package/src/api/impl/debug/index.ts +2 -2
- package/src/chain/ColumnReconstructionTracker.ts +6 -5
- package/src/chain/GetBlobsTracker.ts +14 -12
- package/src/chain/archiveStore/archiveStore.ts +1 -0
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +6 -5
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +2 -1
- package/src/chain/archiveStore/historicalState/types.ts +2 -0
- package/src/chain/archiveStore/historicalState/worker.ts +1 -5
- package/src/chain/archiveStore/interface.ts +1 -0
- package/src/chain/blocks/blockInput/blockInput.ts +8 -8
- package/src/chain/blocks/blockInput/types.ts +4 -4
- package/src/chain/blocks/importBlock.ts +36 -18
- package/src/chain/blocks/importExecutionPayload.ts +84 -53
- package/src/chain/blocks/index.ts +2 -1
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +53 -12
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
- package/src/chain/blocks/types.ts +25 -14
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +4 -4
- package/src/chain/chain.ts +63 -24
- package/src/chain/emitter.ts +25 -7
- package/src/chain/errors/dataColumnSidecarError.ts +32 -1
- package/src/chain/interface.ts +4 -2
- package/src/chain/options.ts +2 -0
- package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
- package/src/chain/validation/dataColumnSidecar.ts +230 -7
- package/src/db/buckets.ts +2 -2
- package/src/db/repositories/dataColumnSidecar.ts +4 -2
- package/src/db/repositories/dataColumnSidecarArchive.ts +4 -2
- package/src/metrics/metrics/lodestar.ts +34 -0
- package/src/network/interface.ts +3 -2
- package/src/network/libp2p/index.ts +24 -13
- package/src/network/network.ts +7 -4
- package/src/network/options.ts +7 -2
- package/src/network/processor/extractSlotRootFns.ts +32 -6
- package/src/network/processor/gossipHandlers.ts +320 -86
- package/src/network/processor/index.ts +304 -22
- package/src/network/reqresp/types.ts +13 -5
- package/src/sync/unknownBlock.ts +3 -3
- package/src/sync/utils/downloadByRange.ts +9 -7
- package/src/sync/utils/downloadByRoot.ts +16 -12
- package/src/util/blobs.ts +35 -15
- package/src/util/dataColumns.ts +69 -25
- package/src/util/execution.ts +49 -30
- package/src/util/sszBytes.ts +245 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractSlotRootFns.d.ts","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extractSlotRootFns.d.ts","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,kBAAkB,CA+ElE"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getBeaconBlockRootFromDataColumnSidecarSerialized,
|
|
1
|
+
import { ForkSeq } from "@lodestar/params";
|
|
2
|
+
import { getBeaconBlockRootFromDataColumnSidecarSerialized, getBlockRootFromBeaconAttestationSerialized, getBlockRootFromPayloadAttestationMessageSerialized, getBlockRootFromSignedAggregateAndProofSerialized, getSlotFromBeaconAttestationSerialized, getSlotFromBlobSidecarSerialized, getSlotFromDataColumnSidecarSerialized, getSlotFromExecutionPayloadEnvelopeSerialized, getSlotFromPayloadAttestationMessageSerialized, getSlotFromSignedAggregateAndProofSerialized, getSlotFromSignedBeaconBlockSerialized, getSlotFromSignedExecutionPayloadBidSerialized, } from "../../util/sszBytes.js";
|
|
3
3
|
import { GossipType } from "../gossip/index.js";
|
|
4
4
|
/**
|
|
5
5
|
* Extract the slot and block root of a gossip message form serialized data.
|
|
6
|
-
*
|
|
6
|
+
* Only do it for messages that have a slot and block root, and we want to await the block if the block root is not known.
|
|
7
7
|
*/
|
|
8
8
|
export function createExtractBlockSlotRootFns() {
|
|
9
9
|
return {
|
|
@@ -42,17 +42,37 @@ export function createExtractBlockSlotRootFns() {
|
|
|
42
42
|
if (slot === null) {
|
|
43
43
|
return null;
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
if (ForkSeq[fork] < ForkSeq.gloas) {
|
|
46
|
+
return { slot };
|
|
47
|
+
}
|
|
48
|
+
const root = getBeaconBlockRootFromDataColumnSidecarSerialized(data);
|
|
49
|
+
// null root means the message is invalid here and will be ignored in gossip handler later
|
|
50
|
+
// returning the slot here helps check the earliest permissable slot in the network processor
|
|
46
51
|
return root !== null ? { slot, root } : { slot };
|
|
47
52
|
},
|
|
48
53
|
[GossipType.execution_payload]: (data) => {
|
|
49
54
|
const slot = getSlotFromExecutionPayloadEnvelopeSerialized(data);
|
|
50
|
-
|
|
55
|
+
// Do not extract the root here; the network processor will extract it in the 2nd round to trigger block search without awaiting.
|
|
56
|
+
if (slot === null) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return { slot };
|
|
60
|
+
},
|
|
61
|
+
[GossipType.payload_attestation_message]: (data) => {
|
|
62
|
+
const slot = getSlotFromPayloadAttestationMessageSerialized(data);
|
|
63
|
+
const root = getBlockRootFromPayloadAttestationMessageSerialized(data);
|
|
51
64
|
if (slot === null || root === null) {
|
|
52
65
|
return null;
|
|
53
66
|
}
|
|
54
67
|
return { slot, root };
|
|
55
68
|
},
|
|
69
|
+
[GossipType.execution_payload_bid]: (data) => {
|
|
70
|
+
const slot = getSlotFromSignedExecutionPayloadBidSerialized(data);
|
|
71
|
+
if (slot === null) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return { slot };
|
|
75
|
+
},
|
|
56
76
|
};
|
|
57
77
|
}
|
|
58
78
|
//# sourceMappingURL=extractSlotRootFns.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractSlotRootFns.js","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,
|
|
1
|
+
{"version":3,"file":"extractSlotRootFns.js","sourceRoot":"","sources":["../../../src/network/processor/extractSlotRootFns.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gossipHandlers.d.ts","sourceRoot":"","sources":["../../../src/network/processor/gossipHandlers.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAkB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"gossipHandlers.d.ts","sourceRoot":"","sources":["../../../src/network/processor/gossipHandlers.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAkB,MAAM,kBAAkB,CAAC;AAc/D,OAAO,EACL,IAAI,EAGJ,IAAI,EASL,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAW,MAAM,EAAgC,MAAM,iBAAiB,CAAC;AA2BhF,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AA0BtD,OAAO,EAAC,OAAO,EAAC,MAAM,wBAAwB,CAAC;AAG/C,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAC7C,OAAO,EAGL,cAAc,EAGf,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,wDAAwD;IACxD,sCAAsC,CAAC,EAAE,OAAO,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAE1G;AAkmCD;;GAEG;AACH,wBAAsB,gCAAgC,CAAC,CAAC,EACtD,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { routes } from "@lodestar/api";
|
|
2
|
-
import {
|
|
2
|
+
import { PayloadStatus } from "@lodestar/fork-choice";
|
|
3
|
+
import { ForkSeq, NUMBER_OF_COLUMNS, isForkPostElectra, isForkPostGloas, } from "@lodestar/params";
|
|
3
4
|
import { computeTimeAtSlot } from "@lodestar/state-transition";
|
|
4
|
-
import { ssz, sszTypesFor, } from "@lodestar/types";
|
|
5
|
+
import { isGloasDataColumnSidecar, ssz, sszTypesFor, } from "@lodestar/types";
|
|
5
6
|
import { LogLevel, prettyBytes, toHex, toRootHex } from "@lodestar/utils";
|
|
6
7
|
import { BlockInputSource, isBlockInputColumns, } from "../../chain/blocks/blockInput/index.js";
|
|
7
8
|
import { PayloadEnvelopeInputSource } from "../../chain/blocks/payloadEnvelopeInput/index.js";
|
|
@@ -9,7 +10,7 @@ import { BlobSidecarValidation } from "../../chain/blocks/types.js";
|
|
|
9
10
|
import { ChainEvent } from "../../chain/emitter.js";
|
|
10
11
|
import { AttestationError, AttestationErrorCode, BlobSidecarErrorCode, BlobSidecarGossipError, BlockError, BlockErrorCode, BlockGossipError, DataColumnSidecarErrorCode, DataColumnSidecarGossipError, ExecutionPayloadEnvelopeError, ExecutionPayloadEnvelopeErrorCode, GossipAction, GossipActionError, SyncCommitteeError, } from "../../chain/errors/index.js";
|
|
11
12
|
import { validateGossipBlobSidecar } from "../../chain/validation/blobSidecar.js";
|
|
12
|
-
import {
|
|
13
|
+
import { validateGossipFuluDataColumnSidecar, validateGossipGloasDataColumnSidecar, } from "../../chain/validation/dataColumnSidecar.js";
|
|
13
14
|
import { validateGossipExecutionPayloadBid } from "../../chain/validation/executionPayloadBid.js";
|
|
14
15
|
import { validateGossipExecutionPayloadEnvelope } from "../../chain/validation/executionPayloadEnvelope.js";
|
|
15
16
|
import { toElectraSingleAttestation, validateGossipAggregateAndProof, validateGossipAttestationsSameAttData, validateGossipAttesterSlashing, validateGossipBlock, validateGossipBlsToExecutionChange, validateGossipProposerSlashing, validateGossipSyncCommittee, validateGossipVoluntaryExit, validateSyncCommitteeGossipContributionAndProof, } from "../../chain/validation/index.js";
|
|
@@ -18,7 +19,7 @@ import { validateLightClientOptimisticUpdate } from "../../chain/validation/ligh
|
|
|
18
19
|
import { validateGossipPayloadAttestationMessage } from "../../chain/validation/payloadAttestationMessage.js";
|
|
19
20
|
import { OpSource } from "../../chain/validatorMonitor.js";
|
|
20
21
|
import { kzgCommitmentToVersionedHash } from "../../util/blobs.js";
|
|
21
|
-
import { getBlobKzgCommitments } from "../../util/dataColumns.js";
|
|
22
|
+
import { getBlobKzgCommitments, getDataColumnSidecarSlot } from "../../util/dataColumns.js";
|
|
22
23
|
import { GossipType, } from "../gossip/interface.js";
|
|
23
24
|
import { sszDeserialize } from "../gossip/topic.js";
|
|
24
25
|
import { PeerAction } from "../peers/index.js";
|
|
@@ -64,16 +65,19 @@ function getSequentialHandlers(modules, options) {
|
|
|
64
65
|
recvToValLatency,
|
|
65
66
|
};
|
|
66
67
|
logger.debug("Received gossip block", { ...logCtx });
|
|
67
|
-
|
|
68
|
+
// optimistically add gossip block to the seen cache
|
|
69
|
+
// if validation fails, we will NOT forward this gossip block to peers
|
|
70
|
+
// - if PARENT_UNKNOWN error, blockInput will then be queued inside BlockInputSync. If the gossip block is really invalid, it will be pruned there
|
|
71
|
+
// - if other validator errors, blockInput will stay in the seen cache and will be pruned on finalization
|
|
72
|
+
const blockInput = chain.seenBlockInputCache.getByBlock({
|
|
73
|
+
block: signedBlock,
|
|
74
|
+
blockRootHex,
|
|
75
|
+
source: BlockInputSource.gossip,
|
|
76
|
+
seenTimestampSec,
|
|
77
|
+
peerIdStr,
|
|
78
|
+
});
|
|
68
79
|
try {
|
|
69
80
|
await validateGossipBlock(config, chain, signedBlock, fork);
|
|
70
|
-
blockInput = chain.seenBlockInputCache.getByBlock({
|
|
71
|
-
block: signedBlock,
|
|
72
|
-
blockRootHex,
|
|
73
|
-
source: BlockInputSource.gossip,
|
|
74
|
-
seenTimestampSec,
|
|
75
|
-
peerIdStr,
|
|
76
|
-
});
|
|
77
81
|
const blockInputMeta = blockInput.getLogMeta();
|
|
78
82
|
const recvToValidation = Date.now() / 1000 - seenTimestampSec;
|
|
79
83
|
const validationTime = recvToValidation - recvToValLatency;
|
|
@@ -85,9 +89,9 @@ function getSequentialHandlers(modules, options) {
|
|
|
85
89
|
}
|
|
86
90
|
catch (e) {
|
|
87
91
|
if (e instanceof BlockGossipError) {
|
|
92
|
+
logger.debug("Gossip block has error", { slot, root: blockShortHex, code: e.type.code });
|
|
88
93
|
if (e.type.code === BlockErrorCode.PARENT_UNKNOWN && blockInput) {
|
|
89
|
-
|
|
90
|
-
chain.emitter.emit(ChainEvent.unknownParent, {
|
|
94
|
+
chain.emitter.emit(ChainEvent.blockUnknownParent, {
|
|
91
95
|
blockInput,
|
|
92
96
|
peer: peerIdStr,
|
|
93
97
|
source: BlockInputSource.gossip,
|
|
@@ -196,7 +200,7 @@ function getSequentialHandlers(modules, options) {
|
|
|
196
200
|
const blockInput = chain.seenBlockInputCache.get(blockRootHex);
|
|
197
201
|
if (blockInput && isBlockInputColumns(blockInput) && blockInput.hasColumn(dataColumnSidecar.index)) {
|
|
198
202
|
metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
|
|
199
|
-
logger.debug("Already have column sidecar, skipping processing", {
|
|
203
|
+
logger.debug("Already have column sidecar in BlockInput, skipping processing", {
|
|
200
204
|
...blockInput.getLogMeta(),
|
|
201
205
|
index: dataColumnSidecar.index,
|
|
202
206
|
});
|
|
@@ -209,9 +213,10 @@ function getSequentialHandlers(modules, options) {
|
|
|
209
213
|
}
|
|
210
214
|
const verificationTimer = metrics?.peerDas.dataColumnSidecarGossipVerificationTime.startTimer();
|
|
211
215
|
const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
|
|
216
|
+
const secFromSlot = chain.clock.secFromSlot(slot);
|
|
212
217
|
const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
|
|
213
218
|
try {
|
|
214
|
-
await
|
|
219
|
+
await validateGossipFuluDataColumnSidecar(chain, dataColumnSidecar, gossipSubnet, metrics);
|
|
215
220
|
const blockInput = chain.seenBlockInputCache.getByColumn({
|
|
216
221
|
blockRootHex,
|
|
217
222
|
columnSidecar: dataColumnSidecar,
|
|
@@ -237,6 +242,7 @@ function getSequentialHandlers(modules, options) {
|
|
|
237
242
|
currentSlot: chain.clock.currentSlot,
|
|
238
243
|
peerId: peerIdStr,
|
|
239
244
|
delaySec,
|
|
245
|
+
secFromSlot,
|
|
240
246
|
gossipSubnet,
|
|
241
247
|
columnIndex: dataColumnSidecar.index,
|
|
242
248
|
recvToValLatency,
|
|
@@ -261,6 +267,108 @@ function getSequentialHandlers(modules, options) {
|
|
|
261
267
|
verificationTimer?.();
|
|
262
268
|
}
|
|
263
269
|
}
|
|
270
|
+
async function validatePayloadDataColumn(dataColumnSidecar, gossipSubnet, peerIdStr, seenTimestampSec) {
|
|
271
|
+
metrics?.peerDas.dataColumnSidecarProcessingRequests.inc();
|
|
272
|
+
const slot = dataColumnSidecar.slot;
|
|
273
|
+
const blockRootHex = toRootHex(dataColumnSidecar.beaconBlockRoot);
|
|
274
|
+
// check to see if payload has already been processed and PayloadEnvelopeInput has been deleted (column received via reqresp or other means)
|
|
275
|
+
if (chain.forkChoice.getBlockHex(blockRootHex, PayloadStatus.FULL) !== null) {
|
|
276
|
+
metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
|
|
277
|
+
logger.debug("Already processed payload for column sidecar, skipping processing", {
|
|
278
|
+
slot,
|
|
279
|
+
blockRoot: blockRootHex,
|
|
280
|
+
index: dataColumnSidecar.index,
|
|
281
|
+
});
|
|
282
|
+
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
283
|
+
code: DataColumnSidecarErrorCode.ALREADY_KNOWN,
|
|
284
|
+
columnIndex: dataColumnSidecar.index,
|
|
285
|
+
slot,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
|
|
289
|
+
if (!payloadInput) {
|
|
290
|
+
// This should not happen for gossip because the network processor queues `data_column_sidecar`
|
|
291
|
+
// until block import creates the corresponding PayloadEnvelopeInput.
|
|
292
|
+
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
293
|
+
code: DataColumnSidecarErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING,
|
|
294
|
+
slot,
|
|
295
|
+
blockRoot: blockRootHex,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
// [IGNORE] The sidecar is the first sidecar for the tuple
|
|
299
|
+
// (sidecar.beacon_block_root, sidecar.index) with valid kzg proof.
|
|
300
|
+
if (payloadInput.hasColumn(dataColumnSidecar.index)) {
|
|
301
|
+
metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
|
|
302
|
+
logger.debug("Already have column sidecar in PayloadEnvelopeInput, skipping processing", {
|
|
303
|
+
...payloadInput.getLogMeta(),
|
|
304
|
+
index: dataColumnSidecar.index,
|
|
305
|
+
});
|
|
306
|
+
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
307
|
+
code: DataColumnSidecarErrorCode.ALREADY_KNOWN,
|
|
308
|
+
columnIndex: dataColumnSidecar.index,
|
|
309
|
+
slot,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
const verificationTimer = metrics?.peerDas.dataColumnSidecarGossipVerificationTime.startTimer();
|
|
313
|
+
const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec);
|
|
314
|
+
const secFromSlot = chain.clock.secFromSlot(slot);
|
|
315
|
+
const recvToValLatency = Date.now() / 1000 - seenTimestampSec;
|
|
316
|
+
try {
|
|
317
|
+
await validateGossipGloasDataColumnSidecar(chain, payloadInput, dataColumnSidecar, gossipSubnet, metrics);
|
|
318
|
+
const addedColumn = payloadInput.addColumn({
|
|
319
|
+
columnSidecar: dataColumnSidecar,
|
|
320
|
+
source: PayloadEnvelopeInputSource.gossip,
|
|
321
|
+
seenTimestampSec,
|
|
322
|
+
peerIdStr,
|
|
323
|
+
});
|
|
324
|
+
if (!addedColumn) {
|
|
325
|
+
metrics?.peerDas.dataColumnSidecarProcessingSkip.inc();
|
|
326
|
+
logger.debug("Already have column sidecar in PayloadEnvelopeInput, skipping processing", {
|
|
327
|
+
...payloadInput.getLogMeta(),
|
|
328
|
+
index: dataColumnSidecar.index,
|
|
329
|
+
});
|
|
330
|
+
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
331
|
+
code: DataColumnSidecarErrorCode.ALREADY_KNOWN,
|
|
332
|
+
columnIndex: dataColumnSidecar.index,
|
|
333
|
+
slot,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
const recvToValidation = Date.now() / 1000 - seenTimestampSec;
|
|
337
|
+
const validationTime = recvToValidation - recvToValLatency;
|
|
338
|
+
metrics?.peerDas.dataColumnSidecarProcessingSuccesses.inc();
|
|
339
|
+
metrics?.gossipBlob.recvToValidation.observe(recvToValidation);
|
|
340
|
+
metrics?.gossipBlob.validationTime.observe(validationTime);
|
|
341
|
+
if (chain.emitter.listenerCount(routes.events.EventType.dataColumnSidecar)) {
|
|
342
|
+
chain.emitter.emit(routes.events.EventType.dataColumnSidecar, {
|
|
343
|
+
blockRoot: blockRootHex,
|
|
344
|
+
slot,
|
|
345
|
+
index: dataColumnSidecar.index,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
logger.debug("Received gossip dataColumn", {
|
|
349
|
+
...payloadInput.getLogMeta(),
|
|
350
|
+
currentSlot: chain.clock.currentSlot,
|
|
351
|
+
peerId: peerIdStr,
|
|
352
|
+
delaySec,
|
|
353
|
+
secFromSlot,
|
|
354
|
+
gossipSubnet,
|
|
355
|
+
columnIndex: dataColumnSidecar.index,
|
|
356
|
+
recvToValLatency,
|
|
357
|
+
recvToValidation,
|
|
358
|
+
validationTime,
|
|
359
|
+
});
|
|
360
|
+
return payloadInput;
|
|
361
|
+
}
|
|
362
|
+
catch (e) {
|
|
363
|
+
if (e instanceof DataColumnSidecarGossipError && e.action === GossipAction.REJECT) {
|
|
364
|
+
chain.persistInvalidSszValue(sszTypesFor(payloadInput.forkName).DataColumnSidecar, dataColumnSidecar, `gossip_reject_slot_${slot}_index_${dataColumnSidecar.index}`);
|
|
365
|
+
}
|
|
366
|
+
throw e;
|
|
367
|
+
}
|
|
368
|
+
finally {
|
|
369
|
+
verificationTimer?.();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
264
372
|
function handleValidBeaconBlock(blockInput, peerIdStr, seenTimestampSec) {
|
|
265
373
|
const signedBlock = blockInput.getBlock();
|
|
266
374
|
const slot = signedBlock.message.slot;
|
|
@@ -382,65 +490,110 @@ function getSequentialHandlers(modules, options) {
|
|
|
382
490
|
}
|
|
383
491
|
},
|
|
384
492
|
[GossipType.data_column_sidecar]: async ({ gossipData, topic, peerIdStr, seenTimestampSec, }) => {
|
|
493
|
+
const { fork } = topic.boundary;
|
|
385
494
|
const { serializedData } = gossipData;
|
|
386
|
-
// TODO GLOAS: handle gloas.DataColumnSidecar
|
|
387
495
|
const dataColumnSidecar = sszDeserialize(topic, serializedData);
|
|
388
|
-
const dataColumnSlot = dataColumnSidecar
|
|
496
|
+
const dataColumnSlot = getDataColumnSidecarSlot(dataColumnSidecar);
|
|
389
497
|
const index = dataColumnSidecar.index;
|
|
390
|
-
if (config.getForkSeq(dataColumnSlot) < ForkSeq.fulu) {
|
|
391
|
-
throw new GossipActionError(GossipAction.REJECT, { code: "PRE_FULU_BLOCK" });
|
|
392
|
-
}
|
|
393
498
|
const delaySec = chain.clock.secFromSlot(dataColumnSlot, seenTimestampSec);
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
case config.SAMPLES_PER_SLOT:
|
|
403
|
-
case 2 * config.SAMPLES_PER_SLOT:
|
|
404
|
-
case NUMBER_OF_COLUMNS / 4:
|
|
405
|
-
case NUMBER_OF_COLUMNS / 2:
|
|
406
|
-
case NUMBER_OF_COLUMNS:
|
|
407
|
-
metrics?.dataColumns.elapsedTimeTillReceived.observe({ receivedOrder: receivedColumns }, delaySec);
|
|
408
|
-
break;
|
|
409
|
-
}
|
|
410
|
-
if (!blockInput.hasComputedAllData()) {
|
|
411
|
-
// immediately attempt fetch of data columns from execution engine
|
|
412
|
-
chain.getBlobsTracker.triggerGetBlobs(blockInput);
|
|
413
|
-
// if we've received at least half of the columns, trigger reconstruction of the rest
|
|
414
|
-
if (blockInput.columnCount >= NUMBER_OF_COLUMNS / 2) {
|
|
415
|
-
chain.columnReconstructionTracker.triggerColumnReconstruction(blockInput);
|
|
499
|
+
if (isForkPostGloas(fork)) {
|
|
500
|
+
if (!isGloasDataColumnSidecar(dataColumnSidecar)) {
|
|
501
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
502
|
+
code: DataColumnSidecarErrorCode.INCORRECT_TYPE,
|
|
503
|
+
slot: dataColumnSlot,
|
|
504
|
+
columnIndex: index,
|
|
505
|
+
fork,
|
|
506
|
+
});
|
|
416
507
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
508
|
+
// After gloas, data columns are tracked in PayloadEnvelopeInput
|
|
509
|
+
const payloadInput = await validatePayloadDataColumn(dataColumnSidecar, topic.subnet, peerIdStr, seenTimestampSec);
|
|
510
|
+
chain.serializedCache.set(dataColumnSidecar, serializedData);
|
|
511
|
+
const payloadInputMeta = payloadInput.getLogMeta();
|
|
512
|
+
const { receivedColumns } = payloadInputMeta;
|
|
513
|
+
// it's not helpful to track every single column received
|
|
514
|
+
// instead of that, track 1st, 8th, 16th 32th, 64th, and 128th column
|
|
515
|
+
switch (receivedColumns) {
|
|
516
|
+
case 1:
|
|
517
|
+
case config.SAMPLES_PER_SLOT:
|
|
518
|
+
case 2 * config.SAMPLES_PER_SLOT:
|
|
519
|
+
case NUMBER_OF_COLUMNS / 4:
|
|
520
|
+
case NUMBER_OF_COLUMNS / 2:
|
|
521
|
+
case NUMBER_OF_COLUMNS:
|
|
522
|
+
metrics?.dataColumns.elapsedTimeTillReceived.observe({ receivedOrder: receivedColumns }, delaySec);
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
if (!payloadInput.hasComputedAllData()) {
|
|
526
|
+
// if we've received at least half of the columns, trigger reconstruction of the rest
|
|
527
|
+
if (receivedColumns >= NUMBER_OF_COLUMNS / 2) {
|
|
528
|
+
chain.columnReconstructionTracker.triggerColumnReconstruction(payloadInput);
|
|
529
|
+
}
|
|
530
|
+
chain.logger.debug("Received gossip data column, payload envelope input not yet complete", {
|
|
531
|
+
dataColumnIndex: index,
|
|
532
|
+
...payloadInputMeta,
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
chain.processExecutionPayload(payloadInput, { validSignature: true }).catch((e) => {
|
|
536
|
+
chain.logger.debug("Error processing execution payload from gossip data column", { slot: dataColumnSlot, root: payloadInput.blockRootHex }, e);
|
|
424
537
|
});
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
if (config.getForkSeq(dataColumnSlot) < ForkSeq.fulu) {
|
|
541
|
+
throw new GossipActionError(GossipAction.REJECT, { code: "PRE_FULU_BLOCK" });
|
|
542
|
+
}
|
|
543
|
+
if (isGloasDataColumnSidecar(dataColumnSidecar)) {
|
|
544
|
+
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
|
545
|
+
code: DataColumnSidecarErrorCode.INCORRECT_TYPE,
|
|
546
|
+
slot: dataColumnSlot,
|
|
547
|
+
columnIndex: index,
|
|
548
|
+
fork,
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
// Before gloas, data columns are tracked in BlockInput
|
|
552
|
+
const blockInput = await validateBeaconDataColumn(dataColumnSidecar, serializedData, topic.subnet, peerIdStr, seenTimestampSec);
|
|
553
|
+
chain.serializedCache.set(dataColumnSidecar, serializedData);
|
|
554
|
+
const blockInputMeta = blockInput.getLogMeta();
|
|
555
|
+
const { receivedColumns } = blockInputMeta;
|
|
556
|
+
// it's not helpful to track every single column received
|
|
557
|
+
// instead of that, track 1st, 8th, 16th 32th, 64th, and 128th column
|
|
558
|
+
switch (receivedColumns) {
|
|
559
|
+
case 1:
|
|
560
|
+
case config.SAMPLES_PER_SLOT:
|
|
561
|
+
case 2 * config.SAMPLES_PER_SLOT:
|
|
562
|
+
case NUMBER_OF_COLUMNS / 4:
|
|
563
|
+
case NUMBER_OF_COLUMNS / 2:
|
|
564
|
+
case NUMBER_OF_COLUMNS:
|
|
565
|
+
metrics?.dataColumns.elapsedTimeTillReceived.observe({ receivedOrder: receivedColumns }, delaySec);
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
if (!blockInput.hasComputedAllData()) {
|
|
569
|
+
// immediately attempt fetch of data columns from execution engine
|
|
570
|
+
chain.getBlobsTracker.triggerGetBlobs(blockInput);
|
|
571
|
+
// if we've received at least half of the columns, trigger reconstruction of the rest
|
|
572
|
+
if (blockInput.columnCount >= NUMBER_OF_COLUMNS / 2) {
|
|
573
|
+
chain.columnReconstructionTracker.triggerColumnReconstruction(blockInput);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (!blockInput.hasBlockAndAllData()) {
|
|
577
|
+
const cutoffTimeMs = getCutoffTimeMs(chain, dataColumnSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
|
|
578
|
+
chain.logger.debug("Received gossip data column, waiting for full data availability", {
|
|
579
|
+
msToWait: cutoffTimeMs,
|
|
428
580
|
dataColumnIndex: index,
|
|
429
581
|
...blockInputMeta,
|
|
430
582
|
});
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
583
|
+
// do not await here to not delay gossip validation
|
|
584
|
+
blockInput.waitForBlockAndAllData(cutoffTimeMs).catch((_e) => {
|
|
585
|
+
chain.logger.debug("Waited for data after receiving gossip column. Cut-off reached so attempting to fetch remainder of BlockInput", {
|
|
586
|
+
dataColumnIndex: index,
|
|
587
|
+
...blockInputMeta,
|
|
588
|
+
});
|
|
589
|
+
chain.emitter.emit(ChainEvent.incompleteBlockInput, {
|
|
590
|
+
blockInput,
|
|
591
|
+
peer: peerIdStr,
|
|
592
|
+
source: BlockInputSource.gossip,
|
|
593
|
+
});
|
|
435
594
|
});
|
|
436
|
-
}
|
|
595
|
+
}
|
|
437
596
|
}
|
|
438
|
-
// TODO GLOAS: In Gloas, also add column to PayloadEnvelopeInput and notify the payload processor:
|
|
439
|
-
// const payloadInput = chain.seenPayloadEnvelopeInput.get(blockRootHex);
|
|
440
|
-
// if (payloadInput) {
|
|
441
|
-
// payloadInput.addColumn({columnSidecar, source: BlockInputSource.gossip, seenTimestampSec, peerIdStr});
|
|
442
|
-
// chain.processExecutionPayload(payloadInput, {validSignature: true});
|
|
443
|
-
// }
|
|
444
597
|
},
|
|
445
598
|
[GossipType.beacon_aggregate_and_proof]: async ({ gossipData, topic, seenTimestampSec, }) => {
|
|
446
599
|
const { serializedData } = gossipData;
|
|
@@ -584,14 +737,38 @@ function getSequentialHandlers(modules, options) {
|
|
|
584
737
|
},
|
|
585
738
|
[GossipType.execution_payload]: async ({ gossipData, topic, peerIdStr, seenTimestampSec, }) => {
|
|
586
739
|
const { serializedData } = gossipData;
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
740
|
+
const signedEnvelope = sszDeserialize(topic, serializedData);
|
|
741
|
+
const envelope = signedEnvelope.message;
|
|
742
|
+
// TODO GLOAS: consider optimistically create PayloadEnvelopeInput here similar to how we do that for beacon_block
|
|
743
|
+
// so that UnknownBlockSync can handle backward sync
|
|
744
|
+
// the problem now is we cannot create a PayloadEnvelopeInput without the beacon block being known, we need at least the proposer index
|
|
745
|
+
// we can achieve that by looking into the EpochCache
|
|
746
|
+
try {
|
|
747
|
+
await validateGossipExecutionPayloadEnvelope(chain, signedEnvelope);
|
|
748
|
+
}
|
|
749
|
+
catch (e) {
|
|
750
|
+
if (e instanceof ExecutionPayloadEnvelopeError) {
|
|
751
|
+
const { slot, beaconBlockRoot } = signedEnvelope.message;
|
|
752
|
+
logger.debug("Gossip envelope has error", { slot, root: toRootHex(beaconBlockRoot), code: e.type.code });
|
|
753
|
+
if (e.type.code === ExecutionPayloadEnvelopeErrorCode.BLOCK_ROOT_UNKNOWN) {
|
|
754
|
+
// TODO GLOAS: UnknownBlockSync to handle this
|
|
755
|
+
chain.emitter.emit(ChainEvent.envelopeUnknownBlock, {
|
|
756
|
+
envelope: signedEnvelope,
|
|
757
|
+
peer: peerIdStr,
|
|
758
|
+
source: BlockInputSource.gossip,
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
if (e.action === GossipAction.REJECT) {
|
|
762
|
+
chain.persistInvalidSszValue(ssz.gloas.SignedExecutionPayloadEnvelope, signedEnvelope, `gossip_reject_slot_${slot}`);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
throw e;
|
|
766
|
+
}
|
|
767
|
+
const slot = envelope.slot;
|
|
591
768
|
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
592
769
|
metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({ source: OpSource.gossip }, delaySec);
|
|
593
|
-
chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec,
|
|
594
|
-
const blockRootHex = toRootHex(
|
|
770
|
+
chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, signedEnvelope);
|
|
771
|
+
const blockRootHex = toRootHex(envelope.beaconBlockRoot);
|
|
595
772
|
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
|
|
596
773
|
if (!payloadInput) {
|
|
597
774
|
// This shouldn't happen because beacon block should have been imported and thus payload input should have been created.
|
|
@@ -600,14 +777,20 @@ function getSequentialHandlers(modules, options) {
|
|
|
600
777
|
blockRoot: blockRootHex,
|
|
601
778
|
});
|
|
602
779
|
}
|
|
603
|
-
chain.serializedCache.set(
|
|
780
|
+
chain.serializedCache.set(signedEnvelope, serializedData);
|
|
604
781
|
payloadInput.addPayloadEnvelope({
|
|
605
|
-
envelope:
|
|
782
|
+
envelope: signedEnvelope,
|
|
606
783
|
source: PayloadEnvelopeInputSource.gossip,
|
|
607
784
|
seenTimestampSec,
|
|
608
785
|
peerIdStr,
|
|
609
786
|
});
|
|
610
|
-
|
|
787
|
+
chain.emitter.emit(routes.events.EventType.executionPayloadGossip, {
|
|
788
|
+
slot,
|
|
789
|
+
builderIndex: envelope.builderIndex,
|
|
790
|
+
blockHash: toRootHex(envelope.payload.blockHash),
|
|
791
|
+
blockRoot: blockRootHex,
|
|
792
|
+
stateRoot: toRootHex(envelope.stateRoot),
|
|
793
|
+
});
|
|
611
794
|
chain.processExecutionPayload(payloadInput, { validSignature: true }).catch((e) => {
|
|
612
795
|
chain.logger.debug("Error processing execution payload from gossip", { slot, root: blockRootHex }, e);
|
|
613
796
|
});
|