@lodestar/beacon-node 1.43.0-dev.aef3645690 → 1.43.0-dev.b741495bdc
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 +1 -4
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -2
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +1 -4
- 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/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +4 -4
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
- 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/archiveStore/utils/archiveBlocks.d.ts +2 -2
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +27 -35
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +15 -14
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +63 -85
- 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 +1 -2
- 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 +15 -21
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +76 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
- 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/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +1 -1
- package/lib/chain/chain.d.ts +3 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +19 -39
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +16 -4
- 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/errors/attestationError.d.ts +8 -1
- package/lib/chain/errors/attestationError.d.ts.map +1 -1
- package/lib/chain/errors/attestationError.js +4 -0
- package/lib/chain/errors/attestationError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +1 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +11 -15
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.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 +30 -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 -12
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +6 -11
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +8 -40
- 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 +7 -34
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/stateCache/datastore/db.d.ts +5 -4
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +10 -32
- package/lib/chain/stateCache/datastore/db.js.map +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/file.js +5 -5
- package/lib/chain/stateCache/datastore/file.js.map +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -7
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -8
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +13 -30
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +120 -216
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +8 -15
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +12 -0
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +12 -0
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +13 -1
- 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 +21 -11
- 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/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +21 -14
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -0
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +6 -0
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/types.d.ts +20 -0
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +18 -0
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +3 -729
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/network.js +1 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +22 -6
- 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/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +16 -3
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -16
- package/src/api/impl/beacon/blocks/index.ts +1 -4
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/validator/index.ts +3 -6
- package/src/chain/GetBlobsTracker.ts +1 -2
- package/src/chain/archiveStore/archiveStore.ts +5 -5
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +6 -8
- package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
- package/src/chain/blocks/importBlock.ts +26 -39
- package/src/chain/blocks/importExecutionPayload.ts +77 -103
- package/src/chain/blocks/index.ts +1 -2
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +6 -5
- package/src/chain/blocks/types.ts +15 -26
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +1 -1
- package/src/chain/chain.ts +25 -62
- package/src/chain/emitter.ts +15 -3
- package/src/chain/errors/attestationError.ts +6 -1
- package/src/chain/errors/executionPayloadBid.ts +6 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
- package/src/chain/forkChoice/index.ts +8 -20
- package/src/chain/interface.ts +2 -2
- package/src/chain/prepareNextSlot.ts +25 -16
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
- package/src/chain/produceBlock/produceBlockBody.ts +41 -20
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +6 -12
- package/src/chain/regen/queued.ts +12 -48
- package/src/chain/regen/regen.ts +8 -36
- package/src/chain/stateCache/datastore/db.ts +10 -33
- package/src/chain/stateCache/datastore/file.ts +5 -6
- package/src/chain/stateCache/datastore/types.ts +2 -3
- package/src/chain/stateCache/fifoBlockStateCache.ts +1 -10
- package/src/chain/stateCache/persistentCheckpointsCache.ts +139 -247
- package/src/chain/stateCache/types.ts +8 -14
- package/src/chain/validation/aggregateAndProof.ts +13 -0
- package/src/chain/validation/attestation.ts +13 -0
- package/src/chain/validation/executionPayloadBid.ts +14 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +22 -12
- package/src/chain/validation/payloadAttestationMessage.ts +5 -3
- package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
- package/src/execution/engine/http.ts +21 -14
- package/src/execution/engine/interface.ts +1 -0
- package/src/execution/engine/mock.ts +8 -1
- package/src/execution/engine/types.ts +41 -0
- package/src/network/network.ts +1 -1
- package/src/network/processor/gossipHandlers.ts +26 -10
- package/src/node/nodejs.ts +4 -2
- package/src/util/sszBytes.ts +21 -3
package/src/chain/chain.ts
CHANGED
|
@@ -2,17 +2,9 @@ import path from "node:path";
|
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
3
|
import {Type} from "@chainsafe/ssz";
|
|
4
4
|
import {BeaconConfig} from "@lodestar/config";
|
|
5
|
-
import {
|
|
6
|
-
CheckpointWithPayloadStatus,
|
|
7
|
-
IForkChoice,
|
|
8
|
-
PayloadStatus,
|
|
9
|
-
ProtoBlock,
|
|
10
|
-
UpdateHeadOpt,
|
|
11
|
-
getCheckpointPayloadStatus,
|
|
12
|
-
} from "@lodestar/fork-choice";
|
|
5
|
+
import {CheckpointWithHex, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
|
|
13
6
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
14
7
|
import {
|
|
15
|
-
BUILDER_INDEX_SELF_BUILD,
|
|
16
8
|
EFFECTIVE_BALANCE_INCREMENT,
|
|
17
9
|
type ForkPostFulu,
|
|
18
10
|
type ForkPostGloas,
|
|
@@ -31,7 +23,6 @@ import {
|
|
|
31
23
|
getEffectiveBalancesFromStateBytes,
|
|
32
24
|
isStatePostAltair,
|
|
33
25
|
isStatePostElectra,
|
|
34
|
-
isStatePostGloas,
|
|
35
26
|
} from "@lodestar/state-transition";
|
|
36
27
|
import {
|
|
37
28
|
BeaconBlock,
|
|
@@ -100,8 +91,8 @@ import {
|
|
|
100
91
|
} from "./opPools/index.js";
|
|
101
92
|
import {IChainOptions} from "./options.js";
|
|
102
93
|
import {PrepareNextSlotScheduler} from "./prepareNextSlot.js";
|
|
103
|
-
import {computeNewStateRoot
|
|
104
|
-
import {AssembledBlockType, BlockType,
|
|
94
|
+
import {computeNewStateRoot} from "./produceBlock/computeNewStateRoot.js";
|
|
95
|
+
import {AssembledBlockType, BlockType, ProduceResult} from "./produceBlock/index.js";
|
|
105
96
|
import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produceBlock/produceBlockBody.js";
|
|
106
97
|
import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js";
|
|
107
98
|
import {ReprocessController} from "./reprocess.js";
|
|
@@ -125,7 +116,7 @@ import {DbCPStateDatastore, checkpointToDatastoreKey} from "./stateCache/datasto
|
|
|
125
116
|
import {FileCPStateDatastore} from "./stateCache/datastore/file.js";
|
|
126
117
|
import {CPStateDatastore} from "./stateCache/datastore/types.js";
|
|
127
118
|
import {FIFOBlockStateCache} from "./stateCache/fifoBlockStateCache.js";
|
|
128
|
-
import {PersistentCheckpointStateCache
|
|
119
|
+
import {PersistentCheckpointStateCache} from "./stateCache/persistentCheckpointsCache.js";
|
|
129
120
|
import {CheckpointStateCache} from "./stateCache/types.js";
|
|
130
121
|
import {ValidatorMonitor} from "./validatorMonitor.js";
|
|
131
122
|
|
|
@@ -390,8 +381,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
390
381
|
const {checkpoint} = anchorState.computeAnchorCheckpoint();
|
|
391
382
|
blockStateCache.add(anchorState);
|
|
392
383
|
blockStateCache.setHeadState(anchorState);
|
|
393
|
-
|
|
394
|
-
checkpointStateCache.add(checkpoint, anchorState, payloadPresent);
|
|
384
|
+
checkpointStateCache.add(checkpoint, anchorState);
|
|
395
385
|
|
|
396
386
|
const forkChoice = initializeForkChoice(
|
|
397
387
|
config,
|
|
@@ -685,16 +675,16 @@ export class BeaconChain implements IBeaconChain {
|
|
|
685
675
|
|
|
686
676
|
// TODO GLOAS: Need to revisit the design of this api. Currently we just retrieve FULL state of the checkpoint for backwards compatibility.
|
|
687
677
|
// because pre-gloas we always store FULL checkpoint state.
|
|
688
|
-
const persistedKey = checkpointToDatastoreKey(checkpoint
|
|
678
|
+
const persistedKey = checkpointToDatastoreKey(checkpoint);
|
|
689
679
|
return this.cpStateDatastore.read(persistedKey);
|
|
690
680
|
}
|
|
691
681
|
|
|
692
682
|
getStateByCheckpoint(
|
|
693
|
-
checkpoint:
|
|
683
|
+
checkpoint: CheckpointWithHex
|
|
694
684
|
): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null {
|
|
695
685
|
// finalized or justified checkpoint states maynot be available with PersistentCheckpointStateCache, use getCheckpointStateOrBytes() api to get Uint8Array
|
|
696
|
-
const
|
|
697
|
-
const cachedStateCtx = this.regen.getCheckpointStateSync(
|
|
686
|
+
const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
|
|
687
|
+
const cachedStateCtx = this.regen.getCheckpointStateSync(checkpointHex);
|
|
698
688
|
if (cachedStateCtx) {
|
|
699
689
|
const block = this.forkChoice.getBlockDefaultStatus(
|
|
700
690
|
ssz.phase0.BeaconBlockHeader.hashTreeRoot(cachedStateCtx.latestBlockHeader)
|
|
@@ -711,10 +701,10 @@ export class BeaconChain implements IBeaconChain {
|
|
|
711
701
|
}
|
|
712
702
|
|
|
713
703
|
async getStateOrBytesByCheckpoint(
|
|
714
|
-
checkpoint:
|
|
704
|
+
checkpoint: CheckpointWithHex
|
|
715
705
|
): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
|
|
716
|
-
const
|
|
717
|
-
const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(
|
|
706
|
+
const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
|
|
707
|
+
const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpointHex);
|
|
718
708
|
if (cachedStateCtx) {
|
|
719
709
|
const block = this.forkChoice.getBlockDefaultStatus(checkpoint.root);
|
|
720
710
|
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
@@ -1070,7 +1060,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1070
1060
|
body,
|
|
1071
1061
|
} as AssembledBlockType<T>;
|
|
1072
1062
|
|
|
1073
|
-
const {newStateRoot, proposerReward
|
|
1063
|
+
const {newStateRoot, proposerReward} = computeNewStateRoot(this.metrics, state, block);
|
|
1074
1064
|
block.stateRoot = newStateRoot;
|
|
1075
1065
|
const blockRoot =
|
|
1076
1066
|
produceResult.type === BlockType.Full
|
|
@@ -1079,26 +1069,9 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1079
1069
|
const blockRootHex = toRootHex(blockRoot);
|
|
1080
1070
|
|
|
1081
1071
|
const fork = this.config.getForkName(slot);
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
throw Error(`Unexpected block type=${produceResult.type} for post-gloas fork=${fork}`);
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
const gloasResult = produceResult as ProduceFullGloas;
|
|
1089
|
-
const envelope: gloas.ExecutionPayloadEnvelope = {
|
|
1090
|
-
payload: gloasResult.executionPayload,
|
|
1091
|
-
executionRequests: gloasResult.executionRequests,
|
|
1092
|
-
builderIndex: BUILDER_INDEX_SELF_BUILD,
|
|
1093
|
-
beaconBlockRoot: blockRoot,
|
|
1094
|
-
slot,
|
|
1095
|
-
stateRoot: ZERO_HASH,
|
|
1096
|
-
};
|
|
1097
|
-
if (!isStatePostGloas(postBlockState)) {
|
|
1098
|
-
throw Error(`Expected gloas+ post-state for execution payload envelope, got fork=${postBlockState.forkName}`);
|
|
1099
|
-
}
|
|
1100
|
-
const payloadEnvelopeStateRoot = computePayloadEnvelopeStateRoot(this.metrics, postBlockState, envelope);
|
|
1101
|
-
gloasResult.payloadEnvelopeStateRoot = payloadEnvelopeStateRoot;
|
|
1072
|
+
// TODO GLOAS: we should retire BlockType post-gloas, may need a new enum for self vs non-self built
|
|
1073
|
+
if (isForkPostGloas(fork) && produceResult.type !== BlockType.Full) {
|
|
1074
|
+
throw Error(`Unexpected block type=${produceResult.type} for post-gloas fork=${fork}`);
|
|
1102
1075
|
}
|
|
1103
1076
|
|
|
1104
1077
|
// Track the produced block for consensus broadcast validations, later validation, etc.
|
|
@@ -1304,7 +1277,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1304
1277
|
* @param blockState state that declares justified checkpoint `checkpoint`
|
|
1305
1278
|
*/
|
|
1306
1279
|
private justifiedBalancesGetter(
|
|
1307
|
-
checkpoint:
|
|
1280
|
+
checkpoint: CheckpointWithHex,
|
|
1308
1281
|
blockState: IBeaconStateView
|
|
1309
1282
|
): EffectiveBalanceIncrements {
|
|
1310
1283
|
this.metrics?.balancesCache.requests.inc();
|
|
@@ -1343,11 +1316,11 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1343
1316
|
* @param blockState state that declares justified checkpoint `checkpoint`
|
|
1344
1317
|
*/
|
|
1345
1318
|
private closestJustifiedBalancesStateToCheckpoint(
|
|
1346
|
-
checkpoint:
|
|
1319
|
+
checkpoint: CheckpointWithHex,
|
|
1347
1320
|
blockState: IBeaconStateView
|
|
1348
1321
|
): {state: IBeaconStateView; stateId: string; shouldWarn: boolean} {
|
|
1349
|
-
const
|
|
1350
|
-
const state = this.regen.getCheckpointStateSync(
|
|
1322
|
+
const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
|
|
1323
|
+
const state = this.regen.getCheckpointStateSync(checkpointHex);
|
|
1351
1324
|
if (state) {
|
|
1352
1325
|
return {state, stateId: "checkpoint_state", shouldWarn: false};
|
|
1353
1326
|
}
|
|
@@ -1358,10 +1331,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1358
1331
|
}
|
|
1359
1332
|
|
|
1360
1333
|
// Find a state in the same branch of checkpoint at same epoch. Balances should exactly the same
|
|
1361
|
-
for (const descendantBlock of this.forkChoice.
|
|
1362
|
-
checkpoint.rootHex,
|
|
1363
|
-
checkpoint.payloadStatus
|
|
1364
|
-
)) {
|
|
1334
|
+
for (const descendantBlock of this.forkChoice.forwardIterateDescendantsDefaultStatus(checkpoint.rootHex)) {
|
|
1365
1335
|
if (computeEpochAtSlot(descendantBlock.slot) === checkpoint.epoch) {
|
|
1366
1336
|
const descendantBlockState = this.regen.getStateSync(descendantBlock.stateRoot);
|
|
1367
1337
|
if (descendantBlockState) {
|
|
@@ -1377,10 +1347,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1377
1347
|
|
|
1378
1348
|
// Find a state in the same branch of checkpoint at a latter epoch. Balances are not the same, but should be close
|
|
1379
1349
|
// Note: must call .forwardIterateDescendants() again since nodes are not sorted
|
|
1380
|
-
for (const descendantBlock of this.forkChoice.
|
|
1381
|
-
checkpoint.rootHex,
|
|
1382
|
-
checkpoint.payloadStatus
|
|
1383
|
-
)) {
|
|
1350
|
+
for (const descendantBlock of this.forkChoice.forwardIterateDescendantsDefaultStatus(checkpoint.rootHex)) {
|
|
1384
1351
|
if (computeEpochAtSlot(descendantBlock.slot) > checkpoint.epoch) {
|
|
1385
1352
|
const descendantBlockState = this.regen.getStateSync(descendantBlock.stateRoot);
|
|
1386
1353
|
if (descendantBlockState) {
|
|
@@ -1471,10 +1438,6 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1471
1438
|
private onClockEpoch(epoch: Epoch): void {
|
|
1472
1439
|
this.metrics?.clockEpoch.set(epoch);
|
|
1473
1440
|
|
|
1474
|
-
if (epoch === this.config.GLOAS_FORK_EPOCH) {
|
|
1475
|
-
this.regen.upgradeForGloas(epoch);
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
1441
|
this.seenAttesters.prune(epoch);
|
|
1479
1442
|
this.seenAggregators.prune(epoch);
|
|
1480
1443
|
this.seenPayloadAttesters.prune(epoch);
|
|
@@ -1488,7 +1451,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1488
1451
|
this.seenContributionAndProof.prune(head.slot);
|
|
1489
1452
|
}
|
|
1490
1453
|
|
|
1491
|
-
private onForkChoiceJustified(this: BeaconChain, cp:
|
|
1454
|
+
private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithHex): void {
|
|
1492
1455
|
this.logger.verbose("Fork choice justified", {epoch: cp.epoch, root: cp.rootHex});
|
|
1493
1456
|
}
|
|
1494
1457
|
|
|
@@ -1499,7 +1462,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1499
1462
|
});
|
|
1500
1463
|
}
|
|
1501
1464
|
|
|
1502
|
-
private async onForkChoiceFinalized(this: BeaconChain, cp:
|
|
1465
|
+
private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithHex): Promise<void> {
|
|
1503
1466
|
this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
|
|
1504
1467
|
const finalizedSlot = computeStartSlotAtEpoch(cp.epoch);
|
|
1505
1468
|
this.seenBlockProposers.prune(finalizedSlot);
|
|
@@ -1540,7 +1503,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1540
1503
|
}
|
|
1541
1504
|
}
|
|
1542
1505
|
|
|
1543
|
-
private async updateValidatorsCustodyRequirement(finalizedCheckpoint:
|
|
1506
|
+
private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithHex): Promise<void> {
|
|
1544
1507
|
if (this.custodyConfig.targetCustodyGroupCount === this.config.NUMBER_OF_CUSTODY_GROUPS) {
|
|
1545
1508
|
// Custody requirements can only be increased, we can disable dynamic custody updates
|
|
1546
1509
|
// if the node already maintains custody of all custody groups in case it is configured
|
package/src/chain/emitter.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {EventEmitter} from "node:events";
|
|
2
2
|
import {StrictEventEmitter} from "strict-event-emitter-types";
|
|
3
3
|
import {routes} from "@lodestar/api";
|
|
4
|
-
import {
|
|
4
|
+
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
5
5
|
import {IBeaconStateView} from "@lodestar/state-transition";
|
|
6
6
|
import {DataColumnSidecar, RootHex, deneb, phase0} from "@lodestar/types";
|
|
7
7
|
import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
|
|
8
8
|
import {PeerIdStr} from "../util/peerId.js";
|
|
9
9
|
import {BlockInputSource, IBlockInput} from "./blocks/blockInput/types.js";
|
|
10
|
+
import {PayloadEnvelopeInput} from "./blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Important chain events that occur during normal chain operation.
|
|
@@ -76,6 +77,11 @@ export enum ChainEvent {
|
|
|
76
77
|
* cut-off window passes for waiting on gossip
|
|
77
78
|
*/
|
|
78
79
|
incompleteBlockInput = "incompleteBlockInput",
|
|
80
|
+
/**
|
|
81
|
+
* Post-gloas: trigger BlockInputSync for payload envelopes whose envelope and/or sampled columns are partially
|
|
82
|
+
* received via gossip but are not complete by time the cut-off window passes for waiting on gossip
|
|
83
|
+
*/
|
|
84
|
+
incompletePayloadEnvelope = "incompletePayloadEnvelope",
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
export type HeadEventData = routes.events.EventData[routes.events.EventType.head];
|
|
@@ -93,14 +99,19 @@ export type ChainEventData = {
|
|
|
93
99
|
};
|
|
94
100
|
[ChainEvent.unknownBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource};
|
|
95
101
|
[ChainEvent.incompleteBlockInput]: {blockInput: IBlockInput; peer: PeerIdStr; source: BlockInputSource};
|
|
102
|
+
[ChainEvent.incompletePayloadEnvelope]: {
|
|
103
|
+
payloadInput: PayloadEnvelopeInput;
|
|
104
|
+
peer: PeerIdStr;
|
|
105
|
+
source: BlockInputSource;
|
|
106
|
+
};
|
|
96
107
|
[ChainEvent.unknownEnvelopeBlockRoot]: {rootHex: RootHex; peer?: PeerIdStr; source: BlockInputSource};
|
|
97
108
|
};
|
|
98
109
|
|
|
99
110
|
export type IChainEvents = ApiEvents & {
|
|
100
111
|
[ChainEvent.checkpoint]: (checkpoint: phase0.Checkpoint, state: IBeaconStateView) => void;
|
|
101
112
|
|
|
102
|
-
[ChainEvent.forkChoiceJustified]: (checkpoint:
|
|
103
|
-
[ChainEvent.forkChoiceFinalized]: (checkpoint:
|
|
113
|
+
[ChainEvent.forkChoiceJustified]: (checkpoint: CheckpointWithHex) => void;
|
|
114
|
+
[ChainEvent.forkChoiceFinalized]: (checkpoint: CheckpointWithHex) => void;
|
|
104
115
|
|
|
105
116
|
[ChainEvent.updateTargetCustodyGroupCount]: (targetGroupCount: number) => void;
|
|
106
117
|
|
|
@@ -116,6 +127,7 @@ export type IChainEvents = ApiEvents & {
|
|
|
116
127
|
[ChainEvent.envelopeUnknownBlock]: (data: ChainEventData[ChainEvent.envelopeUnknownBlock]) => void;
|
|
117
128
|
[ChainEvent.unknownBlockRoot]: (data: ChainEventData[ChainEvent.unknownBlockRoot]) => void;
|
|
118
129
|
[ChainEvent.incompleteBlockInput]: (data: ChainEventData[ChainEvent.incompleteBlockInput]) => void;
|
|
130
|
+
[ChainEvent.incompletePayloadEnvelope]: (data: ChainEventData[ChainEvent.incompletePayloadEnvelope]) => void;
|
|
119
131
|
[ChainEvent.unknownEnvelopeBlockRoot]: (data: ChainEventData[ChainEvent.unknownEnvelopeBlockRoot]) => void;
|
|
120
132
|
};
|
|
121
133
|
|
|
@@ -147,6 +147,10 @@ export enum AttestationErrorCode {
|
|
|
147
147
|
* Gloas: Current slot attestation is marking payload as present
|
|
148
148
|
*/
|
|
149
149
|
PREMATURELY_INDICATED_PAYLOAD_PRESENT = "ATTESTATION_ERROR_PREMATURELY_INDICATED_PAYLOAD_PRESENT",
|
|
150
|
+
/**
|
|
151
|
+
* Gloas: index-1 attestation but the execution payload has not been seen yet
|
|
152
|
+
*/
|
|
153
|
+
EXECUTION_PAYLOAD_NOT_SEEN = "ATTESTATION_ERROR_EXECUTION_PAYLOAD_NOT_SEEN",
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
export type AttestationErrorType =
|
|
@@ -185,7 +189,8 @@ export type AttestationErrorType =
|
|
|
185
189
|
| {code: AttestationErrorCode.NON_ZERO_ATTESTATION_DATA_INDEX}
|
|
186
190
|
| {code: AttestationErrorCode.ATTESTER_NOT_IN_COMMITTEE}
|
|
187
191
|
| {code: AttestationErrorCode.INVALID_PAYLOAD_STATUS_VALUE; attDataIndex: number}
|
|
188
|
-
| {code: AttestationErrorCode.PREMATURELY_INDICATED_PAYLOAD_PRESENT}
|
|
192
|
+
| {code: AttestationErrorCode.PREMATURELY_INDICATED_PAYLOAD_PRESENT}
|
|
193
|
+
| {code: AttestationErrorCode.EXECUTION_PAYLOAD_NOT_SEEN; beaconBlockRoot: RootHex};
|
|
189
194
|
|
|
190
195
|
export class AttestationError extends GossipActionError<AttestationErrorType> {
|
|
191
196
|
getMetadata(): Record<string, string | number | null> {
|
|
@@ -7,6 +7,7 @@ export enum ExecutionPayloadBidErrorCode {
|
|
|
7
7
|
BID_ALREADY_KNOWN = "EXECUTION_PAYLOAD_BID_ERROR_BID_ALREADY_KNOWN",
|
|
8
8
|
BID_TOO_LOW = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_LOW",
|
|
9
9
|
BID_TOO_HIGH = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_HIGH",
|
|
10
|
+
TOO_MANY_KZG_COMMITMENTS = "EXECUTION_PAYLOAD_BID_ERROR_TOO_MANY_KZG_COMMITMENTS",
|
|
10
11
|
UNKNOWN_BLOCK_ROOT = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_BLOCK_ROOT",
|
|
11
12
|
INVALID_SLOT = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SLOT",
|
|
12
13
|
INVALID_SIGNATURE = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SIGNATURE",
|
|
@@ -28,6 +29,11 @@ export type ExecutionPayloadBidErrorType =
|
|
|
28
29
|
}
|
|
29
30
|
| {code: ExecutionPayloadBidErrorCode.BID_TOO_LOW; bidValue: number; currentHighestBid: number}
|
|
30
31
|
| {code: ExecutionPayloadBidErrorCode.BID_TOO_HIGH; bidValue: number; builderBalance: number}
|
|
32
|
+
| {
|
|
33
|
+
code: ExecutionPayloadBidErrorCode.TOO_MANY_KZG_COMMITMENTS;
|
|
34
|
+
blobKzgCommitmentsLen: number;
|
|
35
|
+
commitmentLimit: number;
|
|
36
|
+
}
|
|
31
37
|
| {code: ExecutionPayloadBidErrorCode.UNKNOWN_BLOCK_ROOT; parentBlockRoot: RootHex}
|
|
32
38
|
| {code: ExecutionPayloadBidErrorCode.INVALID_SLOT; builderIndex: BuilderIndex; slot: Slot}
|
|
33
39
|
| {code: ExecutionPayloadBidErrorCode.INVALID_SIGNATURE; builderIndex: BuilderIndex; slot: Slot};
|
|
@@ -11,6 +11,7 @@ export enum ExecutionPayloadEnvelopeErrorCode {
|
|
|
11
11
|
SLOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_SLOT_MISMATCH",
|
|
12
12
|
BUILDER_INDEX_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BUILDER_INDEX_MISMATCH",
|
|
13
13
|
BLOCK_HASH_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_HASH_MISMATCH",
|
|
14
|
+
EXECUTION_REQUESTS_ROOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_EXECUTION_REQUESTS_ROOT_MISMATCH",
|
|
14
15
|
INVALID_SIGNATURE = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_SIGNATURE",
|
|
15
16
|
PAYLOAD_ENVELOPE_INPUT_MISSING = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_PAYLOAD_ENVELOPE_INPUT_MISSING",
|
|
16
17
|
}
|
|
@@ -36,6 +37,11 @@ export type ExecutionPayloadEnvelopeErrorType =
|
|
|
36
37
|
envelopeBlockHash: RootHex;
|
|
37
38
|
bidBlockHash: RootHex | null;
|
|
38
39
|
}
|
|
40
|
+
| {
|
|
41
|
+
code: ExecutionPayloadEnvelopeErrorCode.EXECUTION_REQUESTS_ROOT_MISMATCH;
|
|
42
|
+
envelopeRequestsRoot: RootHex;
|
|
43
|
+
bidRequestsRoot: RootHex;
|
|
44
|
+
}
|
|
39
45
|
| {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
|
|
40
46
|
| {code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING; blockRoot: RootHex};
|
|
41
47
|
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
ProtoArray,
|
|
9
9
|
ProtoBlock,
|
|
10
10
|
ForkChoiceOpts as RawForkChoiceOpts,
|
|
11
|
-
getCheckpointPayloadStatus,
|
|
12
11
|
} from "@lodestar/fork-choice";
|
|
13
12
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
14
13
|
import {
|
|
@@ -104,12 +103,6 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
104
103
|
|
|
105
104
|
const isForkPostGloas = computeEpochAtSlot(state.slot) >= config.GLOAS_FORK_EPOCH;
|
|
106
105
|
|
|
107
|
-
// Determine justified checkpoint payload status
|
|
108
|
-
const justifiedPayloadStatus = getCheckpointPayloadStatus(config, state, justifiedCheckpoint.epoch);
|
|
109
|
-
|
|
110
|
-
// Determine finalized checkpoint payload status
|
|
111
|
-
const finalizedPayloadStatus = getCheckpointPayloadStatus(config, state, finalizedCheckpoint.epoch);
|
|
112
|
-
|
|
113
106
|
return new forkchoiceConstructor(
|
|
114
107
|
config,
|
|
115
108
|
|
|
@@ -119,8 +112,6 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
119
112
|
finalizedCheckpoint,
|
|
120
113
|
justifiedBalances,
|
|
121
114
|
justifiedBalancesGetter,
|
|
122
|
-
justifiedPayloadStatus,
|
|
123
|
-
finalizedPayloadStatus,
|
|
124
115
|
{
|
|
125
116
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
126
117
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
@@ -146,7 +137,9 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
146
137
|
|
|
147
138
|
...(isStatePostBellatrix(state) && state.isExecutionStateType && state.isMergeTransitionComplete
|
|
148
139
|
? {
|
|
149
|
-
executionPayloadBlockHash:
|
|
140
|
+
executionPayloadBlockHash: isStatePostGloas(state)
|
|
141
|
+
? toRootHex(state.latestBlockHash)
|
|
142
|
+
: toRootHex(state.latestExecutionPayloadHeader.blockHash),
|
|
150
143
|
// TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
|
|
151
144
|
// latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
|
|
152
145
|
executionPayloadNumber: isStatePostGloas(state) ? 0 : state.payloadBlockNumber,
|
|
@@ -155,7 +148,7 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
155
148
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
156
149
|
|
|
157
150
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
158
|
-
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
151
|
+
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
159
152
|
parentBlockHash: isStatePostGloas(state) ? toRootHex(state.latestBlockHash) : null,
|
|
160
153
|
},
|
|
161
154
|
currentSlot
|
|
@@ -202,19 +195,12 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
202
195
|
|
|
203
196
|
const isForkPostGloas = computeEpochAtSlot(unfinalizedState.slot) >= config.GLOAS_FORK_EPOCH;
|
|
204
197
|
|
|
205
|
-
// For unfinalized state, use getCheckpointPayloadStatus to determine the correct status.
|
|
206
|
-
// It checks state.execution_payload_availability to determine EMPTY vs FULL.
|
|
207
|
-
const justifiedPayloadStatus = getCheckpointPayloadStatus(config, unfinalizedState, justifiedCheckpoint.epoch);
|
|
208
|
-
const finalizedPayloadStatus = getCheckpointPayloadStatus(config, unfinalizedState, finalizedCheckpoint.epoch);
|
|
209
|
-
|
|
210
198
|
const store = new ForkChoiceStore(
|
|
211
199
|
currentSlot,
|
|
212
200
|
justifiedCheckpoint,
|
|
213
201
|
finalizedCheckpoint,
|
|
214
202
|
justifiedBalances,
|
|
215
203
|
justifiedBalancesGetter,
|
|
216
|
-
justifiedPayloadStatus,
|
|
217
|
-
finalizedPayloadStatus,
|
|
218
204
|
{
|
|
219
205
|
onJustified: (cp) => emitter.emit(ChainEvent.forkChoiceJustified, cp),
|
|
220
206
|
onFinalized: (cp) => emitter.emit(ChainEvent.forkChoiceFinalized, cp),
|
|
@@ -243,7 +229,9 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
243
229
|
unfinalizedState.isExecutionStateType &&
|
|
244
230
|
unfinalizedState.isMergeTransitionComplete
|
|
245
231
|
? {
|
|
246
|
-
executionPayloadBlockHash:
|
|
232
|
+
executionPayloadBlockHash: isStatePostGloas(unfinalizedState)
|
|
233
|
+
? toRootHex(unfinalizedState.latestBlockHash)
|
|
234
|
+
: toRootHex(unfinalizedState.latestExecutionPayloadHeader.blockHash),
|
|
247
235
|
// TODO GLOAS: executionPayloadNumber is not tracked in BeaconState post-gloas (EIP-7732 removed
|
|
248
236
|
// latestExecutionPayloadHeader). Using 0 as unavailable fallback until a solution is found.
|
|
249
237
|
executionPayloadNumber: isStatePostGloas(unfinalizedState) ? 0 : unfinalizedState.payloadBlockNumber,
|
|
@@ -252,7 +240,7 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
252
240
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
253
241
|
|
|
254
242
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
255
|
-
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
243
|
+
payloadStatus: isForkPostGloas ? PayloadStatus.PENDING : PayloadStatus.FULL,
|
|
256
244
|
parentBlockHash: isStatePostGloas(unfinalizedState) ? toRootHex(unfinalizedState.latestBlockHash) : null,
|
|
257
245
|
};
|
|
258
246
|
|
package/src/chain/interface.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Type} from "@chainsafe/ssz";
|
|
2
2
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
|
-
import {CheckpointWithHex,
|
|
3
|
+
import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
4
4
|
import {EpochShuffling, IBeaconStateView, PubkeyCache} from "@lodestar/state-transition";
|
|
5
5
|
import {
|
|
6
6
|
BeaconBlock,
|
|
@@ -195,7 +195,7 @@ export interface IBeaconChain {
|
|
|
195
195
|
): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null;
|
|
196
196
|
/** Return state bytes by checkpoint */
|
|
197
197
|
getStateOrBytesByCheckpoint(
|
|
198
|
-
checkpoint:
|
|
198
|
+
checkpoint: CheckpointWithHex
|
|
199
199
|
): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
200
200
|
|
|
201
201
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {
|
|
3
|
+
import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
4
4
|
import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix} from "@lodestar/params";
|
|
5
5
|
import {
|
|
6
6
|
IBeaconStateView,
|
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
computeEpochAtSlot,
|
|
9
9
|
computeTimeAtSlot,
|
|
10
10
|
isStatePostBellatrix,
|
|
11
|
+
isStatePostGloas,
|
|
11
12
|
} from "@lodestar/state-transition";
|
|
12
|
-
import {Slot} from "@lodestar/types";
|
|
13
|
+
import {Bytes32, Slot} from "@lodestar/types";
|
|
13
14
|
import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
|
|
14
15
|
import {GENESIS_SLOT, ZERO_HASH_HEX} from "../constants/constants.js";
|
|
15
16
|
import {BuilderStatus} from "../execution/builder/http.js";
|
|
@@ -81,6 +82,8 @@ export class PrepareNextSlotScheduler {
|
|
|
81
82
|
// calling updateHead() here before we produce a block to reduce reorg possibility
|
|
82
83
|
const headBlock = this.chain.recomputeForkChoiceHead(ForkchoiceCaller.prepareNextSlot);
|
|
83
84
|
const {slot: headSlot, blockRoot: headRoot} = headBlock;
|
|
85
|
+
// may be updated below if we predict a proposer-boost-reorg
|
|
86
|
+
let updatedHeadRoot = headRoot;
|
|
84
87
|
|
|
85
88
|
// PS: previously this was comparing slots, but that gave no leway on the skipped
|
|
86
89
|
// slots on epoch bounday. Making it more fluid.
|
|
@@ -123,7 +126,6 @@ export class PrepareNextSlotScheduler {
|
|
|
123
126
|
const proposerIndex = prepareState.getBeaconProposer(prepareSlot);
|
|
124
127
|
const feeRecipient = this.chain.beaconProposerCache.get(proposerIndex);
|
|
125
128
|
let updatedPrepareState = prepareState;
|
|
126
|
-
let updatedHeadRoot = headRoot;
|
|
127
129
|
|
|
128
130
|
if (feeRecipient) {
|
|
129
131
|
// If we are proposing next slot, we need to predict if we can proposer-boost-reorg or not
|
|
@@ -156,25 +158,39 @@ export class PrepareNextSlotScheduler {
|
|
|
156
158
|
this.logger.error("Builder disabled as the check status api failed", {prepareSlot}, e as Error);
|
|
157
159
|
});
|
|
158
160
|
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!isStatePostBellatrix(updatedPrepareState)) {
|
|
164
|
+
throw new Error("Expected Bellatrix state for payload attributes");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let parentBlockHash: Bytes32;
|
|
168
|
+
if (isStatePostGloas(updatedPrepareState)) {
|
|
169
|
+
parentBlockHash = this.chain.forkChoice.shouldExtendPayload(updatedHeadRoot)
|
|
170
|
+
? updatedPrepareState.latestExecutionPayloadBid.blockHash
|
|
171
|
+
: updatedPrepareState.latestExecutionPayloadBid.parentBlockHash;
|
|
172
|
+
} else {
|
|
173
|
+
parentBlockHash = updatedPrepareState.latestExecutionPayloadHeader.blockHash;
|
|
174
|
+
}
|
|
159
175
|
|
|
176
|
+
if (feeRecipient) {
|
|
160
177
|
const preparationTime =
|
|
161
178
|
computeTimeAtSlot(this.config, prepareSlot, this.chain.genesisTime) - Date.now() / 1000;
|
|
162
179
|
this.metrics?.blockPayload.payloadAdvancePrepTime.observe(preparationTime);
|
|
163
|
-
if (!isStatePostBellatrix(updatedPrepareState)) {
|
|
164
|
-
throw new Error("Expected Bellatrix state for payload preparation");
|
|
165
|
-
}
|
|
166
180
|
|
|
167
181
|
const safeBlockHash = getSafeExecutionBlockHash(this.chain.forkChoice);
|
|
168
182
|
const finalizedBlockHash =
|
|
169
183
|
this.chain.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
184
|
+
|
|
170
185
|
// awaiting here instead of throwing an async call because there is no other task
|
|
171
|
-
// left for scheduler and this gives nice
|
|
186
|
+
// left for scheduler and this gives nice semantics to catch and log errors in the
|
|
172
187
|
// try/catch wrapper here.
|
|
173
188
|
await prepareExecutionPayload(
|
|
174
189
|
this.chain,
|
|
175
190
|
this.logger,
|
|
176
191
|
fork as ForkPostBellatrix, // State is of execution type
|
|
177
192
|
fromHex(updatedHeadRoot),
|
|
193
|
+
parentBlockHash,
|
|
178
194
|
safeBlockHash,
|
|
179
195
|
finalizedBlockHash,
|
|
180
196
|
updatedPrepareState,
|
|
@@ -187,10 +203,6 @@ export class PrepareNextSlotScheduler {
|
|
|
187
203
|
});
|
|
188
204
|
}
|
|
189
205
|
|
|
190
|
-
if (!isStatePostBellatrix(updatedPrepareState)) {
|
|
191
|
-
throw new Error("Expected Bellatrix state for payload attributes");
|
|
192
|
-
}
|
|
193
|
-
|
|
194
206
|
this.computeStateHashTreeRoot(updatedPrepareState, isEpochTransition);
|
|
195
207
|
|
|
196
208
|
// If emitPayloadAttributes is true emit a SSE payloadAttributes event
|
|
@@ -202,6 +214,7 @@ export class PrepareNextSlotScheduler {
|
|
|
202
214
|
prepareState: updatedPrepareState,
|
|
203
215
|
prepareSlot,
|
|
204
216
|
parentBlockRoot: fromHex(headRoot),
|
|
217
|
+
parentBlockHash,
|
|
205
218
|
// The likely consumers of this API are builders and will anyway ignore the
|
|
206
219
|
// feeRecipient, so just pass zero hash for now till a real use case arises
|
|
207
220
|
feeRecipient: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
@@ -217,11 +230,7 @@ export class PrepareNextSlotScheduler {
|
|
|
217
230
|
// + if next slot is a skipped slot, it'd help getting target checkpoint state faster to validate attestations
|
|
218
231
|
if (isEpochTransition) {
|
|
219
232
|
this.metrics?.precomputeNextEpochTransition.count.inc({result: "success"}, 1);
|
|
220
|
-
|
|
221
|
-
// Pre-Gloas: payloadStatus is always FULL → payloadPresent = true
|
|
222
|
-
// Post-Gloas: FULL → true, EMPTY → false, PENDING → false (conservative, treat as block state)
|
|
223
|
-
const payloadPresent = headBlock.payloadStatus === PayloadStatus.FULL;
|
|
224
|
-
const previousHits = this.chain.regen.updatePreComputedCheckpoint(headRoot, nextEpoch, payloadPresent);
|
|
233
|
+
const previousHits = this.chain.regen.updatePreComputedCheckpoint(headRoot, nextEpoch);
|
|
225
234
|
if (previousHits === 0) {
|
|
226
235
|
this.metrics?.precomputeNextEpochTransition.waste.inc();
|
|
227
236
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DataAvailabilityStatus,
|
|
3
3
|
ExecutionPayloadStatus,
|
|
4
|
-
G2_POINT_AT_INFINITY,
|
|
5
4
|
IBeaconStateView,
|
|
6
|
-
IBeaconStateViewGloas,
|
|
7
5
|
StateHashTreeRootSource,
|
|
8
6
|
} from "@lodestar/state-transition";
|
|
9
|
-
import {BeaconBlock, BlindedBeaconBlock, Gwei, Root
|
|
7
|
+
import {BeaconBlock, BlindedBeaconBlock, Gwei, Root} from "@lodestar/types";
|
|
10
8
|
import {ZERO_HASH} from "../../constants/index.js";
|
|
11
9
|
import {Metrics} from "../../metrics/index.js";
|
|
12
10
|
|
|
@@ -19,11 +17,11 @@ export function computeNewStateRoot(
|
|
|
19
17
|
metrics: Metrics | null,
|
|
20
18
|
state: IBeaconStateView,
|
|
21
19
|
block: BeaconBlock | BlindedBeaconBlock
|
|
22
|
-
): {newStateRoot: Root; proposerReward: Gwei;
|
|
20
|
+
): {newStateRoot: Root; proposerReward: Gwei; postState: IBeaconStateView} {
|
|
23
21
|
// Set signature to zero to re-use stateTransition() function which requires the SignedBeaconBlock type
|
|
24
22
|
const blockEmptySig = {message: block, signature: ZERO_HASH};
|
|
25
23
|
|
|
26
|
-
const
|
|
24
|
+
const postState = state.stateTransition(
|
|
27
25
|
blockEmptySig,
|
|
28
26
|
{
|
|
29
27
|
// ExecutionPayloadStatus.valid: Assume payload valid, it has been produced by a trusted EL
|
|
@@ -42,49 +40,14 @@ export function computeNewStateRoot(
|
|
|
42
40
|
{metrics}
|
|
43
41
|
);
|
|
44
42
|
|
|
45
|
-
const {attestations, syncAggregate, slashing} =
|
|
43
|
+
const {attestations, syncAggregate, slashing} = postState.proposerRewards;
|
|
46
44
|
const proposerReward = BigInt(attestations + syncAggregate + slashing);
|
|
47
45
|
|
|
48
46
|
const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
|
|
49
47
|
source: StateHashTreeRootSource.computeNewStateRoot,
|
|
50
48
|
});
|
|
51
|
-
const newStateRoot =
|
|
49
|
+
const newStateRoot = postState.hashTreeRoot();
|
|
52
50
|
hashTreeRootTimer?.();
|
|
53
51
|
|
|
54
|
-
return {newStateRoot, proposerReward,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Compute the state root after processing an execution payload envelope.
|
|
59
|
-
* Similar to `computeNewStateRoot` but for payload envelope processing.
|
|
60
|
-
*
|
|
61
|
-
*/
|
|
62
|
-
export function computePayloadEnvelopeStateRoot(
|
|
63
|
-
metrics: Metrics | null,
|
|
64
|
-
postBlockState: IBeaconStateViewGloas,
|
|
65
|
-
envelope: gloas.ExecutionPayloadEnvelope
|
|
66
|
-
): Root {
|
|
67
|
-
const signedEnvelope: gloas.SignedExecutionPayloadEnvelope = {
|
|
68
|
-
message: envelope,
|
|
69
|
-
signature: G2_POINT_AT_INFINITY,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const processEnvelopeTimer = metrics?.blockPayload.executionPayloadEnvelopeProcessingTime.startTimer();
|
|
73
|
-
const postPayloadState = postBlockState.processExecutionPayloadEnvelope(signedEnvelope, {
|
|
74
|
-
// Signature is zero-ed (G2_POINT_AT_INFINITY), skip verification
|
|
75
|
-
verifySignature: false,
|
|
76
|
-
// State root is being computed here, the envelope doesn't have it yet
|
|
77
|
-
verifyStateRoot: false,
|
|
78
|
-
// Preserve cache in source state, since the resulting state is not added to the state cache
|
|
79
|
-
dontTransferCache: true,
|
|
80
|
-
});
|
|
81
|
-
processEnvelopeTimer?.();
|
|
82
|
-
|
|
83
|
-
const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
|
|
84
|
-
source: StateHashTreeRootSource.computePayloadEnvelopeStateRoot,
|
|
85
|
-
});
|
|
86
|
-
const stateRoot = postPayloadState.hashTreeRoot();
|
|
87
|
-
hashTreeRootTimer?.();
|
|
88
|
-
|
|
89
|
-
return stateRoot;
|
|
52
|
+
return {newStateRoot, proposerReward, postState};
|
|
90
53
|
}
|