@lodestar/beacon-node 1.43.0-dev.2870b59b6a → 1.43.0-dev.4fb05c546d
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/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +4 -3
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +1 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +1 -2
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +23 -31
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +10 -8
- 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/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +20 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +6 -4
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +1 -1
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +25 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +14 -30
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +13 -1
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -0
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +12 -4
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +22 -16
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -9
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +5 -32
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -8
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +24 -19
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +1 -11
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +0 -2
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +6 -11
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +6 -10
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +3 -10
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +0 -5
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +0 -8
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +1 -7
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +0 -8
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +0 -6
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +1 -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 -3
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +19 -3
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/package.json +16 -16
- package/src/api/impl/validator/index.ts +6 -5
- package/src/chain/GetBlobsTracker.ts +1 -2
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +2 -4
- package/src/chain/blocks/importBlock.ts +22 -35
- package/src/chain/blocks/importExecutionPayload.ts +11 -7
- package/src/chain/blocks/index.ts +1 -1
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +6 -5
- package/src/chain/blocks/types.ts +1 -1
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
- package/src/chain/chain.ts +13 -32
- package/src/chain/emitter.ts +12 -0
- package/src/chain/forkChoice/index.ts +12 -4
- package/src/chain/prepareNextSlot.ts +25 -16
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
- package/src/chain/produceBlock/produceBlockBody.ts +34 -20
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +6 -11
- package/src/chain/regen/queued.ts +6 -14
- package/src/chain/regen/regen.ts +0 -8
- package/src/chain/stateCache/persistentCheckpointsCache.ts +1 -14
- package/src/chain/stateCache/types.ts +0 -3
- package/src/chain/validation/executionPayloadEnvelope.ts +1 -1
- package/src/chain/validation/payloadAttestationMessage.ts +5 -3
- package/src/network/processor/gossipHandlers.ts +23 -7
- package/src/node/nodejs.ts +4 -2
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
IBeaconStateView,
|
|
20
20
|
type IBeaconStateViewBellatrix,
|
|
21
21
|
computeTimeAtSlot,
|
|
22
|
-
isParentBlockFull,
|
|
23
22
|
isStatePostBellatrix,
|
|
24
23
|
isStatePostCapella,
|
|
25
24
|
isStatePostGloas,
|
|
@@ -48,7 +47,7 @@ import {
|
|
|
48
47
|
fulu,
|
|
49
48
|
gloas,
|
|
50
49
|
} from "@lodestar/types";
|
|
51
|
-
import {Logger, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
50
|
+
import {Logger, byteArrayEquals, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
52
51
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
53
52
|
import {numToQuantity} from "../../execution/engine/utils.js";
|
|
54
53
|
import {
|
|
@@ -111,12 +110,6 @@ export type ProduceFullGloas = {
|
|
|
111
110
|
executionRequests: electra.ExecutionRequests;
|
|
112
111
|
blobsBundle: BlobsBundle<ForkPostGloas>;
|
|
113
112
|
cells: fulu.Cell[][];
|
|
114
|
-
/**
|
|
115
|
-
* Cached payload envelope state root computed during block production.
|
|
116
|
-
* This is the state root after running `processExecutionPayloadEnvelope` on the
|
|
117
|
-
* post-block state, and later used to construct the `ExecutionPayloadEnvelope`.
|
|
118
|
-
*/
|
|
119
|
-
payloadEnvelopeStateRoot: Root;
|
|
120
113
|
};
|
|
121
114
|
export type ProduceFullFulu = {
|
|
122
115
|
type: BlockType.Full;
|
|
@@ -220,11 +213,15 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
220
213
|
});
|
|
221
214
|
|
|
222
215
|
// Get execution payload from EL
|
|
216
|
+
const parentBlockHash = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot))
|
|
217
|
+
? currentState.latestExecutionPayloadBid.blockHash
|
|
218
|
+
: currentState.latestExecutionPayloadBid.parentBlockHash;
|
|
223
219
|
const prepareRes = await prepareExecutionPayload(
|
|
224
220
|
this,
|
|
225
221
|
this.logger,
|
|
226
222
|
fork,
|
|
227
223
|
parentBlockRoot,
|
|
224
|
+
parentBlockHash,
|
|
228
225
|
safeBlockHash,
|
|
229
226
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
230
227
|
currentState,
|
|
@@ -261,8 +258,8 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
261
258
|
|
|
262
259
|
// Create self-build execution payload bid
|
|
263
260
|
const bid: gloas.ExecutionPayloadBid = {
|
|
264
|
-
parentBlockHash
|
|
265
|
-
parentBlockRoot
|
|
261
|
+
parentBlockHash,
|
|
262
|
+
parentBlockRoot,
|
|
266
263
|
blockHash: executionPayload.blockHash,
|
|
267
264
|
prevRandao: currentState.getRandaoMix(currentState.epoch),
|
|
268
265
|
feeRecipient: executionPayload.feeRecipient,
|
|
@@ -340,6 +337,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
340
337
|
this.logger,
|
|
341
338
|
fork,
|
|
342
339
|
parentBlockRoot,
|
|
340
|
+
currentState.latestExecutionPayloadHeader.blockHash,
|
|
343
341
|
safeBlockHash,
|
|
344
342
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
345
343
|
currentState,
|
|
@@ -448,6 +446,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
448
446
|
this.logger,
|
|
449
447
|
fork,
|
|
450
448
|
parentBlockRoot,
|
|
449
|
+
currentState.latestExecutionPayloadHeader.blockHash,
|
|
451
450
|
safeBlockHash,
|
|
452
451
|
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
453
452
|
currentState,
|
|
@@ -613,17 +612,17 @@ export async function prepareExecutionPayload(
|
|
|
613
612
|
logger: Logger,
|
|
614
613
|
fork: ForkPostBellatrix,
|
|
615
614
|
parentBlockRoot: Root,
|
|
615
|
+
parentBlockHash: Bytes32,
|
|
616
616
|
safeBlockHash: RootHex,
|
|
617
617
|
finalizedBlockHash: RootHex,
|
|
618
618
|
state: IBeaconStateViewBellatrix,
|
|
619
619
|
suggestedFeeRecipient: string
|
|
620
620
|
): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
|
|
621
|
-
const parentHash = state.latestBlockHash;
|
|
622
621
|
const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
|
|
623
622
|
const prevRandao = state.getRandaoMix(state.epoch);
|
|
624
623
|
|
|
625
624
|
const payloadIdCached = chain.executionEngine.payloadIdCache.get({
|
|
626
|
-
headBlockHash: toRootHex(
|
|
625
|
+
headBlockHash: toRootHex(parentBlockHash),
|
|
627
626
|
finalizedBlockHash,
|
|
628
627
|
timestamp: numToQuantity(timestamp),
|
|
629
628
|
prevRandao: toHex(prevRandao),
|
|
@@ -652,12 +651,13 @@ export async function prepareExecutionPayload(
|
|
|
652
651
|
prepareState: state,
|
|
653
652
|
prepareSlot: state.slot,
|
|
654
653
|
parentBlockRoot,
|
|
654
|
+
parentBlockHash,
|
|
655
655
|
feeRecipient: suggestedFeeRecipient,
|
|
656
656
|
});
|
|
657
657
|
|
|
658
658
|
payloadId = await chain.executionEngine.notifyForkchoiceUpdate(
|
|
659
659
|
fork,
|
|
660
|
-
toRootHex(
|
|
660
|
+
toRootHex(parentBlockHash),
|
|
661
661
|
safeBlockHash,
|
|
662
662
|
finalizedBlockHash,
|
|
663
663
|
attributes
|
|
@@ -709,20 +709,30 @@ export function getPayloadAttributesForSSE(
|
|
|
709
709
|
prepareState,
|
|
710
710
|
prepareSlot,
|
|
711
711
|
parentBlockRoot,
|
|
712
|
+
parentBlockHash,
|
|
712
713
|
feeRecipient,
|
|
713
|
-
}: {
|
|
714
|
+
}: {
|
|
715
|
+
prepareState: IBeaconStateViewBellatrix;
|
|
716
|
+
prepareSlot: Slot;
|
|
717
|
+
parentBlockRoot: Root;
|
|
718
|
+
parentBlockHash: Bytes32;
|
|
719
|
+
feeRecipient: string;
|
|
720
|
+
}
|
|
714
721
|
): SSEPayloadAttributes {
|
|
715
|
-
const parentHash = prepareState.latestBlockHash;
|
|
716
722
|
const payloadAttributes = preparePayloadAttributes(fork, chain, {
|
|
717
723
|
prepareState,
|
|
718
724
|
prepareSlot,
|
|
719
725
|
parentBlockRoot,
|
|
726
|
+
parentBlockHash,
|
|
720
727
|
feeRecipient,
|
|
721
728
|
});
|
|
722
729
|
|
|
723
730
|
let parentBlockNumber: number;
|
|
724
731
|
if (isForkPostGloas(fork)) {
|
|
725
|
-
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
|
|
732
|
+
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
|
|
733
|
+
toRootHex(parentBlockRoot),
|
|
734
|
+
toRootHex(parentBlockHash)
|
|
735
|
+
);
|
|
726
736
|
if (parentBlock?.executionPayloadBlockHash == null) {
|
|
727
737
|
throw Error(`Parent block not found in fork choice root=${toRootHex(parentBlockRoot)}`);
|
|
728
738
|
}
|
|
@@ -736,7 +746,7 @@ export function getPayloadAttributesForSSE(
|
|
|
736
746
|
proposalSlot: prepareSlot,
|
|
737
747
|
parentBlockNumber,
|
|
738
748
|
parentBlockRoot,
|
|
739
|
-
parentBlockHash
|
|
749
|
+
parentBlockHash,
|
|
740
750
|
payloadAttributes,
|
|
741
751
|
};
|
|
742
752
|
return ssePayloadAttributes;
|
|
@@ -751,11 +761,13 @@ function preparePayloadAttributes(
|
|
|
751
761
|
prepareState,
|
|
752
762
|
prepareSlot,
|
|
753
763
|
parentBlockRoot,
|
|
764
|
+
parentBlockHash,
|
|
754
765
|
feeRecipient,
|
|
755
766
|
}: {
|
|
756
767
|
prepareState: IBeaconStateViewBellatrix;
|
|
757
768
|
prepareSlot: Slot;
|
|
758
769
|
parentBlockRoot: Root;
|
|
770
|
+
parentBlockHash: Bytes32;
|
|
759
771
|
feeRecipient: string;
|
|
760
772
|
}
|
|
761
773
|
): SSEPayloadAttributes["payloadAttributes"] {
|
|
@@ -772,13 +784,15 @@ function preparePayloadAttributes(
|
|
|
772
784
|
throw new Error("Expected Capella state for withdrawals");
|
|
773
785
|
}
|
|
774
786
|
|
|
775
|
-
if (isStatePostGloas(prepareState)
|
|
787
|
+
if (isStatePostGloas(prepareState)) {
|
|
788
|
+
const isExtendingPayload = byteArrayEquals(parentBlockHash, prepareState.latestExecutionPayloadBid.blockHash);
|
|
776
789
|
// When the parent block is empty, state.payloadExpectedWithdrawals holds a batch
|
|
777
790
|
// already deducted from CL balances but never credited on the EL (the envelope
|
|
778
791
|
// was not delivered). The next payload must carry those same withdrawals to
|
|
779
792
|
// restore CL/EL consistency, otherwise validators permanently lose that balance.
|
|
780
|
-
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
781
|
-
prepareState.
|
|
793
|
+
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals = isExtendingPayload
|
|
794
|
+
? prepareState.getExpectedWithdrawals().expectedWithdrawals
|
|
795
|
+
: prepareState.payloadExpectedWithdrawals;
|
|
782
796
|
} else {
|
|
783
797
|
// withdrawals logic is now fork aware as it changes on electra fork post capella
|
|
784
798
|
(payloadAttributes as capella.SSEPayloadAttributes["payloadAttributes"]).withdrawals =
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {PayloadStatus} from "@lodestar/fork-choice";
|
|
2
1
|
import {Root, RootHex, Slot} from "@lodestar/types";
|
|
3
2
|
|
|
4
3
|
export enum RegenErrorCode {
|
|
@@ -10,8 +9,6 @@ export enum RegenErrorCode {
|
|
|
10
9
|
BLOCK_NOT_IN_DB = "REGEN_ERROR_BLOCK_NOT_IN_DB",
|
|
11
10
|
STATE_TRANSITION_ERROR = "REGEN_ERROR_STATE_TRANSITION_ERROR",
|
|
12
11
|
INVALID_STATE_ROOT = "REGEN_ERROR_INVALID_STATE_ROOT",
|
|
13
|
-
UNEXPECTED_PAYLOAD_STATUS = "REGEN_ERROR_UNEXPECTED_PAYLOAD_STATUS",
|
|
14
|
-
INTERNAL_ERROR = "REGEN_ERROR_INTERNAL_ERROR",
|
|
15
12
|
}
|
|
16
13
|
|
|
17
14
|
export type RegenErrorType =
|
|
@@ -22,9 +19,7 @@ export type RegenErrorType =
|
|
|
22
19
|
| {code: RegenErrorCode.TOO_MANY_BLOCK_PROCESSED; stateRoot: RootHex | Root}
|
|
23
20
|
| {code: RegenErrorCode.BLOCK_NOT_IN_DB; blockRoot: RootHex | Root}
|
|
24
21
|
| {code: RegenErrorCode.STATE_TRANSITION_ERROR; error: Error}
|
|
25
|
-
| {code: RegenErrorCode.INVALID_STATE_ROOT; slot: Slot; expected: RootHex; actual: RootHex}
|
|
26
|
-
| {code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS; blockRoot: RootHex | Root; payloadStatus: PayloadStatus}
|
|
27
|
-
| {code: RegenErrorCode.INTERNAL_ERROR; message: string};
|
|
22
|
+
| {code: RegenErrorCode.INVALID_STATE_ROOT; slot: Slot; expected: RootHex; actual: RootHex};
|
|
28
23
|
|
|
29
24
|
export class RegenError extends Error {
|
|
30
25
|
type: RegenErrorType;
|
|
@@ -2,7 +2,7 @@ import {routes} from "@lodestar/api";
|
|
|
2
2
|
import {ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {IBeaconStateView} from "@lodestar/state-transition";
|
|
4
4
|
import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
5
|
-
import {
|
|
5
|
+
import {CheckpointHex} from "../stateCache/types.js";
|
|
6
6
|
|
|
7
7
|
export enum RegenCaller {
|
|
8
8
|
getDuties = "getDuties",
|
|
@@ -40,20 +40,15 @@ export interface IStateRegenerator extends IStateRegeneratorInternal {
|
|
|
40
40
|
dumpCacheSummary(): routes.lodestar.StateCacheItem[];
|
|
41
41
|
getStateSync(stateRoot: RootHex): IBeaconStateView | null;
|
|
42
42
|
getPreStateSync(block: BeaconBlock): IBeaconStateView | null;
|
|
43
|
-
getCheckpointStateOrBytes(cp:
|
|
44
|
-
getCheckpointStateSync(cp:
|
|
43
|
+
getCheckpointStateOrBytes(cp: CheckpointHex): Promise<IBeaconStateView | Uint8Array | null>;
|
|
44
|
+
getCheckpointStateSync(cp: CheckpointHex): IBeaconStateView | null;
|
|
45
45
|
getClosestHeadState(head: ProtoBlock): IBeaconStateView | null;
|
|
46
46
|
pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void;
|
|
47
47
|
pruneOnFinalized(finalizedEpoch: Epoch): void;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* payloadPresent is true if this is payload state, false if block state.
|
|
52
|
-
* payloadPresent is always true for pre-gloas.
|
|
53
|
-
*/
|
|
54
|
-
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView, payloadPresent: boolean): void;
|
|
48
|
+
processState(blockRootHex: RootHex, postState: IBeaconStateView): void;
|
|
49
|
+
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView): void;
|
|
55
50
|
updateHeadState(newHead: ProtoBlock, maybeHeadState: IBeaconStateView): void;
|
|
56
|
-
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch
|
|
51
|
+
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null;
|
|
57
52
|
}
|
|
58
53
|
|
|
59
54
|
/**
|
|
@@ -5,7 +5,7 @@ import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lo
|
|
|
5
5
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
8
|
-
import {BlockStateCache,
|
|
8
|
+
import {BlockStateCache, CheckpointHex, CheckpointStateCache} from "../stateCache/types.js";
|
|
9
9
|
import {RegenError, RegenErrorCode} from "./errors.js";
|
|
10
10
|
import {
|
|
11
11
|
IStateRegenerator,
|
|
@@ -125,14 +125,14 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
125
125
|
return null;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
async getCheckpointStateOrBytes(cp:
|
|
128
|
+
async getCheckpointStateOrBytes(cp: CheckpointHex): Promise<IBeaconStateView | Uint8Array | null> {
|
|
129
129
|
return this.checkpointStateCache.getStateOrBytes(cp);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
133
|
* Get checkpoint state from cache
|
|
134
134
|
*/
|
|
135
|
-
getCheckpointStateSync(cp:
|
|
135
|
+
getCheckpointStateSync(cp: CheckpointHex): IBeaconStateView | null {
|
|
136
136
|
return this.checkpointStateCache.get(cp);
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -153,22 +153,14 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
153
153
|
this.blockStateCache.deleteAllBeforeEpoch(finalizedEpoch);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
processState(blockRootHex: RootHex, postState: IBeaconStateView): void {
|
|
157
157
|
this.blockStateCache.add(postState);
|
|
158
158
|
this.checkpointStateCache.processState(blockRootHex, postState).catch((e) => {
|
|
159
159
|
this.logger.debug("Error processing block state", {blockRootHex, slot: postState.slot}, e);
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
* Process payload state for caching after importing execution payload.
|
|
165
|
-
*/
|
|
166
|
-
processPayloadState(payloadState: IBeaconStateView): void {
|
|
167
|
-
// Add payload state to block state cache (keyed by payload state root)
|
|
168
|
-
this.blockStateCache.add(payloadState);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView, _payloadPresent: boolean): void {
|
|
163
|
+
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView): void {
|
|
172
164
|
this.checkpointStateCache.add(cp, item);
|
|
173
165
|
}
|
|
174
166
|
|
|
@@ -205,7 +197,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
205
197
|
}
|
|
206
198
|
}
|
|
207
199
|
|
|
208
|
-
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch
|
|
200
|
+
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null {
|
|
209
201
|
return this.checkpointStateCache.updatePreComputedCheckpoint(rootHex, epoch);
|
|
210
202
|
}
|
|
211
203
|
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -332,11 +332,6 @@ async function processSlotsByCheckpoint(
|
|
|
332
332
|
* emitting "checkpoint" events after every epoch processed.
|
|
333
333
|
*
|
|
334
334
|
* Stops processing after no more full epochs can be processed.
|
|
335
|
-
*
|
|
336
|
-
* Output state variant:
|
|
337
|
-
* - Post-Gloas: If slots are processed, returns block state (payloadPresent=false).
|
|
338
|
-
* If no slots processed, returns preState as-is (preserves variant).
|
|
339
|
-
* - Pre-Gloas: Always payloadPresent=true (no block/payload distinction).
|
|
340
335
|
*/
|
|
341
336
|
export async function processSlotsToNearestCheckpoint(
|
|
342
337
|
modules: {
|
|
@@ -380,9 +375,6 @@ export async function processSlotsToNearestCheckpoint(
|
|
|
380
375
|
// This may becomes the "official" checkpoint state if the 1st block of epoch is skipped
|
|
381
376
|
const checkpointState = postState;
|
|
382
377
|
const cp = getCheckpointFromState(checkpointState);
|
|
383
|
-
// processSlots() only does epoch transitions, never processes payloads
|
|
384
|
-
// Pre-Gloas: payloadPresent is always true (execution payload embedded in block)
|
|
385
|
-
// Post-Gloas: result is a block state (payloadPresent=false)
|
|
386
378
|
checkpointStateCache.add(cp, checkpointState);
|
|
387
379
|
// consumers should not mutate state ever
|
|
388
380
|
emitter?.emit(ChainEvent.checkpoint, cp, checkpointState);
|
|
@@ -9,7 +9,7 @@ import {IClock} from "../../util/clock.js";
|
|
|
9
9
|
import {serializeState} from "../serializeState.js";
|
|
10
10
|
import {CPStateDatastore, DatastoreKey} from "./datastore/index.js";
|
|
11
11
|
import {MapTracker} from "./mapMetrics.js";
|
|
12
|
-
import {BlockStateCache, CacheItemType, CheckpointHex,
|
|
12
|
+
import {BlockStateCache, CacheItemType, CheckpointHex, CheckpointStateCache} from "./types.js";
|
|
13
13
|
|
|
14
14
|
export type PersistentCheckpointStateCacheOpts = {
|
|
15
15
|
/** Keep max n state epochs in memory, persist the rest to disk */
|
|
@@ -843,19 +843,6 @@ export function toCheckpointHex(checkpoint: phase0.Checkpoint): CheckpointHex {
|
|
|
843
843
|
};
|
|
844
844
|
}
|
|
845
845
|
|
|
846
|
-
/** TODO GLOAS: remove after rolling back regen dual-state changes */
|
|
847
|
-
export function fcCheckpointToHexPayload(checkpoint: {
|
|
848
|
-
epoch: Epoch;
|
|
849
|
-
rootHex: RootHex;
|
|
850
|
-
payloadStatus?: number;
|
|
851
|
-
}): CheckpointHexPayload {
|
|
852
|
-
return {
|
|
853
|
-
epoch: checkpoint.epoch,
|
|
854
|
-
rootHex: checkpoint.rootHex,
|
|
855
|
-
payloadPresent: true,
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
|
|
859
846
|
export function toCheckpointKey(cp: CheckpointHex): string {
|
|
860
847
|
return `${cp.rootHex}:${cp.epoch}`;
|
|
861
848
|
}
|
|
@@ -4,9 +4,6 @@ import {Epoch, RootHex, phase0} from "@lodestar/types";
|
|
|
4
4
|
|
|
5
5
|
export type CheckpointHex = {epoch: Epoch; rootHex: RootHex};
|
|
6
6
|
|
|
7
|
-
/** TODO GLOAS: payloadPresent is ignored — remove after rolling back regen dual-state changes */
|
|
8
|
-
export type CheckpointHexPayload = {epoch: Epoch; rootHex: RootHex; payloadPresent: boolean};
|
|
9
|
-
|
|
10
7
|
/**
|
|
11
8
|
* Lodestar currently keeps two state caches around.
|
|
12
9
|
*
|
|
@@ -107,7 +107,7 @@ async function validateExecutionPayloadEnvelope(
|
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
// Get the
|
|
110
|
+
// Get the block state to verify the builder's signature.
|
|
111
111
|
const blockState = await chain.regen
|
|
112
112
|
.getState(block.stateRoot, RegenCaller.validateGossipPayloadEnvelope)
|
|
113
113
|
.catch(() => {
|
|
@@ -18,7 +18,8 @@ export async function validateApiPayloadAttestationMessage(
|
|
|
18
18
|
chain: IBeaconChain,
|
|
19
19
|
payloadAttestationMessage: gloas.PayloadAttestationMessage
|
|
20
20
|
): Promise<PayloadAttestationValidationResult> {
|
|
21
|
-
|
|
21
|
+
const prioritizeBls = true;
|
|
22
|
+
return validatePayloadAttestationMessage(chain, payloadAttestationMessage, prioritizeBls);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export async function validateGossipPayloadAttestationMessage(
|
|
@@ -30,7 +31,8 @@ export async function validateGossipPayloadAttestationMessage(
|
|
|
30
31
|
|
|
31
32
|
async function validatePayloadAttestationMessage(
|
|
32
33
|
chain: IBeaconChain,
|
|
33
|
-
payloadAttestationMessage: gloas.PayloadAttestationMessage
|
|
34
|
+
payloadAttestationMessage: gloas.PayloadAttestationMessage,
|
|
35
|
+
prioritizeBls = false
|
|
34
36
|
): Promise<PayloadAttestationValidationResult> {
|
|
35
37
|
const {data, validatorIndex} = payloadAttestationMessage;
|
|
36
38
|
const epoch = computeEpochAtSlot(data.slot);
|
|
@@ -102,7 +104,7 @@ async function validatePayloadAttestationMessage(
|
|
|
102
104
|
payloadAttestationMessage.signature
|
|
103
105
|
);
|
|
104
106
|
|
|
105
|
-
if (!(await chain.bls.verifySignatureSets([signatureSet]))) {
|
|
107
|
+
if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
|
|
106
108
|
throw new PayloadAttestationError(GossipAction.REJECT, {
|
|
107
109
|
code: PayloadAttestationErrorCode.INVALID_SIGNATURE,
|
|
108
110
|
});
|
|
@@ -745,13 +745,29 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
745
745
|
});
|
|
746
746
|
}
|
|
747
747
|
|
|
748
|
-
chain.processExecutionPayload
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
);
|
|
754
|
-
|
|
748
|
+
// NOTE: we do NOT call chain.processExecutionPayload here. That is triggered only by
|
|
749
|
+
// envelope arrival (gossip or API). An in-flight importExecutionPayload is awaiting
|
|
750
|
+
// payloadInput.waitForAllData(); addColumn above will resolve it once hasAllData flips.
|
|
751
|
+
|
|
752
|
+
if (!payloadInput.isComplete()) {
|
|
753
|
+
const cutoffTimeMs = getCutoffTimeMs(chain, dataColumnSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
|
|
754
|
+
// do not await here to not delay gossip validation
|
|
755
|
+
payloadInput.waitForEnvelopeAndAllData(cutoffTimeMs).catch((_e) => {
|
|
756
|
+
chain.logger.debug(
|
|
757
|
+
"Waited for envelope and data after receiving gossip column. Cut-off reached so emitting incompletePayloadEnvelope",
|
|
758
|
+
{
|
|
759
|
+
dataColumnIndex: index,
|
|
760
|
+
...payloadInputMeta,
|
|
761
|
+
}
|
|
762
|
+
);
|
|
763
|
+
// TODO GLOAS: UnknownBlockSync to handle this event
|
|
764
|
+
chain.emitter.emit(ChainEvent.incompletePayloadEnvelope, {
|
|
765
|
+
payloadInput,
|
|
766
|
+
peer: peerIdStr,
|
|
767
|
+
source: BlockInputSource.gossip,
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
}
|
|
755
771
|
} else {
|
|
756
772
|
if (config.getForkSeq(dataColumnSlot) < ForkSeq.fulu) {
|
|
757
773
|
throw new GossipActionError(GossipAction.REJECT, {code: "PRE_FULU_BLOCK"});
|
package/src/node/nodejs.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
|
6
6
|
import {BeaconConfig} from "@lodestar/config";
|
|
7
7
|
import type {LoggerNode} from "@lodestar/logger/node";
|
|
8
8
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
9
|
-
import {IBeaconStateView, PubkeyCache, isStatePostBellatrix} from "@lodestar/state-transition";
|
|
9
|
+
import {IBeaconStateView, PubkeyCache, isStatePostBellatrix, isStatePostGloas} from "@lodestar/state-transition";
|
|
10
10
|
import {phase0} from "@lodestar/types";
|
|
11
11
|
import {sleep, toRootHex} from "@lodestar/utils";
|
|
12
12
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
@@ -223,7 +223,9 @@ export class BeaconNode {
|
|
|
223
223
|
if (opts.executionEngine.mode === "mock") {
|
|
224
224
|
const eth1BlockHash =
|
|
225
225
|
isStatePostBellatrix(anchorState) && anchorState.isExecutionStateType
|
|
226
|
-
?
|
|
226
|
+
? isStatePostGloas(anchorState)
|
|
227
|
+
? toRootHex(anchorState.latestBlockHash)
|
|
228
|
+
: toRootHex(anchorState.latestExecutionPayloadHeader.blockHash)
|
|
227
229
|
: undefined;
|
|
228
230
|
executionEngineOpts = {
|
|
229
231
|
...opts.executionEngine,
|