@lodestar/beacon-node 1.41.0-dev.279c11da24 → 1.41.0-dev.49f680d9f0
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 +121 -3
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +5 -2
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lightclient/index.d.ts.map +1 -1
- package/lib/api/impl/lightclient/index.js +19 -2
- package/lib/api/impl/lightclient/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +101 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +9 -0
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts +7 -0
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts.map +1 -0
- package/lib/chain/archiveStore/utils/archivePayloads.js +10 -0
- package/lib/chain/archiveStore/utils/archivePayloads.js.map +1 -0
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +0 -2
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +2 -1
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +3 -0
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +2 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +24 -6
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +2 -2
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +1 -1
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/prepareNextSlot.js +3 -3
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +10 -2
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +24 -2
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +22 -7
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +110 -10
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts +2 -2
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/db/beacon.d.ts +3 -1
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +5 -1
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/buckets.d.ts +3 -1
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +2 -0
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/interface.d.ts +3 -1
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.d.ts +5 -3
- package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.js +14 -1
- package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts +5 -3
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +14 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/db/repositories/executionPayloadEnvelope.d.ts +19 -0
- package/lib/db/repositories/executionPayloadEnvelope.d.ts.map +1 -0
- package/lib/db/repositories/executionPayloadEnvelope.js +22 -0
- package/lib/db/repositories/executionPayloadEnvelope.js.map +1 -0
- package/lib/db/repositories/executionPayloadEnvelopeArchive.d.ts +18 -0
- package/lib/db/repositories/executionPayloadEnvelopeArchive.d.ts.map +1 -0
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js +28 -0
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -0
- package/lib/db/repositories/index.d.ts +2 -0
- package/lib/db/repositories/index.d.ts.map +1 -1
- package/lib/db/repositories/index.js +2 -0
- package/lib/db/repositories/index.js.map +1 -1
- package/lib/metrics/metrics/beacon.d.ts +1 -0
- package/lib/metrics/metrics/beacon.d.ts.map +1 -1
- package/lib/metrics/metrics/beacon.js +5 -0
- package/lib/metrics/metrics/beacon.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +5 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +9 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +3 -3
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/topic.d.ts +113 -63
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +2 -2
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/interface.d.ts +3 -2
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +3 -2
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +10 -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 +5 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/reqresp/handlers/lightClientUpdatesByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/lightClientUpdatesByRange.js +7 -1
- package/lib/network/reqresp/handlers/lightClientUpdatesByRange.js.map +1 -1
- package/lib/util/blobs.d.ts +2 -2
- package/lib/util/blobs.d.ts.map +1 -1
- package/lib/util/blobs.js.map +1 -1
- package/lib/util/dataColumns.d.ts +11 -3
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +27 -0
- package/lib/util/dataColumns.js.map +1 -1
- package/lib/util/multifork.d.ts +8 -0
- package/lib/util/multifork.d.ts.map +1 -1
- package/lib/util/multifork.js +37 -0
- package/lib/util/multifork.js.map +1 -1
- package/lib/util/serializedCache.d.ts +5 -0
- package/lib/util/serializedCache.d.ts.map +1 -1
- package/lib/util/serializedCache.js +5 -0
- package/lib/util/serializedCache.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +145 -2
- package/src/api/impl/debug/index.ts +8 -5
- package/src/api/impl/lightclient/index.ts +19 -2
- package/src/api/impl/validator/index.ts +124 -1
- package/src/chain/archiveStore/archiveStore.ts +10 -0
- package/src/chain/archiveStore/utils/archivePayloads.ts +15 -0
- package/src/chain/blocks/importBlock.ts +0 -3
- package/src/chain/blocks/index.ts +2 -1
- package/src/chain/blocks/writeBlockInputToDb.ts +3 -0
- package/src/chain/chain.ts +41 -11
- package/src/chain/emitter.ts +2 -2
- package/src/chain/interface.ts +2 -2
- package/src/chain/lightClient/index.ts +4 -1
- package/src/chain/options.ts +1 -0
- package/src/chain/prepareNextSlot.ts +5 -5
- package/src/chain/produceBlock/computeNewStateRoot.ts +35 -3
- package/src/chain/produceBlock/produceBlockBody.ts +163 -13
- package/src/chain/validation/dataColumnSidecar.ts +2 -5
- package/src/db/beacon.ts +8 -0
- package/src/db/buckets.ts +3 -0
- package/src/db/interface.ts +5 -0
- package/src/db/repositories/dataColumnSidecar.ts +18 -3
- package/src/db/repositories/dataColumnSidecarArchive.ts +18 -3
- package/src/db/repositories/executionPayloadEnvelope.ts +26 -0
- package/src/db/repositories/executionPayloadEnvelopeArchive.ts +32 -0
- package/src/db/repositories/index.ts +2 -0
- package/src/metrics/metrics/beacon.ts +5 -0
- package/src/metrics/metrics/lodestar.ts +9 -0
- package/src/network/gossip/interface.ts +3 -3
- package/src/network/gossip/topic.ts +2 -1
- package/src/network/interface.ts +4 -1
- package/src/network/network.ts +21 -3
- package/src/network/processor/gossipHandlers.ts +7 -1
- package/src/network/reqresp/handlers/lightClientUpdatesByRange.ts +6 -1
- package/src/util/blobs.ts +3 -3
- package/src/util/dataColumns.ts +37 -1
- package/src/util/multifork.ts +45 -0
- package/src/util/serializedCache.ts +5 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
2
2
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
3
|
+
import {ForkSeq} from "@lodestar/params";
|
|
3
4
|
import {Checkpoint} from "@lodestar/types/phase0";
|
|
4
5
|
import {callFnWhenAwait} from "@lodestar/utils";
|
|
5
6
|
import {IBeaconDb} from "../../db/index.js";
|
|
@@ -13,6 +14,7 @@ import {HistoricalStateRegen} from "./historicalState/historicalStateRegen.js";
|
|
|
13
14
|
import {ArchiveMode, ArchiveStoreOpts, StateArchiveStrategy} from "./interface.js";
|
|
14
15
|
import {FrequencyStateArchiveStrategy} from "./strategies/frequencyStateArchiveStrategy.js";
|
|
15
16
|
import {archiveBlocks} from "./utils/archiveBlocks.js";
|
|
17
|
+
import {archiveExecutionPayloadEnvelopes} from "./utils/archivePayloads.js";
|
|
16
18
|
import {pruneHistory} from "./utils/pruneHistory.js";
|
|
17
19
|
import {updateBackfillRange} from "./utils/updateBackfillRange.js";
|
|
18
20
|
|
|
@@ -27,6 +29,7 @@ type ArchiveStoreInitOpts = ArchiveStoreOpts & {dbName: string; anchorState: {fi
|
|
|
27
29
|
|
|
28
30
|
export enum ArchiveStoreTask {
|
|
29
31
|
ArchiveBlocks = "archive_blocks",
|
|
32
|
+
ArchivePayloads = "archive_payloads",
|
|
30
33
|
PruneHistory = "prune_history",
|
|
31
34
|
OnFinalizedCheckpoint = "on_finalized_checkpoint",
|
|
32
35
|
MaybeArchiveState = "maybe_archive_state",
|
|
@@ -189,6 +192,7 @@ export class ArchiveStore {
|
|
|
189
192
|
private processFinalizedCheckpoint = async (finalized: CheckpointWithHex): Promise<void> => {
|
|
190
193
|
try {
|
|
191
194
|
const finalizedEpoch = finalized.epoch;
|
|
195
|
+
const finalizedFork = this.chain.config.getForkSeqAtEpoch(finalizedEpoch);
|
|
192
196
|
this.logger.verbose("Start processing finalized checkpoint", {epoch: finalizedEpoch, rootHex: finalized.rootHex});
|
|
193
197
|
|
|
194
198
|
let timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
@@ -206,6 +210,12 @@ export class ArchiveStore {
|
|
|
206
210
|
);
|
|
207
211
|
timer?.({source: ArchiveStoreTask.ArchiveBlocks});
|
|
208
212
|
|
|
213
|
+
if (finalizedFork >= ForkSeq.gloas) {
|
|
214
|
+
timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
215
|
+
await archiveExecutionPayloadEnvelopes(this.chain, finalized);
|
|
216
|
+
timer?.({source: ArchiveStoreTask.ArchivePayloads});
|
|
217
|
+
}
|
|
218
|
+
|
|
209
219
|
if (this.opts.pruneHistory) {
|
|
210
220
|
timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
211
221
|
await pruneHistory(
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
2
|
+
import {IBeaconChain} from "../../interface.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Archives execution payload envelopes from hot DB to archive DB after finalization.
|
|
6
|
+
*/
|
|
7
|
+
export async function archiveExecutionPayloadEnvelopes(
|
|
8
|
+
chain: IBeaconChain,
|
|
9
|
+
_finalized: CheckpointWithHex
|
|
10
|
+
): Promise<void> {
|
|
11
|
+
const finalizedBlock = chain.forkChoice.getFinalizedBlock();
|
|
12
|
+
if (!finalizedBlock) return;
|
|
13
|
+
|
|
14
|
+
// TODO GLOAS: Implement payload envelope archival after epbs fork choice changes are merged
|
|
15
|
+
}
|
|
@@ -101,9 +101,6 @@ export async function importBlock(
|
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
// Without forcefully clearing this cache, we would rely on WeakMap to evict memory which is not reliable
|
|
105
|
-
this.serializedCache.clear();
|
|
106
|
-
|
|
107
104
|
// 2. Import block to fork choice
|
|
108
105
|
|
|
109
106
|
// Should compute checkpoint balances before forkchoice.onBlock
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {SignedBeaconBlock} from "@lodestar/types";
|
|
2
2
|
import {isErrorAborted, toRootHex} from "@lodestar/utils";
|
|
3
3
|
import {Metrics} from "../../metrics/metrics.js";
|
|
4
|
+
import {nextEventLoop} from "../../util/eventLoop.js";
|
|
4
5
|
import {JobItemQueue, isQueueErrorAborted} from "../../util/queue/index.js";
|
|
5
6
|
import type {BeaconChain} from "../chain.js";
|
|
6
7
|
import {BlockError, BlockErrorCode, isBlockErrorAborted} from "../errors/index.js";
|
|
@@ -100,9 +101,9 @@ export async function processBlocks(
|
|
|
100
101
|
);
|
|
101
102
|
|
|
102
103
|
for (const fullyVerifiedBlock of fullyVerifiedBlocks) {
|
|
103
|
-
// No need to sleep(0) here since `importBlock` includes a disk write
|
|
104
104
|
// TODO: Consider batching importBlock too if it takes significant time
|
|
105
105
|
await importBlock.call(this, fullyVerifiedBlock, opts);
|
|
106
|
+
await nextEventLoop();
|
|
106
107
|
}
|
|
107
108
|
} catch (e) {
|
|
108
109
|
if (isErrorAborted(e) || isQueueErrorAborted(e) || isBlockErrorAborted(e)) {
|
|
@@ -125,6 +125,9 @@ export async function persistBlockInputs(this: BeaconChain, blockInputs: IBlockI
|
|
|
125
125
|
for (const blockInput of blockInputs) {
|
|
126
126
|
this.seenBlockInputCache.prune(blockInput.blockRootHex);
|
|
127
127
|
}
|
|
128
|
+
// Without forcefully clearing this cache, we would rely on WeakMap to evict memory which is not reliable.
|
|
129
|
+
// Clear here (after the DB write) so that writeBlockInputToDb can still use the cached serialized bytes.
|
|
130
|
+
this.serializedCache.clear();
|
|
128
131
|
if (blockInputs.length === 1) {
|
|
129
132
|
this.logger.debug("Pruned block input", {
|
|
130
133
|
slot: blockInputs[0].slot,
|
package/src/chain/chain.ts
CHANGED
|
@@ -5,11 +5,20 @@ import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
|
|
|
5
5
|
import {BeaconConfig} from "@lodestar/config";
|
|
6
6
|
import {CheckpointWithHex, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
|
|
7
7
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
BUILDER_INDEX_SELF_BUILD,
|
|
10
|
+
EFFECTIVE_BALANCE_INCREMENT,
|
|
11
|
+
ForkPostFulu,
|
|
12
|
+
GENESIS_SLOT,
|
|
13
|
+
SLOTS_PER_EPOCH,
|
|
14
|
+
isForkPostElectra,
|
|
15
|
+
isForkPostGloas,
|
|
16
|
+
} from "@lodestar/params";
|
|
9
17
|
import {
|
|
10
18
|
BeaconStateAllForks,
|
|
11
19
|
BeaconStateElectra,
|
|
12
20
|
CachedBeaconStateAllForks,
|
|
21
|
+
CachedBeaconStateGloas,
|
|
13
22
|
EffectiveBalanceIncrements,
|
|
14
23
|
EpochShuffling,
|
|
15
24
|
Index2PubkeyCache,
|
|
@@ -28,6 +37,7 @@ import {
|
|
|
28
37
|
BeaconBlock,
|
|
29
38
|
BlindedBeaconBlock,
|
|
30
39
|
BlindedBeaconBlockBody,
|
|
40
|
+
DataColumnSidecars,
|
|
31
41
|
Epoch,
|
|
32
42
|
Root,
|
|
33
43
|
RootHex,
|
|
@@ -38,7 +48,7 @@ import {
|
|
|
38
48
|
ValidatorIndex,
|
|
39
49
|
Wei,
|
|
40
50
|
deneb,
|
|
41
|
-
|
|
51
|
+
gloas,
|
|
42
52
|
isBlindedBeaconBlock,
|
|
43
53
|
phase0,
|
|
44
54
|
rewards,
|
|
@@ -87,8 +97,8 @@ import {
|
|
|
87
97
|
} from "./opPools/index.js";
|
|
88
98
|
import {IChainOptions} from "./options.js";
|
|
89
99
|
import {PrepareNextSlotScheduler} from "./prepareNextSlot.js";
|
|
90
|
-
import {computeNewStateRoot} from "./produceBlock/computeNewStateRoot.js";
|
|
91
|
-
import {AssembledBlockType, BlockType, ProduceResult} from "./produceBlock/index.js";
|
|
100
|
+
import {computeEnvelopeStateRoot, computeNewStateRoot} from "./produceBlock/computeNewStateRoot.js";
|
|
101
|
+
import {AssembledBlockType, BlockType, ProduceFullGloas, ProduceResult} from "./produceBlock/index.js";
|
|
92
102
|
import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produceBlock/produceBlockBody.js";
|
|
93
103
|
import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js";
|
|
94
104
|
import {ReprocessController} from "./reprocess.js";
|
|
@@ -808,7 +818,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
808
818
|
return null;
|
|
809
819
|
}
|
|
810
820
|
|
|
811
|
-
async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<
|
|
821
|
+
async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecars> {
|
|
812
822
|
const blockInput = this.seenBlockInputCache.get(blockRootHex);
|
|
813
823
|
if (blockInput) {
|
|
814
824
|
if (!isBlockInputColumns(blockInput)) {
|
|
@@ -818,10 +828,10 @@ export class BeaconChain implements IBeaconChain {
|
|
|
818
828
|
}
|
|
819
829
|
const sidecarsUnfinalized = await this.db.dataColumnSidecar.values(fromHex(blockRootHex));
|
|
820
830
|
if (sidecarsUnfinalized.length > 0) {
|
|
821
|
-
return sidecarsUnfinalized;
|
|
831
|
+
return sidecarsUnfinalized as DataColumnSidecars;
|
|
822
832
|
}
|
|
823
833
|
const sidecarsFinalized = await this.db.dataColumnSidecarArchive.values(blockSlot);
|
|
824
|
-
return sidecarsFinalized;
|
|
834
|
+
return sidecarsFinalized as DataColumnSidecars;
|
|
825
835
|
}
|
|
826
836
|
|
|
827
837
|
async getSerializedDataColumnSidecars(
|
|
@@ -843,7 +853,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
843
853
|
if (serialized) {
|
|
844
854
|
return serialized;
|
|
845
855
|
}
|
|
846
|
-
return
|
|
856
|
+
return sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(sidecar);
|
|
847
857
|
});
|
|
848
858
|
}
|
|
849
859
|
const sidecarsUnfinalized = await this.db.dataColumnSidecar.getManyBinary(fromHex(blockRootHex), indices);
|
|
@@ -902,6 +912,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
902
912
|
consensusBlockValue: Wei;
|
|
903
913
|
shouldOverrideBuilder?: boolean;
|
|
904
914
|
}> {
|
|
915
|
+
const fork = this.config.getForkName(slot);
|
|
905
916
|
const state = await this.regen.getBlockSlotState(
|
|
906
917
|
parentBlock,
|
|
907
918
|
slot,
|
|
@@ -930,7 +941,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
930
941
|
// The hashtree root computed here for debug log will get cached and hence won't introduce additional delays
|
|
931
942
|
const bodyRoot =
|
|
932
943
|
produceResult.type === BlockType.Full
|
|
933
|
-
?
|
|
944
|
+
? sszTypesFor(fork).BeaconBlockBody.hashTreeRoot(body)
|
|
934
945
|
: this.config
|
|
935
946
|
.getPostBellatrixForkTypes(slot)
|
|
936
947
|
.BlindedBeaconBlockBody.hashTreeRoot(body as BlindedBeaconBlockBody);
|
|
@@ -948,14 +959,33 @@ export class BeaconChain implements IBeaconChain {
|
|
|
948
959
|
body,
|
|
949
960
|
} as AssembledBlockType<T>;
|
|
950
961
|
|
|
951
|
-
const {newStateRoot, proposerReward} = computeNewStateRoot(this.metrics, state, block);
|
|
962
|
+
const {newStateRoot, proposerReward, postState} = computeNewStateRoot(this.metrics, state, block);
|
|
952
963
|
block.stateRoot = newStateRoot;
|
|
953
964
|
const blockRoot =
|
|
954
965
|
produceResult.type === BlockType.Full
|
|
955
|
-
?
|
|
966
|
+
? sszTypesFor(fork).BeaconBlock.hashTreeRoot(block)
|
|
956
967
|
: this.config.getPostBellatrixForkTypes(slot).BlindedBeaconBlock.hashTreeRoot(block as BlindedBeaconBlock);
|
|
957
968
|
const blockRootHex = toRootHex(blockRoot);
|
|
958
969
|
|
|
970
|
+
if (isForkPostGloas(fork)) {
|
|
971
|
+
// TODO GLOAS: we should retire BlockType post-gloas, may need a new enum for self vs non-self built
|
|
972
|
+
if (produceResult.type !== BlockType.Full) {
|
|
973
|
+
throw Error(`Unexpected block type=${produceResult.type} for post-gloas fork=${fork}`);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
const gloasResult = produceResult as ProduceFullGloas;
|
|
977
|
+
const envelope: gloas.ExecutionPayloadEnvelope = {
|
|
978
|
+
payload: gloasResult.executionPayload,
|
|
979
|
+
executionRequests: gloasResult.executionRequests,
|
|
980
|
+
builderIndex: BUILDER_INDEX_SELF_BUILD,
|
|
981
|
+
beaconBlockRoot: blockRoot,
|
|
982
|
+
slot,
|
|
983
|
+
stateRoot: ZERO_HASH,
|
|
984
|
+
};
|
|
985
|
+
const envelopeStateRoot = computeEnvelopeStateRoot(this.metrics, postState as CachedBeaconStateGloas, envelope);
|
|
986
|
+
gloasResult.envelopeStateRoot = envelopeStateRoot;
|
|
987
|
+
}
|
|
988
|
+
|
|
959
989
|
// Track the produced block for consensus broadcast validations, later validation, etc.
|
|
960
990
|
this.blockProductionCache.set(blockRootHex, produceResult);
|
|
961
991
|
this.metrics?.blockProductionCacheSize.set(this.blockProductionCache.size);
|
package/src/chain/emitter.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {StrictEventEmitter} from "strict-event-emitter-types";
|
|
|
3
3
|
import {routes} from "@lodestar/api";
|
|
4
4
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
5
5
|
import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
|
|
6
|
-
import {RootHex, deneb,
|
|
6
|
+
import {DataColumnSidecars, RootHex, deneb, phase0} from "@lodestar/types";
|
|
7
7
|
import {PeerIdStr} from "../util/peerId.js";
|
|
8
8
|
import {BlockInputSource, IBlockInput} from "./blocks/blockInput/types.js";
|
|
9
9
|
|
|
@@ -88,7 +88,7 @@ export type IChainEvents = ApiEvents & {
|
|
|
88
88
|
|
|
89
89
|
[ChainEvent.updateTargetCustodyGroupCount]: (targetGroupCount: number) => void;
|
|
90
90
|
|
|
91
|
-
[ChainEvent.publishDataColumns]: (sidecars:
|
|
91
|
+
[ChainEvent.publishDataColumns]: (sidecars: DataColumnSidecars) => void;
|
|
92
92
|
|
|
93
93
|
[ChainEvent.publishBlobSidecars]: (sidecars: deneb.BlobSidecar[]) => void;
|
|
94
94
|
|
package/src/chain/interface.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
BeaconBlock,
|
|
13
13
|
BlindedBeaconBlock,
|
|
14
|
+
DataColumnSidecars,
|
|
14
15
|
Epoch,
|
|
15
16
|
Root,
|
|
16
17
|
RootHex,
|
|
@@ -23,7 +24,6 @@ import {
|
|
|
23
24
|
altair,
|
|
24
25
|
capella,
|
|
25
26
|
deneb,
|
|
26
|
-
fulu,
|
|
27
27
|
phase0,
|
|
28
28
|
rewards,
|
|
29
29
|
} from "@lodestar/types";
|
|
@@ -224,7 +224,7 @@ export interface IBeaconChain {
|
|
|
224
224
|
): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
225
225
|
getBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<deneb.BlobSidecars | null>;
|
|
226
226
|
getSerializedBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<Uint8Array | null>;
|
|
227
|
-
getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<
|
|
227
|
+
getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecars>;
|
|
228
228
|
getSerializedDataColumnSidecars(
|
|
229
229
|
blockSlot: Slot,
|
|
230
230
|
blockRootHex: string,
|
|
@@ -355,7 +355,10 @@ export class LightClientServer {
|
|
|
355
355
|
// Signature data
|
|
356
356
|
const update = await this.db.bestLightClientUpdate.get(period);
|
|
357
357
|
if (!update) {
|
|
358
|
-
throw
|
|
358
|
+
throw new LightClientServerError(
|
|
359
|
+
{code: LightClientServerErrorCode.RESOURCE_UNAVAILABLE},
|
|
360
|
+
`No partialUpdate available for period ${period}`
|
|
361
|
+
);
|
|
359
362
|
}
|
|
360
363
|
return update;
|
|
361
364
|
}
|
package/src/chain/options.ts
CHANGED
|
@@ -27,6 +27,7 @@ export type IChainOptions = BlockProcessOpts &
|
|
|
27
27
|
blsVerifyAllMainThread?: boolean;
|
|
28
28
|
blsVerifyAllMultiThread?: boolean;
|
|
29
29
|
blacklistedBlocks?: string[];
|
|
30
|
+
// TODO GLOAS: add similar option for execution payload envelopes?
|
|
30
31
|
persistProducedBlocks?: boolean;
|
|
31
32
|
persistInvalidSszObjects?: boolean;
|
|
32
33
|
persistInvalidSszObjectsDir?: string;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
3
|
import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
4
|
-
import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
4
|
+
import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix} from "@lodestar/params";
|
|
5
5
|
import {
|
|
6
6
|
CachedBeaconStateAllForks,
|
|
7
7
|
CachedBeaconStateExecutions,
|
|
8
|
+
CachedBeaconStateGloas,
|
|
8
9
|
StateHashTreeRootSource,
|
|
9
10
|
computeEpochAtSlot,
|
|
10
11
|
computeTimeAtSlot,
|
|
11
|
-
isExecutionStateType,
|
|
12
12
|
} from "@lodestar/state-transition";
|
|
13
13
|
import {Slot} from "@lodestar/types";
|
|
14
14
|
import {Logger, fromHex, isErrorAborted, sleep} from "@lodestar/utils";
|
|
@@ -120,10 +120,10 @@ export class PrepareNextSlotScheduler {
|
|
|
120
120
|
RegenCaller.precomputeEpoch
|
|
121
121
|
);
|
|
122
122
|
|
|
123
|
-
if (
|
|
123
|
+
if (isForkPostBellatrix(fork)) {
|
|
124
124
|
const proposerIndex = prepareState.epochCtx.getBeaconProposer(prepareSlot);
|
|
125
125
|
const feeRecipient = this.chain.beaconProposerCache.get(proposerIndex);
|
|
126
|
-
let updatedPrepareState = prepareState;
|
|
126
|
+
let updatedPrepareState = prepareState as CachedBeaconStateExecutions | CachedBeaconStateGloas;
|
|
127
127
|
let updatedHeadRoot = headRoot;
|
|
128
128
|
|
|
129
129
|
if (feeRecipient) {
|
|
@@ -146,7 +146,7 @@ export class PrepareNextSlotScheduler {
|
|
|
146
146
|
// only transfer cache if epoch transition because that's the state we will use to stateTransition() the 1st block of epoch
|
|
147
147
|
{dontTransferCache: !isEpochTransition},
|
|
148
148
|
RegenCaller.predictProposerHead
|
|
149
|
-
)) as CachedBeaconStateExecutions;
|
|
149
|
+
)) as CachedBeaconStateExecutions | CachedBeaconStateGloas;
|
|
150
150
|
updatedHeadRoot = proposerHeadRoot;
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CachedBeaconStateAllForks,
|
|
3
|
+
CachedBeaconStateGloas,
|
|
3
4
|
DataAvailabilityStatus,
|
|
4
5
|
ExecutionPayloadStatus,
|
|
6
|
+
G2_POINT_AT_INFINITY,
|
|
5
7
|
StateHashTreeRootSource,
|
|
6
8
|
stateTransition,
|
|
7
9
|
} from "@lodestar/state-transition";
|
|
8
|
-
import {
|
|
10
|
+
import {processExecutionPayloadEnvelope} from "@lodestar/state-transition/block";
|
|
11
|
+
import {BeaconBlock, BlindedBeaconBlock, Gwei, Root, gloas} from "@lodestar/types";
|
|
9
12
|
import {ZERO_HASH} from "../../constants/index.js";
|
|
10
13
|
import {Metrics} from "../../metrics/index.js";
|
|
11
14
|
|
|
@@ -18,7 +21,7 @@ export function computeNewStateRoot(
|
|
|
18
21
|
metrics: Metrics | null,
|
|
19
22
|
state: CachedBeaconStateAllForks,
|
|
20
23
|
block: BeaconBlock | BlindedBeaconBlock
|
|
21
|
-
): {newStateRoot: Root; proposerReward: Gwei} {
|
|
24
|
+
): {newStateRoot: Root; proposerReward: Gwei; postState: CachedBeaconStateAllForks} {
|
|
22
25
|
// Set signature to zero to re-use stateTransition() function which requires the SignedBeaconBlock type
|
|
23
26
|
const blockEmptySig = {message: block, signature: ZERO_HASH};
|
|
24
27
|
|
|
@@ -51,5 +54,34 @@ export function computeNewStateRoot(
|
|
|
51
54
|
const newStateRoot = postState.hashTreeRoot();
|
|
52
55
|
hashTreeRootTimer?.();
|
|
53
56
|
|
|
54
|
-
return {newStateRoot, proposerReward};
|
|
57
|
+
return {newStateRoot, proposerReward, postState};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Compute the state root after processing an execution payload envelope.
|
|
62
|
+
* Similar to `computeNewStateRoot` but for payload envelope processing.
|
|
63
|
+
*
|
|
64
|
+
* The `postBlockState` is mutated in place, callers must ensure it is not needed afterward.
|
|
65
|
+
*/
|
|
66
|
+
export function computeEnvelopeStateRoot(
|
|
67
|
+
metrics: Metrics | null,
|
|
68
|
+
postBlockState: CachedBeaconStateGloas,
|
|
69
|
+
envelope: gloas.ExecutionPayloadEnvelope
|
|
70
|
+
): Root {
|
|
71
|
+
const signedEnvelope: gloas.SignedExecutionPayloadEnvelope = {
|
|
72
|
+
message: envelope,
|
|
73
|
+
signature: G2_POINT_AT_INFINITY,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const processEnvelopeTimer = metrics?.blockPayload.executionPayloadEnvelopeProcessingTime.startTimer();
|
|
77
|
+
processExecutionPayloadEnvelope(postBlockState, signedEnvelope, false);
|
|
78
|
+
processEnvelopeTimer?.();
|
|
79
|
+
|
|
80
|
+
const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
|
|
81
|
+
source: StateHashTreeRootSource.computeEnvelopeStateRoot,
|
|
82
|
+
});
|
|
83
|
+
const stateRoot = postBlockState.hashTreeRoot();
|
|
84
|
+
hashTreeRootTimer?.();
|
|
85
|
+
|
|
86
|
+
return stateRoot;
|
|
55
87
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ProtoBlock, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
2
|
+
import {IForkChoice, ProtoBlock, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
3
3
|
import {
|
|
4
|
+
BUILDER_INDEX_SELF_BUILD,
|
|
4
5
|
ForkName,
|
|
5
6
|
ForkPostBellatrix,
|
|
7
|
+
ForkPostCapella,
|
|
6
8
|
ForkPostDeneb,
|
|
7
9
|
ForkPostFulu,
|
|
10
|
+
ForkPostGloas,
|
|
8
11
|
ForkPreGloas,
|
|
9
12
|
ForkSeq,
|
|
10
13
|
isForkPostAltair,
|
|
@@ -16,6 +19,8 @@ import {
|
|
|
16
19
|
CachedBeaconStateBellatrix,
|
|
17
20
|
CachedBeaconStateCapella,
|
|
18
21
|
CachedBeaconStateExecutions,
|
|
22
|
+
CachedBeaconStateGloas,
|
|
23
|
+
G2_POINT_AT_INFINITY,
|
|
19
24
|
computeTimeAtSlot,
|
|
20
25
|
getExpectedWithdrawals,
|
|
21
26
|
getRandaoMix,
|
|
@@ -42,6 +47,7 @@ import {
|
|
|
42
47
|
deneb,
|
|
43
48
|
electra,
|
|
44
49
|
fulu,
|
|
50
|
+
gloas,
|
|
45
51
|
} from "@lodestar/types";
|
|
46
52
|
import {Logger, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
47
53
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
@@ -99,6 +105,20 @@ export type AssembledBodyType<T extends BlockType> = T extends BlockType.Full
|
|
|
99
105
|
: BlindedBeaconBlockBody;
|
|
100
106
|
export type AssembledBlockType<T extends BlockType> = T extends BlockType.Full ? BeaconBlock : BlindedBeaconBlock;
|
|
101
107
|
|
|
108
|
+
export type ProduceFullGloas = {
|
|
109
|
+
type: BlockType.Full;
|
|
110
|
+
fork: ForkPostGloas;
|
|
111
|
+
executionPayload: ExecutionPayload<ForkPostGloas>;
|
|
112
|
+
executionRequests: electra.ExecutionRequests;
|
|
113
|
+
blobsBundle: BlobsBundle<ForkPostGloas>;
|
|
114
|
+
cells: fulu.Cell[][];
|
|
115
|
+
/**
|
|
116
|
+
* Cached envelope state root computed during block production.
|
|
117
|
+
* This is the state root after running `processExecutionPayloadEnvelope` on the
|
|
118
|
+
* post-block state, and later used to construct the `ExecutionPayloadEnvelope`.
|
|
119
|
+
*/
|
|
120
|
+
envelopeStateRoot: Root;
|
|
121
|
+
};
|
|
102
122
|
export type ProduceFullFulu = {
|
|
103
123
|
type: BlockType.Full;
|
|
104
124
|
fork: ForkPostFulu;
|
|
@@ -131,6 +151,7 @@ export type ProduceBlinded = {
|
|
|
131
151
|
|
|
132
152
|
/** The result of local block production, everything that's not the block itself */
|
|
133
153
|
export type ProduceResult =
|
|
154
|
+
| ProduceFullGloas
|
|
134
155
|
| ProduceFullFulu
|
|
135
156
|
| ProduceFullDeneb
|
|
136
157
|
| ProduceFullBellatrix
|
|
@@ -180,12 +201,112 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
180
201
|
this.logger.verbose("Producing beacon block body", logMeta);
|
|
181
202
|
|
|
182
203
|
if (isForkPostGloas(fork)) {
|
|
183
|
-
// TODO GLOAS:
|
|
204
|
+
// TODO GLOAS: support non self-building here, the block type differentiation between
|
|
205
|
+
// full and blinded no longer makes sense in gloas, it might be a good idea to move
|
|
206
|
+
// this into a completely separate function and have pre/post gloas more separated
|
|
207
|
+
const gloasState = currentState as CachedBeaconStateGloas;
|
|
208
|
+
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
|
|
209
|
+
const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
210
|
+
const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);
|
|
211
|
+
|
|
212
|
+
const endExecutionPayload = this.metrics?.executionBlockProductionTimeSteps.startTimer();
|
|
213
|
+
|
|
214
|
+
this.logger.verbose("Preparing execution payload from engine", {
|
|
215
|
+
slot: blockSlot,
|
|
216
|
+
parentBlockRoot: toRootHex(parentBlockRoot),
|
|
217
|
+
feeRecipient,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Get execution payload from EL
|
|
221
|
+
const prepareRes = await prepareExecutionPayload(
|
|
222
|
+
this,
|
|
223
|
+
this.logger,
|
|
224
|
+
fork,
|
|
225
|
+
parentBlockRoot,
|
|
226
|
+
safeBlockHash,
|
|
227
|
+
finalizedBlockHash ?? ZERO_HASH_HEX,
|
|
228
|
+
gloasState,
|
|
229
|
+
feeRecipient
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const {prepType, payloadId} = prepareRes;
|
|
233
|
+
Object.assign(logMeta, {executionPayloadPrepType: prepType});
|
|
234
|
+
|
|
235
|
+
if (prepType !== PayloadPreparationType.Cached) {
|
|
236
|
+
await sleep(PAYLOAD_GENERATION_TIME_MS);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.logger.verbose("Fetching execution payload from engine", {slot: blockSlot, payloadId});
|
|
240
|
+
const payloadRes = await this.executionEngine.getPayload(fork, payloadId);
|
|
241
|
+
|
|
242
|
+
endExecutionPayload?.({step: BlockProductionStep.executionPayload});
|
|
243
|
+
|
|
244
|
+
const {executionPayload, blobsBundle, executionRequests} = payloadRes;
|
|
245
|
+
executionPayloadValue = payloadRes.executionPayloadValue;
|
|
246
|
+
shouldOverrideBuilder = payloadRes.shouldOverrideBuilder;
|
|
247
|
+
|
|
248
|
+
if (blobsBundle === undefined) {
|
|
249
|
+
throw Error(`Missing blobsBundle response from getPayload at fork=${fork}`);
|
|
250
|
+
}
|
|
251
|
+
if (executionRequests === undefined) {
|
|
252
|
+
throw Error(`Missing executionRequests response from getPayload at fork=${fork}`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const cells = blobsBundle.blobs.map((blob) => kzg.computeCells(blob));
|
|
256
|
+
if (this.opts.sanityCheckExecutionEngineBlobs) {
|
|
257
|
+
await validateCellsAndKzgCommitments(blobsBundle.commitments, blobsBundle.proofs, cells);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Create self-build execution payload bid
|
|
261
|
+
const bid: gloas.ExecutionPayloadBid = {
|
|
262
|
+
parentBlockHash: gloasState.latestBlockHash,
|
|
263
|
+
parentBlockRoot: parentBlockRoot,
|
|
264
|
+
blockHash: executionPayload.blockHash,
|
|
265
|
+
prevRandao: getRandaoMix(gloasState, gloasState.epochCtx.epoch),
|
|
266
|
+
feeRecipient: executionPayload.feeRecipient,
|
|
267
|
+
gasLimit: BigInt(executionPayload.gasLimit),
|
|
268
|
+
builderIndex: BUILDER_INDEX_SELF_BUILD,
|
|
269
|
+
slot: blockSlot,
|
|
270
|
+
value: 0,
|
|
271
|
+
executionPayment: 0,
|
|
272
|
+
blobKzgCommitments: blobsBundle.commitments,
|
|
273
|
+
};
|
|
274
|
+
const signedBid: gloas.SignedExecutionPayloadBid = {
|
|
275
|
+
message: bid,
|
|
276
|
+
signature: G2_POINT_AT_INFINITY,
|
|
277
|
+
};
|
|
278
|
+
|
|
184
279
|
const commonBlockBody = await commonBlockBodyPromise;
|
|
185
|
-
|
|
186
|
-
|
|
280
|
+
const gloasBody = Object.assign({}, commonBlockBody) as gloas.BeaconBlockBody;
|
|
281
|
+
gloasBody.signedExecutionPayloadBid = signedBid;
|
|
282
|
+
// TODO GLOAS: Get payload attestations from pool for previous slot
|
|
283
|
+
gloasBody.payloadAttestations = [];
|
|
284
|
+
blockBody = gloasBody as AssembledBodyType<T>;
|
|
285
|
+
|
|
286
|
+
// Store execution payload data required to construct execution payload envelope later
|
|
287
|
+
const gloasResult = produceResult as ProduceFullGloas;
|
|
288
|
+
gloasResult.executionPayload = executionPayload as ExecutionPayload<ForkPostGloas>;
|
|
289
|
+
gloasResult.executionRequests = executionRequests;
|
|
290
|
+
gloasResult.blobsBundle = blobsBundle;
|
|
291
|
+
gloasResult.cells = cells;
|
|
292
|
+
|
|
293
|
+
const fetchedTime = Date.now() / 1000 - computeTimeAtSlot(this.config, blockSlot, this.genesisTime);
|
|
294
|
+
this.metrics?.blockPayload.payloadFetchedTime.observe({prepType}, fetchedTime);
|
|
295
|
+
this.logger.verbose("Produced block with self-build bid", {
|
|
296
|
+
slot: blockSlot,
|
|
297
|
+
executionPayloadValue,
|
|
298
|
+
prepType,
|
|
299
|
+
payloadId,
|
|
300
|
+
fetchedTime,
|
|
301
|
+
executionBlockHash: toRootHex(executionPayload.blockHash),
|
|
302
|
+
blobs: blobsBundle.commitments.length,
|
|
303
|
+
});
|
|
187
304
|
|
|
188
|
-
|
|
305
|
+
Object.assign(logMeta, {
|
|
306
|
+
transactions: executionPayload.transactions.length,
|
|
307
|
+
blobs: blobsBundle.commitments.length,
|
|
308
|
+
shouldOverrideBuilder,
|
|
309
|
+
});
|
|
189
310
|
} else if (isForkPostBellatrix(fork)) {
|
|
190
311
|
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
|
|
191
312
|
const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
@@ -447,8 +568,14 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
447
568
|
});
|
|
448
569
|
}
|
|
449
570
|
|
|
450
|
-
if (ForkSeq[fork] >= ForkSeq.
|
|
451
|
-
const {blsToExecutionChanges,
|
|
571
|
+
if (ForkSeq[fork] >= ForkSeq.gloas) {
|
|
572
|
+
const {blsToExecutionChanges, payloadAttestations} = blockBody as BeaconBlockBody<ForkPostGloas>;
|
|
573
|
+
Object.assign(logMeta, {
|
|
574
|
+
blsToExecutionChanges: blsToExecutionChanges.length,
|
|
575
|
+
payloadAttestations: payloadAttestations.length,
|
|
576
|
+
});
|
|
577
|
+
} else if (ForkSeq[fork] >= ForkSeq.capella) {
|
|
578
|
+
const {blsToExecutionChanges, executionPayload} = blockBody as BeaconBlockBody<ForkPostCapella & ForkPreGloas>;
|
|
452
579
|
Object.assign(logMeta, {
|
|
453
580
|
blsToExecutionChanges: blsToExecutionChanges.length,
|
|
454
581
|
});
|
|
@@ -480,10 +607,12 @@ export async function prepareExecutionPayload(
|
|
|
480
607
|
parentBlockRoot: Root,
|
|
481
608
|
safeBlockHash: RootHex,
|
|
482
609
|
finalizedBlockHash: RootHex,
|
|
483
|
-
state: CachedBeaconStateExecutions,
|
|
610
|
+
state: CachedBeaconStateExecutions | CachedBeaconStateGloas,
|
|
484
611
|
suggestedFeeRecipient: string
|
|
485
612
|
): Promise<{prepType: PayloadPreparationType; payloadId: PayloadId}> {
|
|
486
|
-
const parentHash =
|
|
613
|
+
const parentHash = isForkPostGloas(fork)
|
|
614
|
+
? (state as CachedBeaconStateGloas).latestBlockHash
|
|
615
|
+
: (state as CachedBeaconStateExecutions).latestExecutionPayloadHeader.blockHash;
|
|
487
616
|
const timestamp = computeTimeAtSlot(chain.config, state.slot, state.genesisTime);
|
|
488
617
|
const prevRandao = getRandaoMix(state, state.epochCtx.epoch);
|
|
489
618
|
|
|
@@ -568,25 +697,46 @@ export function getPayloadAttributesForSSE(
|
|
|
568
697
|
fork: ForkPostBellatrix,
|
|
569
698
|
chain: {
|
|
570
699
|
config: ChainForkConfig;
|
|
700
|
+
forkChoice: IForkChoice;
|
|
571
701
|
},
|
|
572
702
|
{
|
|
573
703
|
prepareState,
|
|
574
704
|
prepareSlot,
|
|
575
705
|
parentBlockRoot,
|
|
576
706
|
feeRecipient,
|
|
577
|
-
}: {
|
|
707
|
+
}: {
|
|
708
|
+
prepareState: CachedBeaconStateExecutions | CachedBeaconStateGloas;
|
|
709
|
+
prepareSlot: Slot;
|
|
710
|
+
parentBlockRoot: Root;
|
|
711
|
+
feeRecipient: string;
|
|
712
|
+
}
|
|
578
713
|
): SSEPayloadAttributes {
|
|
579
|
-
const parentHash =
|
|
714
|
+
const parentHash = isForkPostGloas(fork)
|
|
715
|
+
? (prepareState as CachedBeaconStateGloas).latestBlockHash
|
|
716
|
+
: (prepareState as CachedBeaconStateExecutions).latestExecutionPayloadHeader.blockHash;
|
|
580
717
|
const payloadAttributes = preparePayloadAttributes(fork, chain, {
|
|
581
718
|
prepareState,
|
|
582
719
|
prepareSlot,
|
|
583
720
|
parentBlockRoot,
|
|
584
721
|
feeRecipient,
|
|
585
722
|
});
|
|
723
|
+
|
|
724
|
+
let parentBlockNumber: number;
|
|
725
|
+
if (isForkPostGloas(fork)) {
|
|
726
|
+
// TODO GLOAS: revisit this after fork choice changes are merged
|
|
727
|
+
const parentBlock = chain.forkChoice.getBlock(parentBlockRoot);
|
|
728
|
+
if (parentBlock?.executionPayloadBlockHash == null) {
|
|
729
|
+
throw Error(`Parent block not found in fork choice root=${toRootHex(parentBlockRoot)}`);
|
|
730
|
+
}
|
|
731
|
+
parentBlockNumber = parentBlock.executionPayloadNumber;
|
|
732
|
+
} else {
|
|
733
|
+
parentBlockNumber = (prepareState as CachedBeaconStateExecutions).latestExecutionPayloadHeader.blockNumber;
|
|
734
|
+
}
|
|
735
|
+
|
|
586
736
|
const ssePayloadAttributes: SSEPayloadAttributes = {
|
|
587
737
|
proposerIndex: prepareState.epochCtx.getBeaconProposer(prepareSlot),
|
|
588
738
|
proposalSlot: prepareSlot,
|
|
589
|
-
parentBlockNumber
|
|
739
|
+
parentBlockNumber,
|
|
590
740
|
parentBlockRoot,
|
|
591
741
|
parentBlockHash: parentHash,
|
|
592
742
|
payloadAttributes,
|
|
@@ -605,7 +755,7 @@ function preparePayloadAttributes(
|
|
|
605
755
|
parentBlockRoot,
|
|
606
756
|
feeRecipient,
|
|
607
757
|
}: {
|
|
608
|
-
prepareState: CachedBeaconStateExecutions;
|
|
758
|
+
prepareState: CachedBeaconStateExecutions | CachedBeaconStateGloas;
|
|
609
759
|
prepareSlot: Slot;
|
|
610
760
|
parentBlockRoot: Root;
|
|
611
761
|
feeRecipient: string;
|