@lodestar/beacon-node 1.41.0-dev.07f3dcc477 → 1.41.0-dev.0b3690a9ad
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/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/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/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/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/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/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/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/index.ts +2 -1
- package/src/chain/chain.ts +41 -11
- package/src/chain/emitter.ts +2 -2
- package/src/chain/interface.ts +2 -2
- 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/util/blobs.ts +3 -3
- package/src/util/dataColumns.ts +37 -1
- package/src/util/multifork.ts +45 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ApiError, ApplicationMethods} from "@lodestar/api/server";
|
|
3
3
|
import {
|
|
4
|
+
BUILDER_INDEX_SELF_BUILD,
|
|
4
5
|
ForkPostBellatrix,
|
|
5
6
|
ForkPostFulu,
|
|
6
7
|
ForkPreGloas,
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
WithOptionalBytes,
|
|
28
29
|
deneb,
|
|
29
30
|
fulu,
|
|
31
|
+
gloas,
|
|
30
32
|
isDenebBlockContents,
|
|
31
33
|
sszTypesFor,
|
|
32
34
|
} from "@lodestar/types";
|
|
@@ -42,6 +44,7 @@ import {
|
|
|
42
44
|
ProduceFullBellatrix,
|
|
43
45
|
ProduceFullDeneb,
|
|
44
46
|
ProduceFullFulu,
|
|
47
|
+
ProduceFullGloas,
|
|
45
48
|
} from "../../../../chain/produceBlock/index.js";
|
|
46
49
|
import {validateGossipBlock} from "../../../../chain/validation/block.js";
|
|
47
50
|
import {OpSource} from "../../../../chain/validatorMonitor.js";
|
|
@@ -51,7 +54,7 @@ import {
|
|
|
51
54
|
kzgCommitmentToVersionedHash,
|
|
52
55
|
reconstructBlobs,
|
|
53
56
|
} from "../../../../util/blobs.js";
|
|
54
|
-
import {getDataColumnSidecarsFromBlock} from "../../../../util/dataColumns.js";
|
|
57
|
+
import {getDataColumnSidecarsForGloas, getDataColumnSidecarsFromBlock} from "../../../../util/dataColumns.js";
|
|
55
58
|
import {isOptimisticBlock} from "../../../../util/forkChoice.js";
|
|
56
59
|
import {kzg} from "../../../../util/kzg.js";
|
|
57
60
|
import {promiseAllMaybeAsync} from "../../../../util/promises.js";
|
|
@@ -93,6 +96,7 @@ export function getBeaconBlockApi({
|
|
|
93
96
|
const fork = config.getForkName(slot);
|
|
94
97
|
const blockRoot = toRootHex(chain.config.getForkTypes(slot).BeaconBlock.hashTreeRoot(signedBlock.message));
|
|
95
98
|
|
|
99
|
+
// TODO GLOAS: handle new BlockInput type
|
|
96
100
|
const blockForImport = chain.seenBlockInputCache.getByBlock({
|
|
97
101
|
block: signedBlock,
|
|
98
102
|
source: BlockInputSource.api,
|
|
@@ -309,7 +313,9 @@ export function getBeaconBlockApi({
|
|
|
309
313
|
];
|
|
310
314
|
const sentPeersArr = await promiseAllMaybeAsync<number | void>(publishPromises);
|
|
311
315
|
|
|
312
|
-
if (
|
|
316
|
+
if (isForkPostGloas(fork)) {
|
|
317
|
+
// After gloas, data columns are not published with the block but when publishing the execution payload envelope
|
|
318
|
+
} else if (isForkPostFulu(fork)) {
|
|
313
319
|
let columnsPublishedWithZeroPeers = 0;
|
|
314
320
|
// sent peers per topic are logged in network.publishGossip(), here we only track metrics for it
|
|
315
321
|
// starting from fulu, we have to push to 128 subnets so need to make sure we have enough sent peers per topic
|
|
@@ -632,6 +638,143 @@ export function getBeaconBlockApi({
|
|
|
632
638
|
await publishBlock(args, context, opts);
|
|
633
639
|
},
|
|
634
640
|
|
|
641
|
+
async publishExecutionPayloadEnvelope({signedExecutionPayloadEnvelope}) {
|
|
642
|
+
const seenTimestampSec = Date.now() / 1000;
|
|
643
|
+
const envelope = signedExecutionPayloadEnvelope.message;
|
|
644
|
+
const slot = envelope.slot;
|
|
645
|
+
const fork = config.getForkName(slot);
|
|
646
|
+
const blockRootHex = toRootHex(envelope.beaconBlockRoot);
|
|
647
|
+
|
|
648
|
+
if (!isForkPostGloas(fork)) {
|
|
649
|
+
throw new ApiError(400, `publishExecutionPayloadEnvelope not supported for pre-gloas fork=${fork}`);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// TODO GLOAS: review checks, do we want to implement `broadcast_validation`?
|
|
653
|
+
const block = chain.forkChoice.getBlockHex(blockRootHex);
|
|
654
|
+
if (block === null) {
|
|
655
|
+
throw new ApiError(404, `Block not found for beacon block root ${blockRootHex}`);
|
|
656
|
+
}
|
|
657
|
+
if (block.slot !== slot) {
|
|
658
|
+
throw new ApiError(400, `Envelope slot ${slot} does not match block slot ${block.slot}`);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
const isSelfBuild = envelope.builderIndex === BUILDER_INDEX_SELF_BUILD;
|
|
662
|
+
let dataColumnSidecars: gloas.DataColumnSidecars = [];
|
|
663
|
+
|
|
664
|
+
if (isSelfBuild) {
|
|
665
|
+
// For self-builds, construct and publish data column sidecars from cached block production data
|
|
666
|
+
const cachedResult = chain.blockProductionCache.get(blockRootHex) as ProduceFullGloas | undefined;
|
|
667
|
+
if (cachedResult === undefined) {
|
|
668
|
+
throw new ApiError(404, `No cached block production result found for block root ${blockRootHex}`);
|
|
669
|
+
}
|
|
670
|
+
if (!isForkPostGloas(cachedResult.fork)) {
|
|
671
|
+
throw new ApiError(400, `Cached block production result is for pre-gloas fork=${cachedResult.fork}`);
|
|
672
|
+
}
|
|
673
|
+
if (cachedResult.type !== BlockType.Full) {
|
|
674
|
+
throw new ApiError(400, "Cached block production result is not full block");
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (cachedResult.cells && cachedResult.blobsBundle.commitments.length > 0) {
|
|
678
|
+
const cellsAndProofs = cachedResult.cells.map((rowCells, rowIndex) => ({
|
|
679
|
+
cells: rowCells,
|
|
680
|
+
proofs: cachedResult.blobsBundle.proofs.slice(
|
|
681
|
+
rowIndex * NUMBER_OF_COLUMNS,
|
|
682
|
+
(rowIndex + 1) * NUMBER_OF_COLUMNS
|
|
683
|
+
),
|
|
684
|
+
}));
|
|
685
|
+
|
|
686
|
+
dataColumnSidecars = getDataColumnSidecarsForGloas(slot, envelope.beaconBlockRoot, cellsAndProofs);
|
|
687
|
+
}
|
|
688
|
+
} else {
|
|
689
|
+
// TODO GLOAS: will this api be used by builders or only for self-building?
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// TODO GLOAS: Verify execution payload envelope signature
|
|
693
|
+
// For self-builds, the proposer signs with their own validator key
|
|
694
|
+
// For external builders, verify using the builder's registered pubkey
|
|
695
|
+
// Use verify_execution_payload_envelope_signature(state, signed_envelope)
|
|
696
|
+
|
|
697
|
+
// TODO GLOAS: Process execution payload via state transition
|
|
698
|
+
// Call process_execution_payload(state, signed_envelope, execution_engine)
|
|
699
|
+
|
|
700
|
+
// TODO GLOAS: Update fork choice with the execution payload
|
|
701
|
+
// Call on_execution_payload(store, signed_envelope) to update fork choice state
|
|
702
|
+
|
|
703
|
+
// TODO GLOAS: Add envelope and data columns to block input via seenBlockInputCache
|
|
704
|
+
// and trigger block import (Gloas block import requires both beacon block and envelope)
|
|
705
|
+
|
|
706
|
+
const valLogMeta = {
|
|
707
|
+
slot,
|
|
708
|
+
blockRoot: blockRootHex,
|
|
709
|
+
builderIndex: envelope.builderIndex,
|
|
710
|
+
isSelfBuild,
|
|
711
|
+
dataColumns: dataColumnSidecars.length,
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
// If called near a slot boundary (e.g. late in slot N-1), hold briefly so gossip aligns with slot N.
|
|
715
|
+
const msToBlockSlot = computeTimeAtSlot(config, slot, chain.genesisTime) * 1000 - Date.now();
|
|
716
|
+
if (msToBlockSlot <= MAX_API_CLOCK_DISPARITY_MS && msToBlockSlot > 0) {
|
|
717
|
+
await sleep(msToBlockSlot);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
721
|
+
metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({source: OpSource.api}, delaySec);
|
|
722
|
+
|
|
723
|
+
chain.logger.info("Publishing execution payload envelope", valLogMeta);
|
|
724
|
+
|
|
725
|
+
// Publish envelope and data columns
|
|
726
|
+
const publishPromises = [
|
|
727
|
+
// Gossip the signed execution payload envelope first
|
|
728
|
+
() => network.publishSignedExecutionPayloadEnvelope(signedExecutionPayloadEnvelope),
|
|
729
|
+
// For self-builds, publish all data column sidecars
|
|
730
|
+
...dataColumnSidecars.map((dataColumnSidecar) => () => network.publishDataColumnSidecar(dataColumnSidecar)),
|
|
731
|
+
];
|
|
732
|
+
|
|
733
|
+
const sentPeersArr = await promiseAllMaybeAsync<number | void>(publishPromises);
|
|
734
|
+
|
|
735
|
+
// Track metrics for data column publishing
|
|
736
|
+
if (dataColumnSidecars.length > 0) {
|
|
737
|
+
let columnsPublishedWithZeroPeers = 0;
|
|
738
|
+
// Skip first entry (envelope), track data columns
|
|
739
|
+
for (let i = 1; i < sentPeersArr.length; i++) {
|
|
740
|
+
const sentPeers = sentPeersArr[i] as number;
|
|
741
|
+
metrics?.dataColumns.sentPeersPerSubnet.observe(sentPeers);
|
|
742
|
+
if (sentPeers === 0) {
|
|
743
|
+
columnsPublishedWithZeroPeers++;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (columnsPublishedWithZeroPeers > 0) {
|
|
747
|
+
chain.logger.warn("Published data columns to 0 peers, increased risk of reorg", {
|
|
748
|
+
slot,
|
|
749
|
+
blockRoot: blockRootHex,
|
|
750
|
+
columns: columnsPublishedWithZeroPeers,
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
metrics?.dataColumns.bySource.inc({source: BlockInputSource.api}, dataColumnSidecars.length);
|
|
755
|
+
|
|
756
|
+
if (chain.emitter.listenerCount(routes.events.EventType.dataColumnSidecar)) {
|
|
757
|
+
// TODO GLOAS: revisit this, we likely don't wanna emit KZG commitments anymore
|
|
758
|
+
const cachedResult = chain.blockProductionCache.get(blockRootHex) as ProduceFullGloas | undefined;
|
|
759
|
+
const kzgCommitments = cachedResult?.blobsBundle.commitments.map(toHex) ?? [];
|
|
760
|
+
for (const dataColumnSidecar of dataColumnSidecars) {
|
|
761
|
+
chain.emitter.emit(routes.events.EventType.dataColumnSidecar, {
|
|
762
|
+
blockRoot: blockRootHex,
|
|
763
|
+
slot,
|
|
764
|
+
index: dataColumnSidecar.index,
|
|
765
|
+
kzgCommitments,
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
chain.logger.info("Published execution payload envelope", {
|
|
772
|
+
...valLogMeta,
|
|
773
|
+
delaySec,
|
|
774
|
+
sentPeers: (sentPeersArr[0] as number) ?? 0,
|
|
775
|
+
});
|
|
776
|
+
},
|
|
777
|
+
|
|
635
778
|
async getBlobSidecars({blockId, indices}) {
|
|
636
779
|
assertUniqueItems(indices, "Duplicate indices provided");
|
|
637
780
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ApplicationMethods} from "@lodestar/api/server";
|
|
3
3
|
import {ExecutionStatus} from "@lodestar/fork-choice";
|
|
4
|
-
import {ZERO_HASH_HEX, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
5
|
-
import {BeaconState,
|
|
4
|
+
import {ForkPostDeneb, ZERO_HASH_HEX, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
5
|
+
import {BeaconState, DataColumnSidecars, type SignedBeaconBlock, sszTypesFor} from "@lodestar/types";
|
|
6
6
|
import {toRootHex} from "@lodestar/utils";
|
|
7
|
+
import {getBlobKzgCommitments} from "../../../util/dataColumns.js";
|
|
7
8
|
import {isOptimisticBlock} from "../../../util/forkChoice.js";
|
|
8
9
|
import {getStateSlotFromBytes} from "../../../util/multifork.js";
|
|
9
10
|
import {getBlockResponse} from "../beacon/blocks/utils.js";
|
|
@@ -96,10 +97,10 @@ export function getDebugApi({
|
|
|
96
97
|
const fork = config.getForkName(block.message.slot);
|
|
97
98
|
const blockRoot = sszTypesFor(fork).BeaconBlock.hashTreeRoot(block.message);
|
|
98
99
|
|
|
99
|
-
let dataColumnSidecars:
|
|
100
|
+
let dataColumnSidecars: DataColumnSidecars;
|
|
100
101
|
|
|
101
102
|
const blobCount = isForkPostDeneb(fork)
|
|
102
|
-
? (block
|
|
103
|
+
? getBlobKzgCommitments(fork, block as SignedBeaconBlock<ForkPostDeneb>).length
|
|
103
104
|
: 0;
|
|
104
105
|
|
|
105
106
|
if (isForkPostFulu(fork) && blobCount > 0) {
|
|
@@ -115,7 +116,9 @@ export function getDebugApi({
|
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
return {
|
|
118
|
-
data:
|
|
119
|
+
data: (indices
|
|
120
|
+
? dataColumnSidecars.filter(({index}) => indices.includes(index))
|
|
121
|
+
: dataColumnSidecars) as DataColumnSidecars,
|
|
119
122
|
meta: {
|
|
120
123
|
executionOptimistic,
|
|
121
124
|
finalized,
|
|
@@ -3,6 +3,7 @@ import {routes} from "@lodestar/api";
|
|
|
3
3
|
import {ApplicationMethods} from "@lodestar/api/server";
|
|
4
4
|
import {ExecutionStatus, ProtoBlock} from "@lodestar/fork-choice";
|
|
5
5
|
import {
|
|
6
|
+
BUILDER_INDEX_SELF_BUILD,
|
|
6
7
|
ForkName,
|
|
7
8
|
ForkPostBellatrix,
|
|
8
9
|
ForkPreGloas,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
isForkPostBellatrix,
|
|
15
16
|
isForkPostDeneb,
|
|
16
17
|
isForkPostElectra,
|
|
18
|
+
isForkPostGloas,
|
|
17
19
|
} from "@lodestar/params";
|
|
18
20
|
import {
|
|
19
21
|
CachedBeaconStateAllForks,
|
|
@@ -45,6 +47,7 @@ import {
|
|
|
45
47
|
Wei,
|
|
46
48
|
bellatrix,
|
|
47
49
|
getValidatorStatus,
|
|
50
|
+
gloas,
|
|
48
51
|
phase0,
|
|
49
52
|
ssz,
|
|
50
53
|
} from "@lodestar/types";
|
|
@@ -69,7 +72,7 @@ import {
|
|
|
69
72
|
} from "../../../chain/errors/index.js";
|
|
70
73
|
import {ChainEvent, CommonBlockBody} from "../../../chain/index.js";
|
|
71
74
|
import {PREPARE_NEXT_SLOT_BPS} from "../../../chain/prepareNextSlot.js";
|
|
72
|
-
import {BlockType, ProduceFullDeneb} from "../../../chain/produceBlock/index.js";
|
|
75
|
+
import {BlockType, ProduceFullDeneb, ProduceFullGloas} from "../../../chain/produceBlock/index.js";
|
|
73
76
|
import {RegenCaller} from "../../../chain/regen/index.js";
|
|
74
77
|
import {CheckpointHex} from "../../../chain/stateCache/types.js";
|
|
75
78
|
import {validateApiAggregateAndProof} from "../../../chain/validation/index.js";
|
|
@@ -901,6 +904,77 @@ export function getValidatorApi(
|
|
|
901
904
|
return {data, meta};
|
|
902
905
|
},
|
|
903
906
|
|
|
907
|
+
async produceBlockV4({slot, randaoReveal, graffiti, feeRecipient}) {
|
|
908
|
+
const fork = config.getForkName(slot);
|
|
909
|
+
|
|
910
|
+
if (!isForkPostGloas(fork)) {
|
|
911
|
+
throw new ApiError(400, `produceBlockV4 not supported for pre-gloas fork=${fork}`);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
notWhileSyncing();
|
|
915
|
+
await waitForSlot(slot);
|
|
916
|
+
|
|
917
|
+
// TODO GLOAS: support producing blocks from builder bids
|
|
918
|
+
const source = ProducedBlockSource.engine;
|
|
919
|
+
|
|
920
|
+
// TODO GLOAS: needs to be updated after fork choice changes are merged
|
|
921
|
+
const parentBlock = chain.getProposerHead(slot);
|
|
922
|
+
const {blockRoot: parentBlockRootHex, slot: parentSlot} = parentBlock;
|
|
923
|
+
const parentBlockRoot = fromHex(parentBlockRootHex);
|
|
924
|
+
notOnOutOfRangeData(parentBlockRoot);
|
|
925
|
+
metrics?.blockProductionSlotDelta.set(slot - parentSlot);
|
|
926
|
+
metrics?.blockProductionRequests.inc({source});
|
|
927
|
+
|
|
928
|
+
const graffitiBytes = toGraffitiBytes(
|
|
929
|
+
graffiti ?? getDefaultGraffiti(getLodestarClientVersion(), chain.executionEngine.clientVersion, {})
|
|
930
|
+
);
|
|
931
|
+
const commonBlockBodyPromise = chain.produceCommonBlockBody({
|
|
932
|
+
slot,
|
|
933
|
+
parentBlock,
|
|
934
|
+
randaoReveal,
|
|
935
|
+
graffiti: graffitiBytes,
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
let timer: undefined | ((opts: {source: ProducedBlockSource}) => number);
|
|
939
|
+
try {
|
|
940
|
+
timer = metrics?.blockProductionTime.startTimer();
|
|
941
|
+
const {block, executionPayloadValue, consensusBlockValue} = await chain.produceBlock({
|
|
942
|
+
slot,
|
|
943
|
+
parentBlock,
|
|
944
|
+
randaoReveal,
|
|
945
|
+
graffiti: graffitiBytes,
|
|
946
|
+
feeRecipient,
|
|
947
|
+
commonBlockBodyPromise,
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
metrics?.blockProductionSuccess.inc({source});
|
|
951
|
+
metrics?.blockProductionNumAggregated.observe({source}, block.body.attestations.length);
|
|
952
|
+
metrics?.blockProductionConsensusBlockValue.observe({source}, Number(formatWeiToEth(consensusBlockValue)));
|
|
953
|
+
metrics?.blockProductionExecutionPayloadValue.observe({source}, Number(formatWeiToEth(executionPayloadValue)));
|
|
954
|
+
|
|
955
|
+
const blockRoot = toRootHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block));
|
|
956
|
+
logger.verbose("Produced block", {
|
|
957
|
+
slot,
|
|
958
|
+
executionPayloadValue,
|
|
959
|
+
consensusBlockValue,
|
|
960
|
+
root: blockRoot,
|
|
961
|
+
});
|
|
962
|
+
if (chain.opts.persistProducedBlocks) {
|
|
963
|
+
void chain.persistBlock(block, "produced_engine_block");
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
return {
|
|
967
|
+
data: block as gloas.BeaconBlock,
|
|
968
|
+
meta: {
|
|
969
|
+
version: fork,
|
|
970
|
+
consensusBlockValue,
|
|
971
|
+
},
|
|
972
|
+
};
|
|
973
|
+
} finally {
|
|
974
|
+
timer?.({source});
|
|
975
|
+
}
|
|
976
|
+
},
|
|
977
|
+
|
|
904
978
|
async produceAttestationData({committeeIndex, slot}) {
|
|
905
979
|
notWhileSyncing();
|
|
906
980
|
|
|
@@ -1532,5 +1606,54 @@ export function getValidatorApi(
|
|
|
1532
1606
|
count: filteredRegistrations.length,
|
|
1533
1607
|
});
|
|
1534
1608
|
},
|
|
1609
|
+
|
|
1610
|
+
async getExecutionPayloadEnvelope({slot, beaconBlockRoot}) {
|
|
1611
|
+
const fork = config.getForkName(slot);
|
|
1612
|
+
|
|
1613
|
+
if (!isForkPostGloas(fork)) {
|
|
1614
|
+
throw new ApiError(400, `getExecutionPayloadEnvelope not supported for pre-gloas fork=${fork}`);
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
notWhileSyncing();
|
|
1618
|
+
await waitForSlot(slot);
|
|
1619
|
+
|
|
1620
|
+
const blockRootHex = toRootHex(beaconBlockRoot);
|
|
1621
|
+
const produceResult = chain.blockProductionCache.get(blockRootHex);
|
|
1622
|
+
|
|
1623
|
+
if (produceResult === undefined) {
|
|
1624
|
+
throw new ApiError(404, `No cached block production result found for block root ${blockRootHex}`);
|
|
1625
|
+
}
|
|
1626
|
+
if (!isForkPostGloas(produceResult.fork)) {
|
|
1627
|
+
throw Error(`Cached block production result is for pre-gloas fork=${produceResult.fork}`);
|
|
1628
|
+
}
|
|
1629
|
+
if (produceResult.type !== BlockType.Full) {
|
|
1630
|
+
throw Error("Cached block production result is not full block");
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
const {executionPayload, executionRequests, envelopeStateRoot} = produceResult as ProduceFullGloas;
|
|
1634
|
+
|
|
1635
|
+
const envelope: gloas.ExecutionPayloadEnvelope = {
|
|
1636
|
+
payload: executionPayload,
|
|
1637
|
+
executionRequests: executionRequests,
|
|
1638
|
+
builderIndex: BUILDER_INDEX_SELF_BUILD,
|
|
1639
|
+
beaconBlockRoot,
|
|
1640
|
+
slot,
|
|
1641
|
+
stateRoot: envelopeStateRoot,
|
|
1642
|
+
};
|
|
1643
|
+
|
|
1644
|
+
logger.info("Produced execution payload envelope", {
|
|
1645
|
+
slot,
|
|
1646
|
+
blockRoot: blockRootHex,
|
|
1647
|
+
transactions: executionPayload.transactions.length,
|
|
1648
|
+
blockHash: toRootHex(executionPayload.blockHash),
|
|
1649
|
+
});
|
|
1650
|
+
|
|
1651
|
+
return {
|
|
1652
|
+
data: envelope,
|
|
1653
|
+
meta: {
|
|
1654
|
+
version: fork,
|
|
1655
|
+
},
|
|
1656
|
+
};
|
|
1657
|
+
},
|
|
1535
1658
|
};
|
|
1536
1659
|
}
|
|
@@ -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
|
+
}
|
|
@@ -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)) {
|
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,
|
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;
|