@lodestar/beacon-node 1.42.0-dev.8b81ee6c3e → 1.42.0-dev.972ec54bb9
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 +22 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +4 -0
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/index.js +13 -10
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +4 -0
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +9 -3
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +6 -4
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +14 -5
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.js +1 -1
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +3 -3
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +3 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +4 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +26 -9
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +27 -5
- 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/blockError.d.ts +11 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +4 -0
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +10 -8
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -1
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -2
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +7 -0
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +5 -2
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +2 -2
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.js +2 -2
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +7 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -3
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +8 -8
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +5 -5
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +23 -4
- package/lib/chain/produceBlock/produceBlockBody.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/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +27 -5
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +7 -4
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +6 -1
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +4 -1
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/syncCommittee.js +4 -0
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +3 -3
- package/lib/chain/validatorMonitor.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 +1 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +1 -0
- 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/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 +42 -12
- 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/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +2 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js +2 -0
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts +2 -2
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js +7 -3
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +6 -0
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts +2 -2
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +7 -3
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +2 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +3 -8
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -1
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.d.ts.map +1 -1
- package/lib/node/notifier.js +2 -2
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/unknownBlock.js +2 -2
- package/lib/sync/unknownBlock.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 +155 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +31 -2
- package/src/api/impl/beacon/pool/index.ts +4 -0
- package/src/api/impl/beacon/state/index.ts +15 -15
- package/src/api/impl/lodestar/index.ts +4 -0
- package/src/api/impl/validator/index.ts +9 -2
- package/src/chain/blocks/importBlock.ts +11 -7
- package/src/chain/blocks/importExecutionPayload.ts +15 -5
- package/src/chain/blocks/index.ts +1 -1
- package/src/chain/blocks/types.ts +3 -3
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +2 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
- package/src/chain/chain.ts +35 -9
- package/src/chain/emitter.ts +23 -5
- package/src/chain/errors/blockError.ts +7 -1
- package/src/chain/forkChoice/index.ts +11 -8
- package/src/chain/interface.ts +7 -0
- package/src/chain/lightClient/index.ts +15 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +6 -1
- package/src/chain/opPools/executionPayloadBidPool.ts +3 -3
- package/src/chain/prepareNextSlot.ts +8 -0
- package/src/chain/produceBlock/computeNewStateRoot.ts +11 -10
- package/src/chain/produceBlock/produceBlockBody.ts +40 -10
- package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
- package/src/chain/validation/block.ts +30 -7
- package/src/chain/validation/executionPayloadBid.ts +7 -3
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -1
- package/src/chain/validation/payloadAttestationMessage.ts +4 -0
- package/src/chain/validation/syncCommittee.ts +5 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -1
- package/src/chain/validatorMonitor.ts +3 -2
- package/src/metrics/metrics/lodestar.ts +34 -0
- package/src/network/interface.ts +1 -0
- package/src/network/network.ts +4 -0
- package/src/network/processor/extractSlotRootFns.ts +32 -6
- package/src/network/processor/gossipHandlers.ts +49 -12
- package/src/network/processor/index.ts +304 -22
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +3 -1
- package/src/network/reqresp/handlers/beaconBlocksByRoot.ts +3 -0
- package/src/network/reqresp/handlers/blobSidecarsByRange.ts +15 -3
- package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +11 -0
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +19 -3
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +3 -1
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +3 -12
- package/src/node/nodejs.ts +5 -2
- package/src/node/notifier.ts +7 -2
- package/src/sync/unknownBlock.ts +3 -3
- package/src/util/sszBytes.ts +203 -1
|
@@ -14,7 +14,16 @@ import {
|
|
|
14
14
|
isForkPostBellatrix,
|
|
15
15
|
isForkPostGloas,
|
|
16
16
|
} from "@lodestar/params";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
G2_POINT_AT_INFINITY,
|
|
19
|
+
IBeaconStateView,
|
|
20
|
+
type IBeaconStateViewBellatrix,
|
|
21
|
+
computeTimeAtSlot,
|
|
22
|
+
isParentBlockFull,
|
|
23
|
+
isStatePostBellatrix,
|
|
24
|
+
isStatePostCapella,
|
|
25
|
+
isStatePostGloas,
|
|
26
|
+
} from "@lodestar/state-transition";
|
|
18
27
|
import {
|
|
19
28
|
BLSPubkey,
|
|
20
29
|
BLSSignature,
|
|
@@ -103,11 +112,11 @@ export type ProduceFullGloas = {
|
|
|
103
112
|
blobsBundle: BlobsBundle<ForkPostGloas>;
|
|
104
113
|
cells: fulu.Cell[][];
|
|
105
114
|
/**
|
|
106
|
-
* Cached envelope state root computed during block production.
|
|
115
|
+
* Cached payload envelope state root computed during block production.
|
|
107
116
|
* This is the state root after running `processExecutionPayloadEnvelope` on the
|
|
108
117
|
* post-block state, and later used to construct the `ExecutionPayloadEnvelope`.
|
|
109
118
|
*/
|
|
110
|
-
|
|
119
|
+
payloadEnvelopeStateRoot: Root;
|
|
111
120
|
};
|
|
112
121
|
export type ProduceFullFulu = {
|
|
113
122
|
type: BlockType.Full;
|
|
@@ -191,6 +200,10 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
191
200
|
this.logger.verbose("Producing beacon block body", logMeta);
|
|
192
201
|
|
|
193
202
|
if (isForkPostGloas(fork)) {
|
|
203
|
+
if (!isStatePostGloas(currentState)) {
|
|
204
|
+
throw new Error("Expected Gloas state for Gloas block production");
|
|
205
|
+
}
|
|
206
|
+
|
|
194
207
|
// TODO GLOAS: support non self-building here, the block type differentiation between
|
|
195
208
|
// full and blinded no longer makes sense in gloas, it might be a good idea to move
|
|
196
209
|
// this into a completely separate function and have pre/post gloas more separated
|
|
@@ -297,6 +310,10 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
297
310
|
shouldOverrideBuilder,
|
|
298
311
|
});
|
|
299
312
|
} else if (isForkPostBellatrix(fork)) {
|
|
313
|
+
if (!isStatePostBellatrix(currentState)) {
|
|
314
|
+
throw new Error("Expected Bellatrix state for execution block production");
|
|
315
|
+
}
|
|
316
|
+
|
|
300
317
|
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
|
|
301
318
|
const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
302
319
|
const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);
|
|
@@ -598,7 +615,7 @@ export async function prepareExecutionPayload(
|
|
|
598
615
|
parentBlockRoot: Root,
|
|
599
616
|
safeBlockHash: RootHex,
|
|
600
617
|
finalizedBlockHash: RootHex,
|
|
601
|
-
state:
|
|
618
|
+
state: IBeaconStateViewBellatrix,
|
|
602
619
|
suggestedFeeRecipient: string
|
|
603
620
|
): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
|
|
604
621
|
const parentHash = state.latestBlockHash;
|
|
@@ -666,7 +683,7 @@ async function prepareExecutionPayloadHeader(
|
|
|
666
683
|
config: ChainForkConfig;
|
|
667
684
|
},
|
|
668
685
|
fork: ForkPostBellatrix,
|
|
669
|
-
state:
|
|
686
|
+
state: IBeaconStateViewBellatrix,
|
|
670
687
|
proposerPubKey: BLSPubkey
|
|
671
688
|
): Promise<{
|
|
672
689
|
header: ExecutionPayloadHeader;
|
|
@@ -693,7 +710,7 @@ export function getPayloadAttributesForSSE(
|
|
|
693
710
|
prepareSlot,
|
|
694
711
|
parentBlockRoot,
|
|
695
712
|
feeRecipient,
|
|
696
|
-
}: {prepareState:
|
|
713
|
+
}: {prepareState: IBeaconStateViewBellatrix; prepareSlot: Slot; parentBlockRoot: Root; feeRecipient: string}
|
|
697
714
|
): SSEPayloadAttributes {
|
|
698
715
|
const parentHash = prepareState.latestBlockHash;
|
|
699
716
|
const payloadAttributes = preparePayloadAttributes(fork, chain, {
|
|
@@ -736,7 +753,7 @@ function preparePayloadAttributes(
|
|
|
736
753
|
parentBlockRoot,
|
|
737
754
|
feeRecipient,
|
|
738
755
|
}: {
|
|
739
|
-
prepareState:
|
|
756
|
+
prepareState: IBeaconStateViewBellatrix;
|
|
740
757
|
prepareSlot: Slot;
|
|
741
758
|
parentBlockRoot: Root;
|
|
742
759
|
feeRecipient: string;
|
|
@@ -751,9 +768,22 @@ function preparePayloadAttributes(
|
|
|
751
768
|
};
|
|
752
769
|
|
|
753
770
|
if (ForkSeq[fork] >= ForkSeq.capella) {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
771
|
+
if (!isStatePostCapella(prepareState)) {
|
|
772
|
+
throw new Error("Expected Capella state for withdrawals");
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if (isStatePostGloas(prepareState) && !isParentBlockFull(prepareState)) {
|
|
776
|
+
// When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
|
|
777
|
+
// already deducted from CL balances but never credited on the EL (the envelope
|
|
778
|
+
// was not delivered). The next payload must carry those same withdrawals to
|
|
779
|
+
// restore CL/EL consistency, otherwise validators permanently lose that balance.
|
|
780
|
+
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
781
|
+
prepareState.payloadExpectedWithdrawals;
|
|
782
|
+
} else {
|
|
783
|
+
// withdrawals logic is now fork aware as it changes on electra fork post capella
|
|
784
|
+
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
785
|
+
prepareState.getExpectedWithdrawals().expectedWithdrawals;
|
|
786
|
+
}
|
|
757
787
|
}
|
|
758
788
|
|
|
759
789
|
if (ForkSeq[fork] >= ForkSeq.deneb) {
|
|
@@ -149,8 +149,8 @@ export class SeenBlockInput {
|
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
return this.blockInputs.
|
|
152
|
+
hasBlock(rootHex: RootHex): boolean {
|
|
153
|
+
return this.blockInputs.get(rootHex)?.hasBlock() ?? false;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
get(rootHex: RootHex): IBlockInput | undefined {
|
|
@@ -84,8 +84,8 @@ export class SeenPayloadEnvelopeInput {
|
|
|
84
84
|
return this.payloadInputs.get(blockRootHex);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
return this.payloadInputs.
|
|
87
|
+
hasPayload(blockRootHex: RootHex): boolean {
|
|
88
|
+
return this.payloadInputs.get(blockRootHex)?.hasPayloadEnvelope() ?? false;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
prune(blockRootHex: RootHex): void {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
+
import {ExecutionStatus} from "@lodestar/fork-choice";
|
|
2
3
|
import {ForkName, isForkPostBellatrix, isForkPostDeneb, isForkPostGloas} from "@lodestar/params";
|
|
3
4
|
import {
|
|
4
5
|
computeEpochAtSlot,
|
|
@@ -6,6 +7,7 @@ import {
|
|
|
6
7
|
computeTimeAtSlot,
|
|
7
8
|
getBlockProposerSignatureSet,
|
|
8
9
|
isExecutionBlockBodyType,
|
|
10
|
+
isStatePostBellatrix,
|
|
9
11
|
} from "@lodestar/state-transition";
|
|
10
12
|
import {SignedBeaconBlock, deneb, gloas, isGloasBeaconBlock} from "@lodestar/types";
|
|
11
13
|
import {byteArrayEquals, sleep, toRootHex} from "@lodestar/utils";
|
|
@@ -70,12 +72,7 @@ export async function validateGossipBlock(
|
|
|
70
72
|
// [REJECT] The current finalized_checkpoint is an ancestor of block -- i.e.
|
|
71
73
|
// get_ancestor(store, block.parent_root, compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)) == store.finalized_checkpoint.root
|
|
72
74
|
const parentRoot = toRootHex(block.parentRoot);
|
|
73
|
-
const parentBlock =
|
|
74
|
-
? chain.forkChoice.getBlockHexAndBlockHash(
|
|
75
|
-
parentRoot,
|
|
76
|
-
toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
77
|
-
)
|
|
78
|
-
: chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
75
|
+
const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
79
76
|
if (parentBlock === null) {
|
|
80
77
|
// If fork choice does *not* consider the parent to be a descendant of the finalized block,
|
|
81
78
|
// then there are two more cases:
|
|
@@ -90,6 +87,27 @@ export async function validateGossipBlock(
|
|
|
90
87
|
throw new BlockGossipError(GossipAction.IGNORE, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
|
|
91
88
|
}
|
|
92
89
|
|
|
90
|
+
// [IGNORE] The block's parent (defined by `block.parent_root`) passes all validation
|
|
91
|
+
// (including execution node verification of the `block.body.execution_payload`)
|
|
92
|
+
if (isForkPostBellatrix(fork) && parentBlock.executionStatus === ExecutionStatus.Invalid) {
|
|
93
|
+
throw new BlockGossipError(GossipAction.IGNORE, {
|
|
94
|
+
code: BlockErrorCode.PARENT_EXECUTION_INVALID,
|
|
95
|
+
parentRoot,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// [IGNORE] The block's parent execution payload (defined by bid.parent_block_hash) has been seen
|
|
100
|
+
// (via gossip or non-gossip sources) (a client MAY queue blocks for processing once the parent payload is retrieved).
|
|
101
|
+
if (isGloasBeaconBlock(block)) {
|
|
102
|
+
const parentBlockHashHex = toRootHex(block.body.signedExecutionPayloadBid.message.parentBlockHash);
|
|
103
|
+
if (chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHashHex) === null) {
|
|
104
|
+
throw new BlockGossipError(GossipAction.IGNORE, {
|
|
105
|
+
code: BlockErrorCode.PARENT_PAYLOAD_UNKNOWN,
|
|
106
|
+
parentBlockHash: parentBlockHashHex,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
93
111
|
// [IGNORE] The attestation head block is too far behind the attestation slot, causing many skip slots.
|
|
94
112
|
// This is deemed a DoS risk because we need to get the proposerShuffling. To get the shuffling we have
|
|
95
113
|
// to do a bunch of epoch transitions, the longer the distance between the parent and block,
|
|
@@ -174,7 +192,7 @@ export async function validateGossipBlock(
|
|
|
174
192
|
if (isForkPostBellatrix(fork) && !isForkPostGloas(fork)) {
|
|
175
193
|
if (!isExecutionBlockBodyType(block.body)) throw Error("Not execution block body type");
|
|
176
194
|
const executionPayload = block.body.executionPayload;
|
|
177
|
-
if (blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
|
|
195
|
+
if (isStatePostBellatrix(blockState) && blockState.isExecutionStateType && blockState.isExecutionEnabled(block)) {
|
|
178
196
|
const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
|
|
179
197
|
if (executionPayload.timestamp !== computeTimeAtSlot(config, blockSlot, chain.genesisTime)) {
|
|
180
198
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
@@ -186,6 +204,11 @@ export async function validateGossipBlock(
|
|
|
186
204
|
}
|
|
187
205
|
}
|
|
188
206
|
|
|
207
|
+
// [REJECT] The proposer index is a valid validator index
|
|
208
|
+
if (proposerIndex >= blockState.validatorCount) {
|
|
209
|
+
throw new BlockGossipError(GossipAction.REJECT, {code: BlockErrorCode.UNKNOWN_PROPOSER, proposerIndex});
|
|
210
|
+
}
|
|
211
|
+
|
|
189
212
|
// [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
|
|
190
213
|
if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRoot, signedBlock.signature)) {
|
|
191
214
|
const signatureSet = getBlockProposerSignatureSet(chain.config, signedBlock);
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
createSingleSignatureSetFromComponents,
|
|
4
4
|
getExecutionPayloadBidSigningRoot,
|
|
5
5
|
isActiveBuilder,
|
|
6
|
+
isStatePostGloas,
|
|
6
7
|
} from "@lodestar/state-transition";
|
|
7
8
|
import {gloas} from "@lodestar/types";
|
|
8
9
|
import {toRootHex} from "@lodestar/utils";
|
|
@@ -32,6 +33,9 @@ async function validateExecutionPayloadBid(
|
|
|
32
33
|
const parentBlockRootHex = toRootHex(bid.parentBlockRoot);
|
|
33
34
|
const parentBlockHashHex = toRootHex(bid.parentBlockHash);
|
|
34
35
|
const state = await chain.getHeadStateAtCurrentEpoch(RegenCaller.validateGossipExecutionPayloadBid);
|
|
36
|
+
if (!isStatePostGloas(state)) {
|
|
37
|
+
throw new Error(`Expected gloas+ state for execution payload bid validation, got fork=${state.forkName}`);
|
|
38
|
+
}
|
|
35
39
|
|
|
36
40
|
// [IGNORE] `bid.slot` is the current slot or the next slot.
|
|
37
41
|
const currentSlot = chain.clock.currentSlot;
|
|
@@ -83,9 +87,9 @@ async function validateExecutionPayloadBid(
|
|
|
83
87
|
});
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
// [IGNORE] this bid is the highest value bid seen for the
|
|
87
|
-
//
|
|
88
|
-
const bestBid = chain.executionPayloadBidPool.getBestBid(
|
|
90
|
+
// [IGNORE] this bid is the highest value bid seen for the tuple
|
|
91
|
+
// `(bid.slot, bid.parent_block_hash, bid.parent_block_root)`.
|
|
92
|
+
const bestBid = chain.executionPayloadBidPool.getBestBid(bid.slot, parentBlockHashHex, parentBlockRootHex);
|
|
89
93
|
if (bestBid !== null && bestBid.value >= bid.value) {
|
|
90
94
|
throw new ExecutionPayloadBidError(GossipAction.IGNORE, {
|
|
91
95
|
code: ExecutionPayloadBidErrorCode.BID_TOO_LOW,
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import {PayloadStatus} from "@lodestar/fork-choice";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
computeStartSlotAtEpoch,
|
|
4
|
+
getExecutionPayloadEnvelopeSignatureSet,
|
|
5
|
+
isStatePostGloas,
|
|
6
|
+
} from "@lodestar/state-transition";
|
|
3
7
|
import {gloas} from "@lodestar/types";
|
|
4
8
|
import {toRootHex} from "@lodestar/utils";
|
|
5
9
|
import {ExecutionPayloadEnvelopeError, ExecutionPayloadEnvelopeErrorCode, GossipAction} from "../errors/index.js";
|
|
@@ -113,7 +117,12 @@ async function validateExecutionPayloadEnvelope(
|
|
|
113
117
|
slot: envelope.slot,
|
|
114
118
|
});
|
|
115
119
|
});
|
|
120
|
+
if (!isStatePostGloas(blockState)) {
|
|
121
|
+
throw new Error(`Expected gloas+ state for execution payload envelope validation, got fork=${blockState.forkName}`);
|
|
122
|
+
}
|
|
116
123
|
|
|
124
|
+
// [REJECT] `signed_execution_payload_envelope.signature` is valid as verified
|
|
125
|
+
// by `verify_execution_payload_envelope_signature`.
|
|
117
126
|
const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
|
|
118
127
|
chain.config,
|
|
119
128
|
chain.pubkeyCache,
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
computeEpochAtSlot,
|
|
3
3
|
createSingleSignatureSetFromComponents,
|
|
4
4
|
getPayloadAttestationDataSigningRoot,
|
|
5
|
+
isStatePostGloas,
|
|
5
6
|
} from "@lodestar/state-transition";
|
|
6
7
|
import {RootHex, gloas, ssz} from "@lodestar/types";
|
|
7
8
|
import {toRootHex} from "@lodestar/utils";
|
|
@@ -66,6 +67,9 @@ async function validatePayloadAttestationMessage(
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
const state = chain.getHeadState();
|
|
70
|
+
if (!isStatePostGloas(state)) {
|
|
71
|
+
throw new Error(`Expected gloas+ state for payload attestation validation, got fork=${state.forkName}`);
|
|
72
|
+
}
|
|
69
73
|
|
|
70
74
|
// [REJECT] The message's block `data.beacon_block_root` passes validation.
|
|
71
75
|
// TODO GLOAS: implement this. Technically if we cannot get proto block from fork choice,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {SYNC_COMMITTEE_SUBNET_COUNT, SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params";
|
|
2
|
-
import {IBeaconStateView} from "@lodestar/state-transition";
|
|
2
|
+
import {IBeaconStateView, isStatePostAltair} from "@lodestar/state-transition";
|
|
3
3
|
import {SubnetID, altair} from "@lodestar/types";
|
|
4
4
|
import {toRootHex} from "@lodestar/utils";
|
|
5
5
|
import {GossipAction, SyncCommitteeError, SyncCommitteeErrorCode} from "../errors/index.js";
|
|
@@ -148,6 +148,10 @@ function getIndicesInSubcommittee(
|
|
|
148
148
|
subnet: SubnetID,
|
|
149
149
|
data: Pick<altair.SyncCommitteeMessage, "slot" | "validatorIndex">
|
|
150
150
|
): IndexInSubcommittee[] | null {
|
|
151
|
+
if (!isStatePostAltair(headState)) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
151
155
|
const syncCommittee = headState.getIndexedSyncCommittee(data.slot);
|
|
152
156
|
const indexesInCommittee = syncCommittee.validatorIndexMap.get(data.validatorIndex);
|
|
153
157
|
if (indexesInCommittee === undefined) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params";
|
|
2
|
-
import {IBeaconStateView, isSyncCommitteeAggregator} from "@lodestar/state-transition";
|
|
2
|
+
import {IBeaconStateView, isStatePostAltair, isSyncCommitteeAggregator} from "@lodestar/state-transition";
|
|
3
3
|
import {ValidatorIndex, altair} from "@lodestar/types";
|
|
4
4
|
import {GossipAction, SyncCommitteeError, SyncCommitteeErrorCode} from "../errors/index.js";
|
|
5
5
|
import {IBeaconChain} from "../interface.js";
|
|
@@ -107,6 +107,10 @@ function getContributionIndices(
|
|
|
107
107
|
state: IBeaconStateView,
|
|
108
108
|
contribution: altair.SyncCommitteeContribution
|
|
109
109
|
): ValidatorIndex[] {
|
|
110
|
+
if (!isStatePostAltair(state)) {
|
|
111
|
+
throw new Error("Expected Altair state for sync committee contribution");
|
|
112
|
+
}
|
|
113
|
+
|
|
110
114
|
const startIndex = contribution.subcommitteeIndex * SYNC_COMMITTEE_SUBNET_SIZE;
|
|
111
115
|
|
|
112
116
|
const syncCommittee = state.getIndexedSyncCommittee(contribution.slot);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {
|
|
2
|
+
import {MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
3
|
import {
|
|
4
4
|
IBeaconStateView,
|
|
5
5
|
ParticipationFlags,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
computeStartSlotAtEpoch,
|
|
8
8
|
computeTimeAtSlot,
|
|
9
9
|
getCurrentSlot,
|
|
10
|
+
isStatePostAltair,
|
|
10
11
|
parseAttesterFlags,
|
|
11
12
|
parseParticipationFlags,
|
|
12
13
|
} from "@lodestar/state-transition";
|
|
@@ -740,7 +741,7 @@ export function createValidatorMonitor(
|
|
|
740
741
|
|
|
741
742
|
const rootCache = new RootHexCache(headState);
|
|
742
743
|
|
|
743
|
-
if (
|
|
744
|
+
if (isStatePostAltair(headState)) {
|
|
744
745
|
const prevEpochStartSlot = computeStartSlotAtEpoch(prevEpoch);
|
|
745
746
|
const prevEpochTargetRoot = toRootHex(headState.getBlockRootAtSlot(prevEpochStartSlot));
|
|
746
747
|
|
|
@@ -1746,6 +1746,40 @@ export function createLodestarMetrics(
|
|
|
1746
1746
|
}),
|
|
1747
1747
|
},
|
|
1748
1748
|
|
|
1749
|
+
// some gossip messages need to wait for payload to be processed before they can be processed
|
|
1750
|
+
awaitingPayloadGossipMessages: {
|
|
1751
|
+
queue: register.gauge<{topic: GossipType}>({
|
|
1752
|
+
name: "lodestar_awaiting_payload_gossip_messages_total",
|
|
1753
|
+
help: "Total number of gossip messages waiting for payload to be processed",
|
|
1754
|
+
labelNames: ["topic"],
|
|
1755
|
+
}),
|
|
1756
|
+
countPerSlot: register.gauge({
|
|
1757
|
+
name: "lodestar_awaiting_payload_gossip_messages_per_slot_total",
|
|
1758
|
+
help: "Total number of gossip messages waiting for payload to be processed per slot",
|
|
1759
|
+
}),
|
|
1760
|
+
resolve: register.gauge<{topic: GossipType}>({
|
|
1761
|
+
name: "lodestar_awaiting_payload_gossip_messages_resolve_total",
|
|
1762
|
+
help: "Total number of gossip messages are reprocessed",
|
|
1763
|
+
labelNames: ["topic"],
|
|
1764
|
+
}),
|
|
1765
|
+
waitSecBeforeResolve: register.gauge<{topic: GossipType}>({
|
|
1766
|
+
name: "lodestar_awaiting_payload_gossip_messages_wait_time_resolve_seconds",
|
|
1767
|
+
help: "Time to wait for unknown payload in seconds",
|
|
1768
|
+
labelNames: ["topic"],
|
|
1769
|
+
}),
|
|
1770
|
+
// having 2 labels here is not great for performance, however it's rarely happening and having the reason label is important for debugging
|
|
1771
|
+
reject: register.gauge<{reason: ReprocessRejectReason; topic: GossipType}>({
|
|
1772
|
+
name: "lodestar_awaiting_payload_gossip_messages_reject_total",
|
|
1773
|
+
help: "Total number of gossip messages are rejected to reprocess",
|
|
1774
|
+
labelNames: ["reason", "topic"],
|
|
1775
|
+
}),
|
|
1776
|
+
waitSecBeforeReject: register.gauge<{reason: ReprocessRejectReason; topic: GossipType}>({
|
|
1777
|
+
name: "lodestar_awaiting_payload_gossip_messages_wait_time_reject_seconds",
|
|
1778
|
+
help: "Time to wait for unknown payload before being rejected",
|
|
1779
|
+
labelNames: ["reason", "topic"],
|
|
1780
|
+
}),
|
|
1781
|
+
},
|
|
1782
|
+
|
|
1749
1783
|
lightclientServer: {
|
|
1750
1784
|
onSyncAggregate: register.gauge<{event: string}>({
|
|
1751
1785
|
name: "lodestar_lightclient_server_on_sync_aggregate_event_total",
|
package/src/network/interface.ts
CHANGED
|
@@ -74,6 +74,7 @@ export interface INetwork extends INetworkCorePublic {
|
|
|
74
74
|
shouldAggregate(subnet: SubnetID, slot: Slot): boolean;
|
|
75
75
|
reStatusPeers(peers: PeerIdStr[]): Promise<void>;
|
|
76
76
|
searchUnknownBlock(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void;
|
|
77
|
+
searchUnknownEnvelope(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void;
|
|
77
78
|
// ReqResp
|
|
78
79
|
sendBeaconBlocksByRange(peerId: PeerIdStr, request: phase0.BeaconBlocksByRangeRequest): Promise<SignedBeaconBlock[]>;
|
|
79
80
|
sendBeaconBlocksByRoot(peerId: PeerIdStr, request: BeaconBlocksByRootRequest): Promise<SignedBeaconBlock[]>;
|
package/src/network/network.ts
CHANGED
|
@@ -285,6 +285,10 @@ export class Network implements INetwork {
|
|
|
285
285
|
this.networkProcessor.searchUnknownBlock(slotRoot, source, peer);
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
searchUnknownEnvelope(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
289
|
+
this.networkProcessor.searchUnknownEnvelope(slotRoot, source, peer);
|
|
290
|
+
}
|
|
291
|
+
|
|
288
292
|
async reportPeer(peer: PeerIdStr, action: PeerAction, actionName: string): Promise<void> {
|
|
289
293
|
return this.core.reportPeer(peer, action, actionName);
|
|
290
294
|
}
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import {ForkName,
|
|
1
|
+
import {ForkName, ForkSeq} from "@lodestar/params";
|
|
2
2
|
import {SlotOptionalRoot, SlotRootHex} from "@lodestar/types";
|
|
3
3
|
import {
|
|
4
4
|
getBeaconBlockRootFromDataColumnSidecarSerialized,
|
|
5
|
-
getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized,
|
|
6
5
|
getBlockRootFromBeaconAttestationSerialized,
|
|
6
|
+
getBlockRootFromPayloadAttestationMessageSerialized,
|
|
7
7
|
getBlockRootFromSignedAggregateAndProofSerialized,
|
|
8
8
|
getSlotFromBeaconAttestationSerialized,
|
|
9
9
|
getSlotFromBlobSidecarSerialized,
|
|
10
10
|
getSlotFromDataColumnSidecarSerialized,
|
|
11
11
|
getSlotFromExecutionPayloadEnvelopeSerialized,
|
|
12
|
+
getSlotFromPayloadAttestationMessageSerialized,
|
|
12
13
|
getSlotFromSignedAggregateAndProofSerialized,
|
|
13
14
|
getSlotFromSignedBeaconBlockSerialized,
|
|
15
|
+
getSlotFromSignedExecutionPayloadBidSerialized,
|
|
14
16
|
} from "../../util/sszBytes.js";
|
|
15
17
|
import {GossipType} from "../gossip/index.js";
|
|
16
18
|
import {ExtractSlotRootFns} from "./types.js";
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
* Extract the slot and block root of a gossip message form serialized data.
|
|
20
|
-
*
|
|
22
|
+
* 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.
|
|
21
23
|
*/
|
|
22
24
|
export function createExtractBlockSlotRootFns(): ExtractSlotRootFns {
|
|
23
25
|
return {
|
|
@@ -57,21 +59,45 @@ export function createExtractBlockSlotRootFns(): ExtractSlotRootFns {
|
|
|
57
59
|
},
|
|
58
60
|
[GossipType.data_column_sidecar]: (data: Uint8Array, fork: ForkName): SlotOptionalRoot | null => {
|
|
59
61
|
const slot = getSlotFromDataColumnSidecarSerialized(data, fork);
|
|
62
|
+
|
|
60
63
|
if (slot === null) {
|
|
61
64
|
return null;
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
if (ForkSeq[fork] < ForkSeq.gloas) {
|
|
68
|
+
return {slot};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const root = getBeaconBlockRootFromDataColumnSidecarSerialized(data);
|
|
72
|
+
// null root means the message is invalid here and will be ignored in gossip handler later
|
|
73
|
+
// returning the slot here helps check the earliest permissable slot in the network processor
|
|
65
74
|
return root !== null ? {slot, root} : {slot};
|
|
66
75
|
},
|
|
67
|
-
[GossipType.execution_payload]: (data: Uint8Array):
|
|
76
|
+
[GossipType.execution_payload]: (data: Uint8Array): SlotOptionalRoot | null => {
|
|
68
77
|
const slot = getSlotFromExecutionPayloadEnvelopeSerialized(data);
|
|
69
|
-
|
|
78
|
+
// Do not extract the root here; the network processor will extract it in the 2nd round to trigger block search without awaiting.
|
|
79
|
+
if (slot === null) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return {slot};
|
|
83
|
+
},
|
|
84
|
+
[GossipType.payload_attestation_message]: (data: Uint8Array): SlotRootHex | null => {
|
|
85
|
+
const slot = getSlotFromPayloadAttestationMessageSerialized(data);
|
|
86
|
+
const root = getBlockRootFromPayloadAttestationMessageSerialized(data);
|
|
70
87
|
|
|
71
88
|
if (slot === null || root === null) {
|
|
72
89
|
return null;
|
|
73
90
|
}
|
|
74
91
|
return {slot, root};
|
|
75
92
|
},
|
|
93
|
+
[GossipType.execution_payload_bid]: (data: Uint8Array): SlotOptionalRoot | null => {
|
|
94
|
+
const slot = getSlotFromSignedExecutionPayloadBidSerialized(data);
|
|
95
|
+
|
|
96
|
+
if (slot === null) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {slot};
|
|
101
|
+
},
|
|
76
102
|
};
|
|
77
103
|
}
|
|
@@ -169,16 +169,19 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
169
169
|
|
|
170
170
|
logger.debug("Received gossip block", {...logCtx});
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
// optimistically add gossip block to the seen cache
|
|
173
|
+
// if validation fails, we will NOT forward this gossip block to peers
|
|
174
|
+
// - if PARENT_UNKNOWN error, blockInput will then be queued inside BlockInputSync. If the gossip block is really invalid, it will be pruned there
|
|
175
|
+
// - if other validator errors, blockInput will stay in the seen cache and will be pruned on finalization
|
|
176
|
+
const blockInput = chain.seenBlockInputCache.getByBlock({
|
|
177
|
+
block: signedBlock,
|
|
178
|
+
blockRootHex,
|
|
179
|
+
source: BlockInputSource.gossip,
|
|
180
|
+
seenTimestampSec,
|
|
181
|
+
peerIdStr,
|
|
182
|
+
});
|
|
173
183
|
try {
|
|
174
184
|
await validateGossipBlock(config, chain, signedBlock, fork);
|
|
175
|
-
blockInput = chain.seenBlockInputCache.getByBlock({
|
|
176
|
-
block: signedBlock,
|
|
177
|
-
blockRootHex,
|
|
178
|
-
source: BlockInputSource.gossip,
|
|
179
|
-
seenTimestampSec,
|
|
180
|
-
peerIdStr,
|
|
181
|
-
});
|
|
182
185
|
const blockInputMeta = blockInput.getLogMeta();
|
|
183
186
|
|
|
184
187
|
const recvToValidation = Date.now() / 1000 - seenTimestampSec;
|
|
@@ -194,9 +197,9 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
194
197
|
return blockInput;
|
|
195
198
|
} catch (e) {
|
|
196
199
|
if (e instanceof BlockGossipError) {
|
|
200
|
+
logger.debug("Gossip block has error", {slot, root: blockShortHex, code: e.type.code});
|
|
197
201
|
if (e.type.code === BlockErrorCode.PARENT_UNKNOWN && blockInput) {
|
|
198
|
-
|
|
199
|
-
chain.emitter.emit(ChainEvent.unknownParent, {
|
|
202
|
+
chain.emitter.emit(ChainEvent.blockUnknownParent, {
|
|
200
203
|
blockInput,
|
|
201
204
|
peer: peerIdStr,
|
|
202
205
|
source: BlockInputSource.gossip,
|
|
@@ -1037,8 +1040,37 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1037
1040
|
const {serializedData} = gossipData;
|
|
1038
1041
|
const signedEnvelope = sszDeserialize(topic, serializedData);
|
|
1039
1042
|
const envelope = signedEnvelope.message;
|
|
1040
|
-
|
|
1041
|
-
|
|
1043
|
+
|
|
1044
|
+
// TODO GLOAS: consider optimistically create PayloadEnvelopeInput here similar to how we do that for beacon_block
|
|
1045
|
+
// so that UnknownBlockSync can handle backward sync
|
|
1046
|
+
// the problem now is we cannot create a PayloadEnvelopeInput without the beacon block being known, we need at least the proposer index
|
|
1047
|
+
// we can achieve that by looking into the EpochCache
|
|
1048
|
+
try {
|
|
1049
|
+
await validateGossipExecutionPayloadEnvelope(chain, signedEnvelope);
|
|
1050
|
+
} catch (e) {
|
|
1051
|
+
if (e instanceof ExecutionPayloadEnvelopeError) {
|
|
1052
|
+
const {slot, beaconBlockRoot} = signedEnvelope.message;
|
|
1053
|
+
logger.debug("Gossip envelope has error", {slot, root: toRootHex(beaconBlockRoot), code: e.type.code});
|
|
1054
|
+
if (e.type.code === ExecutionPayloadEnvelopeErrorCode.BLOCK_ROOT_UNKNOWN) {
|
|
1055
|
+
// TODO GLOAS: UnknownBlockSync to handle this
|
|
1056
|
+
chain.emitter.emit(ChainEvent.envelopeUnknownBlock, {
|
|
1057
|
+
envelope: signedEnvelope,
|
|
1058
|
+
peer: peerIdStr,
|
|
1059
|
+
source: BlockInputSource.gossip,
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
if (e.action === GossipAction.REJECT) {
|
|
1064
|
+
chain.persistInvalidSszValue(
|
|
1065
|
+
ssz.gloas.SignedExecutionPayloadEnvelope,
|
|
1066
|
+
signedEnvelope,
|
|
1067
|
+
`gossip_reject_slot_${slot}`
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
throw e;
|
|
1073
|
+
}
|
|
1042
1074
|
|
|
1043
1075
|
const slot = envelope.slot;
|
|
1044
1076
|
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
@@ -1116,6 +1148,11 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1116
1148
|
} catch (e) {
|
|
1117
1149
|
logger.error("Error adding to executionPayloadBid pool", {}, e as Error);
|
|
1118
1150
|
}
|
|
1151
|
+
|
|
1152
|
+
chain.emitter.emit(routes.events.EventType.executionPayloadBid, {
|
|
1153
|
+
version: config.getForkName(executionPayloadBid.message.slot),
|
|
1154
|
+
data: executionPayloadBid,
|
|
1155
|
+
});
|
|
1119
1156
|
},
|
|
1120
1157
|
};
|
|
1121
1158
|
}
|