@lodestar/beacon-node 1.41.0 → 1.42.0-dev.4118b5b440
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 +35 -16
- 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 +6 -2
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +0 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +0 -9
- 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 +4 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +38 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +4 -3
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/types.js +1 -0
- package/lib/chain/blocks/blockInput/types.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +29 -9
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +48 -0
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -0
- package/lib/chain/blocks/importExecutionPayload.js +159 -0
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.js +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +80 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +248 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +29 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.js +11 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +15 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +46 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -0
- package/lib/chain/blocks/types.d.ts +7 -0
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +12 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +40 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -0
- package/lib/chain/chain.d.ts +10 -5
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +44 -10
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +12 -2
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +3 -1
- 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 +0 -10
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +8 -5
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +1 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +6 -2
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +6 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +11 -1
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +2 -0
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +14 -6
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +2 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +11 -6
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +40 -8
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +5 -0
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +33 -6
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/index.d.ts +1 -1
- package/lib/chain/seenCache/index.d.ts.map +1 -1
- package/lib/chain/seenCache/index.js +1 -1
- package/lib/chain/seenCache/index.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +38 -0
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -0
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +76 -0
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -0
- package/lib/chain/stateCache/datastore/db.d.ts +4 -5
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +32 -10
- 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 +7 -4
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +8 -3
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +33 -14
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +217 -119
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +15 -8
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +30 -19
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.js +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.js +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
- package/lib/chain/validation/syncCommittee.d.ts +2 -2
- package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/syncCommittee.js +12 -11
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +2 -2
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +2 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +4 -1
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +2 -2
- package/lib/metrics/metrics/lodestar.d.ts +40 -4
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +93 -15
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +15 -0
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/interface.d.ts +1 -1
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +4 -4
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
- package/lib/network/processor/extractSlotRootFns.js +15 -5
- package/lib/network/processor/extractSlotRootFns.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +39 -9
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +12 -7
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +99 -78
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.d.ts +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
- package/lib/sync/backfill/backfill.d.ts +1 -1
- package/lib/sync/backfill/backfill.js +1 -1
- package/lib/sync/constants.d.ts +1 -1
- package/lib/sync/constants.js +1 -1
- package/lib/sync/unknownBlock.d.ts +3 -9
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +8 -41
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/util/sszBytes.d.ts +4 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +69 -12
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +36 -17
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/validator/index.ts +8 -4
- package/src/chain/archiveStore/archiveStore.ts +0 -10
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +8 -5
- package/src/chain/archiveStore/utils/archiveBlocks.ts +59 -1
- package/src/chain/blocks/blockInput/types.ts +4 -3
- package/src/chain/blocks/importBlock.ts +47 -8
- package/src/chain/blocks/importExecutionPayload.ts +241 -0
- package/src/chain/blocks/payloadEnvelopeInput/index.ts +2 -0
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +336 -0
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +33 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +61 -0
- package/src/chain/blocks/types.ts +8 -0
- package/src/chain/blocks/verifyBlocksSignatures.ts +1 -1
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +55 -0
- package/src/chain/chain.ts +60 -15
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -2
- package/src/chain/forkChoice/index.ts +0 -10
- package/src/chain/interface.ts +8 -5
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/prepareNextSlot.ts +6 -2
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -1
- package/src/chain/produceBlock/produceBlockBody.ts +1 -1
- package/src/chain/regen/errors.ts +6 -1
- package/src/chain/regen/interface.ts +14 -6
- package/src/chain/regen/queued.ts +48 -12
- package/src/chain/regen/regen.ts +37 -7
- package/src/chain/seenCache/index.ts +1 -1
- package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +106 -0
- package/src/chain/stateCache/datastore/db.ts +33 -10
- package/src/chain/stateCache/datastore/file.ts +6 -5
- package/src/chain/stateCache/datastore/types.ts +3 -2
- package/src/chain/stateCache/fifoBlockStateCache.ts +10 -4
- package/src/chain/stateCache/persistentCheckpointsCache.ts +248 -139
- package/src/chain/stateCache/types.ts +18 -8
- package/src/chain/validation/executionPayloadEnvelope.ts +38 -25
- package/src/chain/validation/lightClientFinalityUpdate.ts +1 -1
- package/src/chain/validation/lightClientOptimisticUpdate.ts +1 -1
- package/src/chain/validation/syncCommittee.ts +15 -14
- package/src/chain/validation/voluntaryExit.ts +2 -1
- package/src/chain/validatorMonitor.ts +11 -1
- package/src/execution/engine/interface.ts +2 -2
- package/src/metrics/metrics/lodestar.ts +100 -19
- package/src/network/gossip/encoding.ts +16 -0
- package/src/network/interface.ts +1 -1
- package/src/network/network.ts +4 -4
- package/src/network/processor/extractSlotRootFns.ts +19 -6
- package/src/network/processor/gossipHandlers.ts +45 -8
- package/src/network/processor/index.ts +110 -89
- package/src/network/reqresp/ReqRespBeaconNode.ts +1 -1
- package/src/sync/backfill/backfill.ts +1 -1
- package/src/sync/constants.ts +1 -1
- package/src/sync/unknownBlock.ts +10 -50
- package/src/util/sszBytes.ts +90 -10
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts +0 -7
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts.map +0 -1
- package/lib/chain/archiveStore/utils/archivePayloads.js +0 -10
- package/lib/chain/archiveStore/utils/archivePayloads.js.map +0 -1
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts +0 -15
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts.map +0 -1
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js +0 -28
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js.map +0 -1
- package/src/chain/archiveStore/utils/archivePayloads.ts +0 -15
- package/src/chain/seenCache/seenExecutionPayloadEnvelope.ts +0 -34
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import {NUMBER_OF_COLUMNS} from "@lodestar/params";
|
|
2
|
+
import {ColumnIndex, DataColumnSidecars, RootHex, Slot, ValidatorIndex, deneb, gloas} from "@lodestar/types";
|
|
3
|
+
import {toRootHex, withTimeout} from "@lodestar/utils";
|
|
4
|
+
import {VersionedHashes} from "../../../execution/index.js";
|
|
5
|
+
import {kzgCommitmentToVersionedHash} from "../../../util/blobs.js";
|
|
6
|
+
import {AddPayloadEnvelopeProps, ColumnWithSource, CreateFromBlockProps, SourceMeta} from "./types.js";
|
|
7
|
+
|
|
8
|
+
export type PayloadEnvelopeInputState =
|
|
9
|
+
| {
|
|
10
|
+
hasPayload: false;
|
|
11
|
+
hasAllData: false;
|
|
12
|
+
hasComputedAllData: false;
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
hasPayload: false;
|
|
16
|
+
hasAllData: true;
|
|
17
|
+
hasComputedAllData: boolean;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
hasPayload: true;
|
|
21
|
+
hasAllData: false;
|
|
22
|
+
hasComputedAllData: false;
|
|
23
|
+
payloadEnvelope: gloas.SignedExecutionPayloadEnvelope;
|
|
24
|
+
payloadEnvelopeSource: SourceMeta;
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
hasPayload: true;
|
|
28
|
+
hasAllData: true;
|
|
29
|
+
hasComputedAllData: boolean;
|
|
30
|
+
payloadEnvelope: gloas.SignedExecutionPayloadEnvelope;
|
|
31
|
+
payloadEnvelopeSource: SourceMeta;
|
|
32
|
+
timeCompleteSec: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type PromiseParts<T> = {
|
|
36
|
+
promise: Promise<T>;
|
|
37
|
+
resolve: (value: T) => void;
|
|
38
|
+
reject: (e: Error) => void;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function createPromise<T>(): PromiseParts<T> {
|
|
42
|
+
let resolve!: (value: T) => void;
|
|
43
|
+
let reject!: (e: Error) => void;
|
|
44
|
+
const promise = new Promise<T>((_resolve, _reject) => {
|
|
45
|
+
resolve = _resolve;
|
|
46
|
+
reject = _reject;
|
|
47
|
+
});
|
|
48
|
+
return {promise, resolve, reject};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Tracks bid + payload envelope + data columns for a Gloas block.
|
|
53
|
+
*
|
|
54
|
+
* Created during block import from signedExecutionPayloadBid in block body.
|
|
55
|
+
* Always has bid (required for creation).
|
|
56
|
+
*
|
|
57
|
+
* Completion requires: payload envelope + all sampled columns
|
|
58
|
+
*/
|
|
59
|
+
export class PayloadEnvelopeInput {
|
|
60
|
+
readonly blockRootHex: RootHex;
|
|
61
|
+
readonly slot: Slot;
|
|
62
|
+
readonly proposerIndex: ValidatorIndex;
|
|
63
|
+
readonly bid: gloas.ExecutionPayloadBid;
|
|
64
|
+
readonly versionedHashes: VersionedHashes;
|
|
65
|
+
|
|
66
|
+
private columnsCache = new Map<ColumnIndex, ColumnWithSource>();
|
|
67
|
+
|
|
68
|
+
private readonly sampledColumns: ColumnIndex[];
|
|
69
|
+
private readonly custodyColumns: ColumnIndex[];
|
|
70
|
+
|
|
71
|
+
private timeCreatedSec: number;
|
|
72
|
+
|
|
73
|
+
private readonly payloadEnvelopeDataPromise: PromiseParts<gloas.SignedExecutionPayloadEnvelope>;
|
|
74
|
+
private readonly columnsDataPromise: PromiseParts<DataColumnSidecars>;
|
|
75
|
+
|
|
76
|
+
state: PayloadEnvelopeInputState;
|
|
77
|
+
|
|
78
|
+
private constructor(props: {
|
|
79
|
+
blockRootHex: RootHex;
|
|
80
|
+
slot: Slot;
|
|
81
|
+
proposerIndex: ValidatorIndex;
|
|
82
|
+
bid: gloas.ExecutionPayloadBid;
|
|
83
|
+
sampledColumns: ColumnIndex[];
|
|
84
|
+
custodyColumns: ColumnIndex[];
|
|
85
|
+
timeCreatedSec: number;
|
|
86
|
+
}) {
|
|
87
|
+
this.blockRootHex = props.blockRootHex;
|
|
88
|
+
this.slot = props.slot;
|
|
89
|
+
this.proposerIndex = props.proposerIndex;
|
|
90
|
+
this.bid = props.bid;
|
|
91
|
+
this.versionedHashes = props.bid.blobKzgCommitments.map(kzgCommitmentToVersionedHash);
|
|
92
|
+
this.sampledColumns = props.sampledColumns;
|
|
93
|
+
this.custodyColumns = props.custodyColumns;
|
|
94
|
+
this.timeCreatedSec = props.timeCreatedSec;
|
|
95
|
+
this.payloadEnvelopeDataPromise = createPromise();
|
|
96
|
+
this.columnsDataPromise = createPromise();
|
|
97
|
+
|
|
98
|
+
const noBlobs = props.bid.blobKzgCommitments.length === 0;
|
|
99
|
+
const noSampledColumns = props.sampledColumns.length === 0;
|
|
100
|
+
const hasAllData = noBlobs || noSampledColumns;
|
|
101
|
+
|
|
102
|
+
if (hasAllData) {
|
|
103
|
+
this.state = {hasPayload: false, hasAllData: true, hasComputedAllData: true};
|
|
104
|
+
this.columnsDataPromise.resolve(this.getSampledColumns());
|
|
105
|
+
} else {
|
|
106
|
+
this.state = {hasPayload: false, hasAllData: false, hasComputedAllData: false};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static createFromBlock(props: CreateFromBlockProps): PayloadEnvelopeInput {
|
|
111
|
+
const bid = (props.block.message.body as gloas.BeaconBlockBody).signedExecutionPayloadBid.message;
|
|
112
|
+
return new PayloadEnvelopeInput({
|
|
113
|
+
blockRootHex: props.blockRootHex,
|
|
114
|
+
slot: props.block.message.slot,
|
|
115
|
+
proposerIndex: props.block.message.proposerIndex,
|
|
116
|
+
bid,
|
|
117
|
+
sampledColumns: props.sampledColumns,
|
|
118
|
+
custodyColumns: props.custodyColumns,
|
|
119
|
+
timeCreatedSec: props.timeCreatedSec,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getBid(): gloas.ExecutionPayloadBid {
|
|
124
|
+
return this.bid;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getBuilderIndex(): ValidatorIndex {
|
|
128
|
+
return this.bid.builderIndex;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
getBlockHashHex(): RootHex {
|
|
132
|
+
return toRootHex(this.bid.blockHash);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
getBlobKzgCommitments(): deneb.BlobKzgCommitments {
|
|
136
|
+
return this.bid.blobKzgCommitments;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
addPayloadEnvelope(props: AddPayloadEnvelopeProps): void {
|
|
140
|
+
if (this.state.hasPayload) {
|
|
141
|
+
throw new Error(`Payload envelope already set for block ${this.blockRootHex}`);
|
|
142
|
+
}
|
|
143
|
+
if (toRootHex(props.envelope.message.beaconBlockRoot) !== this.blockRootHex) {
|
|
144
|
+
throw new Error("Payload envelope beacon_block_root mismatch");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const source: SourceMeta = {
|
|
148
|
+
source: props.source,
|
|
149
|
+
seenTimestampSec: props.seenTimestampSec,
|
|
150
|
+
peerIdStr: props.peerIdStr,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
if (this.state.hasAllData) {
|
|
154
|
+
// Complete state
|
|
155
|
+
this.state = {
|
|
156
|
+
hasPayload: true,
|
|
157
|
+
hasAllData: true,
|
|
158
|
+
hasComputedAllData: this.state.hasComputedAllData,
|
|
159
|
+
payloadEnvelope: props.envelope,
|
|
160
|
+
payloadEnvelopeSource: source,
|
|
161
|
+
timeCompleteSec: props.seenTimestampSec,
|
|
162
|
+
};
|
|
163
|
+
this.payloadEnvelopeDataPromise.resolve(props.envelope);
|
|
164
|
+
} else {
|
|
165
|
+
// Has payload, waiting for columns
|
|
166
|
+
this.state = {
|
|
167
|
+
hasPayload: true,
|
|
168
|
+
hasAllData: false,
|
|
169
|
+
hasComputedAllData: false,
|
|
170
|
+
payloadEnvelope: props.envelope,
|
|
171
|
+
payloadEnvelopeSource: source,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
addColumn(columnWithSource: ColumnWithSource): void {
|
|
177
|
+
const {columnSidecar, seenTimestampSec} = columnWithSource;
|
|
178
|
+
this.columnsCache.set(columnSidecar.index, columnWithSource);
|
|
179
|
+
|
|
180
|
+
const sampledColumns = this.getSampledColumns();
|
|
181
|
+
const hasAllData =
|
|
182
|
+
// already hasAllData
|
|
183
|
+
this.state.hasAllData ||
|
|
184
|
+
// has all sampled columns
|
|
185
|
+
sampledColumns.length === this.sampledColumns.length ||
|
|
186
|
+
// has enough columns to reconstruct the rest
|
|
187
|
+
this.columnsCache.size >= NUMBER_OF_COLUMNS / 2;
|
|
188
|
+
|
|
189
|
+
const hasComputedAllData =
|
|
190
|
+
// has all sampled columns
|
|
191
|
+
sampledColumns.length === this.sampledColumns.length;
|
|
192
|
+
|
|
193
|
+
if (!hasAllData) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (hasComputedAllData) {
|
|
198
|
+
this.columnsDataPromise.resolve(sampledColumns);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (this.state.hasPayload) {
|
|
202
|
+
// Complete state
|
|
203
|
+
this.state = {
|
|
204
|
+
hasPayload: true,
|
|
205
|
+
hasAllData: true,
|
|
206
|
+
hasComputedAllData: hasComputedAllData || this.state.hasComputedAllData,
|
|
207
|
+
payloadEnvelope: this.state.payloadEnvelope,
|
|
208
|
+
payloadEnvelopeSource: this.state.payloadEnvelopeSource,
|
|
209
|
+
timeCompleteSec: seenTimestampSec,
|
|
210
|
+
};
|
|
211
|
+
this.payloadEnvelopeDataPromise.resolve(this.state.payloadEnvelope);
|
|
212
|
+
} else {
|
|
213
|
+
// No payload yet, all data ready
|
|
214
|
+
this.state = {
|
|
215
|
+
hasPayload: false,
|
|
216
|
+
hasAllData: true,
|
|
217
|
+
hasComputedAllData: hasComputedAllData || this.state.hasComputedAllData,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
getVersionedHashes(): VersionedHashes {
|
|
223
|
+
return this.versionedHashes;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
hasPayloadEnvelope(): boolean {
|
|
227
|
+
return this.state.hasPayload;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
getPayloadEnvelope(): gloas.SignedExecutionPayloadEnvelope {
|
|
231
|
+
if (!this.state.hasPayload) throw new Error("Payload envelope not set");
|
|
232
|
+
return this.state.payloadEnvelope;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
getPayloadEnvelopeSource(): SourceMeta {
|
|
236
|
+
if (!this.state.hasPayload) throw new Error("Payload envelope source not set");
|
|
237
|
+
return this.state.payloadEnvelopeSource;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
getSampledColumns(): gloas.DataColumnSidecars {
|
|
241
|
+
const columns: gloas.DataColumnSidecars = [];
|
|
242
|
+
for (const index of this.sampledColumns) {
|
|
243
|
+
const column = this.columnsCache.get(index);
|
|
244
|
+
if (column) {
|
|
245
|
+
columns.push(column.columnSidecar);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return columns;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
getSampledColumnsWithSource(): ColumnWithSource[] {
|
|
252
|
+
const columns: ColumnWithSource[] = [];
|
|
253
|
+
for (const index of this.sampledColumns) {
|
|
254
|
+
const column = this.columnsCache.get(index);
|
|
255
|
+
if (column) {
|
|
256
|
+
columns.push(column);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return columns;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
getCustodyColumns(): gloas.DataColumnSidecars {
|
|
263
|
+
const columns: gloas.DataColumnSidecars = [];
|
|
264
|
+
for (const index of this.custodyColumns) {
|
|
265
|
+
const column = this.columnsCache.get(index);
|
|
266
|
+
if (column) {
|
|
267
|
+
columns.push(column.columnSidecar);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return columns;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
hasComputedAllData(): boolean {
|
|
274
|
+
return this.state.hasComputedAllData;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<DataColumnSidecars> {
|
|
278
|
+
if (this.state.hasComputedAllData) {
|
|
279
|
+
return Promise.resolve(this.getSampledColumns());
|
|
280
|
+
}
|
|
281
|
+
return withTimeout(() => this.columnsDataPromise.promise, timeout, signal);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
getTimeCreated(): number {
|
|
285
|
+
return this.timeCreatedSec;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
getTimeComplete(): number {
|
|
289
|
+
if (!this.state.hasPayload || !this.state.hasAllData) throw new Error("Not yet complete");
|
|
290
|
+
return this.state.timeCompleteSec;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
isComplete(): boolean {
|
|
294
|
+
return this.state.hasPayload && this.state.hasAllData;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async waitForData(): Promise<gloas.SignedExecutionPayloadEnvelope> {
|
|
298
|
+
return this.payloadEnvelopeDataPromise.promise;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
getSerializedCacheKeys(): object[] {
|
|
302
|
+
const objects: object[] = [];
|
|
303
|
+
|
|
304
|
+
if (this.state.hasPayload) {
|
|
305
|
+
objects.push(this.state.payloadEnvelope);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
for (const {columnSidecar} of this.columnsCache.values()) {
|
|
309
|
+
objects.push(columnSidecar);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return objects;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
getLogMeta(): {
|
|
316
|
+
slot: number;
|
|
317
|
+
blockRoot: string;
|
|
318
|
+
hasPayload: boolean;
|
|
319
|
+
hasAllData: boolean;
|
|
320
|
+
hasComputedAllData: boolean;
|
|
321
|
+
isComplete: boolean;
|
|
322
|
+
columnsCount: number;
|
|
323
|
+
sampledColumnsCount: number;
|
|
324
|
+
} {
|
|
325
|
+
return {
|
|
326
|
+
slot: this.slot,
|
|
327
|
+
blockRoot: this.blockRootHex,
|
|
328
|
+
hasPayload: this.state.hasPayload,
|
|
329
|
+
hasAllData: this.state.hasAllData,
|
|
330
|
+
hasComputedAllData: this.state.hasComputedAllData,
|
|
331
|
+
isComplete: this.isComplete(),
|
|
332
|
+
columnsCount: this.columnsCache.size,
|
|
333
|
+
sampledColumnsCount: this.sampledColumns.length,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {ForkPostGloas} from "@lodestar/params";
|
|
2
|
+
import {ColumnIndex, RootHex, SignedBeaconBlock, gloas} from "@lodestar/types";
|
|
3
|
+
|
|
4
|
+
export enum PayloadEnvelopeInputSource {
|
|
5
|
+
gossip = "gossip",
|
|
6
|
+
api = "api",
|
|
7
|
+
engine = "engine",
|
|
8
|
+
byRange = "req_resp_by_range",
|
|
9
|
+
byRoot = "req_resp_by_root",
|
|
10
|
+
recovery = "recovery",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type SourceMeta = {
|
|
14
|
+
source: PayloadEnvelopeInputSource;
|
|
15
|
+
seenTimestampSec: number;
|
|
16
|
+
peerIdStr?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type ColumnWithSource = SourceMeta & {
|
|
20
|
+
columnSidecar: gloas.DataColumnSidecar;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type CreateFromBlockProps = {
|
|
24
|
+
blockRootHex: RootHex;
|
|
25
|
+
block: SignedBeaconBlock<ForkPostGloas>;
|
|
26
|
+
sampledColumns: ColumnIndex[];
|
|
27
|
+
custodyColumns: ColumnIndex[];
|
|
28
|
+
timeCreatedSec: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type AddPayloadEnvelopeProps = SourceMeta & {
|
|
32
|
+
envelope: gloas.SignedExecutionPayloadEnvelope;
|
|
33
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {Metrics} from "../../metrics/metrics.js";
|
|
2
|
+
import {JobItemQueue} from "../../util/queue/index.js";
|
|
3
|
+
import type {BeaconChain} from "../chain.js";
|
|
4
|
+
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
5
|
+
import {importExecutionPayload} from "./importExecutionPayload.js";
|
|
6
|
+
import {ImportPayloadOpts} from "./types.js";
|
|
7
|
+
|
|
8
|
+
// TODO GLOAS: Set to be equal to DEFAULT_MAX_PENDING_UNFINALIZED_PAYLOAD_ENVELOPE_WRITES for now
|
|
9
|
+
const QUEUE_MAX_LENGTH = 16;
|
|
10
|
+
|
|
11
|
+
enum PayloadEnvelopeImportStatus {
|
|
12
|
+
queued = "queued",
|
|
13
|
+
importing = "importing",
|
|
14
|
+
imported = "imported",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* PayloadEnvelopeProcessor processes payload envelope jobs in a queued fashion, one after the other.
|
|
19
|
+
*/
|
|
20
|
+
export class PayloadEnvelopeProcessor {
|
|
21
|
+
readonly jobQueue: JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>;
|
|
22
|
+
private readonly importStatus = new WeakMap<PayloadEnvelopeInput, PayloadEnvelopeImportStatus>();
|
|
23
|
+
|
|
24
|
+
constructor(chain: BeaconChain, metrics: Metrics | null, signal: AbortSignal) {
|
|
25
|
+
this.jobQueue = new JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>(
|
|
26
|
+
(payloadInput, opts) => {
|
|
27
|
+
this.importStatus.set(payloadInput, PayloadEnvelopeImportStatus.importing);
|
|
28
|
+
return importExecutionPayload.call(chain, payloadInput, opts);
|
|
29
|
+
},
|
|
30
|
+
{maxLength: QUEUE_MAX_LENGTH, noYieldIfOneItem: true, signal},
|
|
31
|
+
metrics?.payloadEnvelopeProcessorQueue ?? undefined
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async processPayloadEnvelopeJob(payloadInput: PayloadEnvelopeInput, opts: ImportPayloadOpts = {}): Promise<void> {
|
|
36
|
+
if (!payloadInput.isComplete()) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (this.importStatus.get(payloadInput) !== undefined) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
await this.jobQueue.waitForSpace();
|
|
45
|
+
|
|
46
|
+
// Re-check after await, as another call may have queued this payload.
|
|
47
|
+
if (this.importStatus.get(payloadInput) !== undefined) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.importStatus.set(payloadInput, PayloadEnvelopeImportStatus.queued);
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
await this.jobQueue.push(payloadInput, opts);
|
|
55
|
+
this.importStatus.set(payloadInput, PayloadEnvelopeImportStatus.imported);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
this.importStatus.delete(payloadInput);
|
|
58
|
+
throw e;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -41,6 +41,14 @@ export enum BlobSidecarValidation {
|
|
|
41
41
|
Full,
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
export type ImportPayloadOpts = {
|
|
45
|
+
/**
|
|
46
|
+
* Set to true if envelope signature was already verified (e.g., during gossip/API validation).
|
|
47
|
+
* When false/undefined, signature will be verified during import.
|
|
48
|
+
*/
|
|
49
|
+
validSignature?: boolean;
|
|
50
|
+
};
|
|
51
|
+
|
|
44
52
|
export type ImportBlockOpts = {
|
|
45
53
|
/**
|
|
46
54
|
* TEMP: Review if this is safe, Lighthouse always imports attestations even in finalized sync.
|
|
@@ -41,7 +41,7 @@ export async function verifyBlocksSignatures(
|
|
|
41
41
|
: //
|
|
42
42
|
// Verify signatures per block to track which block is invalid
|
|
43
43
|
bls.verifySignatureSets(
|
|
44
|
-
getBlockSignatureSets(config, currentSyncCommitteeIndexed, block, indexedAttestationsByBlock[i], {
|
|
44
|
+
getBlockSignatureSets(config, currentSyncCommitteeIndexed, preState0, block, indexedAttestationsByBlock[i], {
|
|
45
45
|
skipProposerSignature: opts.validProposerSignature,
|
|
46
46
|
})
|
|
47
47
|
);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {BeaconChain} from "../chain.js";
|
|
2
|
+
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
3
|
+
import {writeDataColumnsToDb} from "./writeBlockInputToDb.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Persists payload envelope data to DB. This operation must be eventually completed if a payload is imported.
|
|
7
|
+
*
|
|
8
|
+
* TODO GLOAS: Persist envelope metadata (stateRoot, executionRequests, builderIndex, etc.) without the full
|
|
9
|
+
* execution payload body — only keep the blockHash reference. The EL already stores the payload.
|
|
10
|
+
* See https://github.com/ChainSafe/lodestar/issues/5671
|
|
11
|
+
*/
|
|
12
|
+
export async function writePayloadEnvelopeInputToDb(
|
|
13
|
+
this: BeaconChain,
|
|
14
|
+
payloadInput: PayloadEnvelopeInput
|
|
15
|
+
): Promise<void> {
|
|
16
|
+
const envelope = payloadInput.getPayloadEnvelope();
|
|
17
|
+
const blockRootHex = payloadInput.blockRootHex;
|
|
18
|
+
|
|
19
|
+
const envelopeBytes = this.serializedCache.get(envelope);
|
|
20
|
+
const envelopePromise = envelopeBytes
|
|
21
|
+
? this.db.executionPayloadEnvelope.putBinary(this.db.executionPayloadEnvelope.getId(envelope), envelopeBytes)
|
|
22
|
+
: this.db.executionPayloadEnvelope.add(envelope);
|
|
23
|
+
|
|
24
|
+
// Write envelope and data columns in parallel (reuses shared column writing logic)
|
|
25
|
+
await Promise.all([envelopePromise, writeDataColumnsToDb.call(this, payloadInput)]);
|
|
26
|
+
this.logger.debug("Persisted payload envelope to db", {
|
|
27
|
+
slot: payloadInput.slot,
|
|
28
|
+
root: blockRootHex,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function persistPayloadEnvelopeInput(
|
|
33
|
+
this: BeaconChain,
|
|
34
|
+
payloadInput: PayloadEnvelopeInput
|
|
35
|
+
): Promise<void> {
|
|
36
|
+
await writePayloadEnvelopeInputToDb
|
|
37
|
+
.call(this, payloadInput)
|
|
38
|
+
.catch((e) => {
|
|
39
|
+
this.logger.error(
|
|
40
|
+
"Error persisting payload envelope in hot db",
|
|
41
|
+
{
|
|
42
|
+
slot: payloadInput.slot,
|
|
43
|
+
root: payloadInput.blockRootHex,
|
|
44
|
+
},
|
|
45
|
+
e
|
|
46
|
+
);
|
|
47
|
+
})
|
|
48
|
+
.finally(() => {
|
|
49
|
+
this.seenPayloadEnvelopeInputCache.prune(payloadInput.blockRootHex);
|
|
50
|
+
this.logger.debug("Pruned payload envelope input", {
|
|
51
|
+
slot: payloadInput.slot,
|
|
52
|
+
root: payloadInput.blockRootHex,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|