@lodestar/beacon-node 1.48.0-dev.e9c9b8835d → 1.48.0-dev.fd70e5fc15
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 +4 -4
- package/lib/api/impl/beacon/blocks/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 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +0 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +1 -12
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +0 -2
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +1 -4
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +34 -31
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +2 -3
- 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 +16 -9
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -4
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +35 -60
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +2 -16
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +2 -15
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +0 -10
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +13 -13
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +4 -26
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +13 -38
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +0 -10
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/db/beacon.d.ts +5 -14
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +3 -17
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/index.d.ts +0 -1
- package/lib/db/index.d.ts.map +1 -1
- package/lib/db/interface.d.ts +1 -8
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.d.ts +1 -8
- package/lib/db/repositories/blockArchive.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +28 -65
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.js +7 -3
- package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +0 -18
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +1 -55
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/monitoring/clientStats.js +1 -1
- package/lib/monitoring/clientStats.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +6 -0
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +1 -2
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +20 -4
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +7 -6
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +3 -49
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +98 -232
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +91 -112
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +0 -2
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +22 -6
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +1 -2
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js +9 -14
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/lib/node/nodejs.d.ts +1 -2
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +2 -4
- package/lib/node/nodejs.js.map +1 -1
- package/lib/util/sszBytes.d.ts +0 -6
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +1 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +4 -8
- package/src/chain/archiveStore/archiveStore.ts +1 -6
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +0 -1
- package/src/chain/archiveStore/historicalState/metrics.ts +1 -14
- package/src/chain/archiveStore/historicalState/types.ts +0 -2
- package/src/chain/archiveStore/historicalState/worker.ts +1 -4
- package/src/chain/archiveStore/utils/archiveBlocks.ts +39 -34
- package/src/chain/blocks/index.ts +2 -13
- package/src/chain/blocks/writeBlockInputToDb.ts +17 -10
- package/src/chain/chain.ts +34 -75
- package/src/chain/errors/blockError.ts +8 -20
- package/src/chain/errors/dataColumnSidecarError.ts +8 -24
- package/src/chain/errors/executionPayloadEnvelope.ts +2 -14
- package/src/chain/interface.ts +2 -2
- package/src/chain/prepareNextSlot.ts +16 -16
- package/src/chain/validation/block.ts +4 -26
- package/src/chain/validation/dataColumnSidecar.ts +14 -47
- package/src/chain/validation/executionPayloadEnvelope.ts +0 -10
- package/src/db/beacon.ts +6 -33
- package/src/db/index.ts +0 -1
- package/src/db/interface.ts +1 -9
- package/src/db/repositories/blockArchive.ts +30 -89
- package/src/db/repositories/blockArchiveIndex.ts +9 -4
- package/src/metrics/metrics/lodestar.ts +1 -57
- package/src/monitoring/clientStats.ts +1 -1
- package/src/network/gossip/encoding.ts +6 -0
- package/src/network/gossip/topic.ts +25 -3
- package/src/network/processor/gossipHandlers.ts +11 -11
- package/src/network/processor/index.ts +148 -263
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +105 -139
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +0 -2
- package/src/network/reqresp/protocols.ts +24 -7
- package/src/network/reqresp/utils/dataColumnResponseValidation.ts +7 -15
- package/src/node/nodejs.ts +1 -6
- package/src/util/sszBytes.ts +1 -1
- package/lib/db/dataColumnStore.d.ts +0 -39
- package/lib/db/dataColumnStore.d.ts.map +0 -1
- package/lib/db/dataColumnStore.js +0 -81
- package/lib/db/dataColumnStore.js.map +0 -1
- package/lib/db/flatFileStore/atomicWrite.d.ts +0 -8
- package/lib/db/flatFileStore/atomicWrite.d.ts.map +0 -1
- package/lib/db/flatFileStore/atomicWrite.js +0 -61
- package/lib/db/flatFileStore/atomicWrite.js.map +0 -1
- package/lib/db/flatFileStore/dcolFormat.d.ts +0 -90
- package/lib/db/flatFileStore/dcolFormat.d.ts.map +0 -1
- package/lib/db/flatFileStore/dcolFormat.js +0 -286
- package/lib/db/flatFileStore/dcolFormat.js.map +0 -1
- package/lib/db/flatFileStore/errors.d.ts +0 -82
- package/lib/db/flatFileStore/errors.d.ts.map +0 -1
- package/lib/db/flatFileStore/errors.js +0 -32
- package/lib/db/flatFileStore/errors.js.map +0 -1
- package/lib/db/flatFileStore/flatFileStore.d.ts +0 -41
- package/lib/db/flatFileStore/flatFileStore.d.ts.map +0 -1
- package/lib/db/flatFileStore/flatFileStore.js +0 -251
- package/lib/db/flatFileStore/flatFileStore.js.map +0 -1
- package/lib/db/flatFileStore/index.d.ts +0 -4
- package/lib/db/flatFileStore/index.d.ts.map +0 -1
- package/lib/db/flatFileStore/index.js +0 -2
- package/lib/db/flatFileStore/index.js.map +0 -1
- package/lib/db/flatFileStore/interface.d.ts +0 -25
- package/lib/db/flatFileStore/interface.d.ts.map +0 -1
- package/lib/db/flatFileStore/interface.js +0 -2
- package/lib/db/flatFileStore/interface.js.map +0 -1
- package/lib/db/flatFileStore/metrics.d.ts +0 -24
- package/lib/db/flatFileStore/metrics.d.ts.map +0 -1
- package/lib/db/flatFileStore/metrics.js +0 -25
- package/lib/db/flatFileStore/metrics.js.map +0 -1
- package/lib/db/flatFileStore/path.d.ts +0 -9
- package/lib/db/flatFileStore/path.d.ts.map +0 -1
- package/lib/db/flatFileStore/path.js +0 -21
- package/lib/db/flatFileStore/path.js.map +0 -1
- package/lib/db/flatFileStore/slotIndex.d.ts +0 -14
- package/lib/db/flatFileStore/slotIndex.d.ts.map +0 -1
- package/lib/db/flatFileStore/slotIndex.js +0 -46
- package/lib/db/flatFileStore/slotIndex.js.map +0 -1
- package/lib/db/flatFileStore/snappy.d.ts +0 -3
- package/lib/db/flatFileStore/snappy.d.ts.map +0 -1
- package/lib/db/flatFileStore/snappy.js +0 -12
- package/lib/db/flatFileStore/snappy.js.map +0 -1
- package/src/db/dataColumnStore.ts +0 -113
- package/src/db/flatFileStore/atomicWrite.ts +0 -65
- package/src/db/flatFileStore/dcolFormat.ts +0 -389
- package/src/db/flatFileStore/errors.ts +0 -53
- package/src/db/flatFileStore/flatFileStore.ts +0 -310
- package/src/db/flatFileStore/index.ts +0 -3
- package/src/db/flatFileStore/interface.ts +0 -21
- package/src/db/flatFileStore/metrics.ts +0 -48
- package/src/db/flatFileStore/path.ts +0 -32
- package/src/db/flatFileStore/slotIndex.ts +0 -56
- package/src/db/flatFileStore/snappy.ts +0 -14
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {PeerId} from "@libp2p/interface";
|
|
2
2
|
import {ChainConfig} from "@lodestar/config";
|
|
3
3
|
import {PayloadStatus} from "@lodestar/fork-choice";
|
|
4
|
-
import {ForkSeq, GENESIS_SLOT
|
|
4
|
+
import {ForkSeq, GENESIS_SLOT} from "@lodestar/params";
|
|
5
5
|
import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
|
|
6
6
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
7
|
-
import {ColumnIndex, Epoch,
|
|
8
|
-
import {fromHex
|
|
7
|
+
import {ColumnIndex, Epoch, fulu} from "@lodestar/types";
|
|
8
|
+
import {fromHex} from "@lodestar/utils";
|
|
9
9
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
10
10
|
import {IBeaconDb} from "../../../db/index.js";
|
|
11
11
|
import {prettyPrintPeerId} from "../../util.js";
|
|
@@ -50,155 +50,121 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
50
50
|
);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
const finalized = db.dataColumnSidecarArchive;
|
|
53
54
|
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
|
|
54
|
-
//
|
|
55
|
-
//
|
|
55
|
+
// Columns of the last finalized block live in different DBs depending on fork:
|
|
56
|
+
// - Pre-gloas (fulu): migrated to dataColumnSidecarArchive in the same finalization run.
|
|
57
|
+
// - Post-gloas: stay in the hot db (db.dataColumnSidecar) until the next finalization run,
|
|
58
|
+
// because the migration filter requires payloadStatus === FULL for gloas blocks.
|
|
59
|
+
// archiveMaxSlot is the last slot whose columns are served by the archive loop below;
|
|
60
|
+
// anything above it is served by the headChain loop.
|
|
56
61
|
const isPostGloasFinalized = chain.config.getForkSeq(finalizedSlot) >= ForkSeq.gloas;
|
|
57
62
|
const archiveMaxSlot = isPostGloasFinalized ? finalizedSlot - 1 : finalizedSlot;
|
|
58
|
-
const headBlock = chain.forkChoice.getHead();
|
|
59
|
-
const headChain = chain.forkChoice.getAllAncestorBlocks(headBlock.blockRoot, headBlock.payloadStatus);
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
};
|
|
83
|
-
} else {
|
|
84
|
-
unavailableColumnIndices.push(availableColumns[i]);
|
|
64
|
+
// Finalized range of columns
|
|
65
|
+
if (startSlot <= archiveMaxSlot) {
|
|
66
|
+
const archiveEnd = Math.min(endSlot, archiveMaxSlot + 1);
|
|
67
|
+
for (let slot = startSlot; slot < archiveEnd; slot++) {
|
|
68
|
+
const dataColumnSidecars = await finalized.getManyBinary(slot, availableColumns);
|
|
69
|
+
|
|
70
|
+
const unavailableColumnIndices: ColumnIndex[] = [];
|
|
71
|
+
for (let i = 0; i < dataColumnSidecars.length; i++) {
|
|
72
|
+
const dataColumnSidecarBytes = dataColumnSidecars[i];
|
|
73
|
+
if (dataColumnSidecarBytes) {
|
|
74
|
+
yield {
|
|
75
|
+
data: dataColumnSidecarBytes,
|
|
76
|
+
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot)),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// TODO: Check blobs for that block and respond resource_unavailable
|
|
81
|
+
// After we have consensus from other teams on the specs
|
|
82
|
+
else {
|
|
83
|
+
unavailableColumnIndices.push(availableColumns[i]);
|
|
84
|
+
}
|
|
85
85
|
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (unavailableColumnIndices.length > 0) {
|
|
89
|
-
await handleColumnSidecarUnavailability({
|
|
90
|
-
chain,
|
|
91
|
-
db,
|
|
92
|
-
metrics: chain.metrics,
|
|
93
|
-
unavailableColumnIndices,
|
|
94
|
-
blockRoot: block.unavailabilityBlockRoot ? fromHex(block.unavailabilityBlockRoot) : undefined,
|
|
95
|
-
finalized: block.finalized,
|
|
96
|
-
slot: block.slot,
|
|
97
|
-
requestedColumns,
|
|
98
|
-
availableColumns,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
86
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
async function* resolveCanonicalDataColumnBlocks(
|
|
112
|
-
chain: IBeaconChain,
|
|
113
|
-
db: IBeaconDb,
|
|
114
|
-
headChain: ReturnType<IBeaconChain["forkChoice"]["getAllAncestorBlocks"]>,
|
|
115
|
-
startSlot: number,
|
|
116
|
-
endSlot: number,
|
|
117
|
-
archiveMaxSlot: number,
|
|
118
|
-
finalizedSlot: number
|
|
119
|
-
): AsyncIterable<CanonicalDataColumnBlock> {
|
|
120
|
-
const canonicalBlocksBySlot = new Map(headChain.map((block) => [block.slot, block]));
|
|
121
|
-
const oldestForkChoiceSlot = headChain.at(-1)?.slot ?? Number.POSITIVE_INFINITY;
|
|
122
|
-
const archiveEnd = Math.min(endSlot, archiveMaxSlot + 1);
|
|
123
|
-
const recentRoots = getRecentCanonicalRoots(chain, startSlot, Math.min(archiveEnd, oldestForkChoiceSlot));
|
|
124
|
-
|
|
125
|
-
for (let slot = startSlot; slot < archiveEnd; slot++) {
|
|
126
|
-
if (slot >= oldestForkChoiceSlot) {
|
|
127
|
-
const block = canonicalBlocksBySlot.get(slot);
|
|
128
|
-
if (block?.payloadStatus === PayloadStatus.FULL) {
|
|
129
|
-
yield {
|
|
87
|
+
if (unavailableColumnIndices.length) {
|
|
88
|
+
await handleColumnSidecarUnavailability({
|
|
89
|
+
chain,
|
|
90
|
+
db,
|
|
91
|
+
metrics: chain.metrics,
|
|
92
|
+
unavailableColumnIndices,
|
|
130
93
|
slot,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
};
|
|
94
|
+
requestedColumns,
|
|
95
|
+
availableColumns,
|
|
96
|
+
});
|
|
135
97
|
}
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
let blockRoot = recentRoots.get(slot);
|
|
140
|
-
if (blockRoot === null) continue;
|
|
141
|
-
if (blockRoot === undefined) {
|
|
142
|
-
const root = await db.blockArchive.getRootBySlot(slot);
|
|
143
|
-
blockRoot = root === null ? null : toRootHex(root);
|
|
144
|
-
}
|
|
145
|
-
if (blockRoot === null && (db.lastLegacyArchiveSlot === null || slot > db.lastLegacyArchiveSlot)) continue;
|
|
146
|
-
if (
|
|
147
|
-
chain.config.getForkSeq(slot) >= ForkSeq.gloas &&
|
|
148
|
-
!(await hasExecutionPayloadEnvelope(chain, db, slot, blockRoot))
|
|
149
|
-
) {
|
|
150
|
-
continue;
|
|
151
98
|
}
|
|
152
|
-
yield {
|
|
153
|
-
slot,
|
|
154
|
-
blockRoot,
|
|
155
|
-
unavailabilityBlockRoot: chain.config.getForkSeq(slot) >= ForkSeq.gloas ? (blockRoot ?? undefined) : undefined,
|
|
156
|
-
finalized: true,
|
|
157
|
-
};
|
|
158
99
|
}
|
|
159
100
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
101
|
+
// Non-finalized range of columns
|
|
102
|
+
if (endSlot > archiveMaxSlot) {
|
|
103
|
+
const headBlock = chain.forkChoice.getHead();
|
|
104
|
+
const headRoot = headBlock.blockRoot;
|
|
105
|
+
// getAllAncestorBlocks includes the last finalized block as its final element.
|
|
106
|
+
// Skip anything the archive loop above already served via the block.slot > archiveMaxSlot
|
|
107
|
+
// filter below (pre-gloas this skips finalizedSlot, post-gloas it keeps it).
|
|
108
|
+
const headChain = chain.forkChoice.getAllAncestorBlocks(headRoot, headBlock.payloadStatus);
|
|
109
|
+
|
|
110
|
+
// Iterate head chain with ascending block numbers
|
|
111
|
+
for (let i = headChain.length - 1; i >= 0; i--) {
|
|
112
|
+
const block = headChain[i];
|
|
113
|
+
|
|
114
|
+
// Must include only columns in the range requested
|
|
115
|
+
if (block.slot > archiveMaxSlot && block.slot >= startSlot && block.slot < endSlot) {
|
|
116
|
+
// Post-gloas, columns exist only for FULL blocks (pre-gloas blocks are always FULL)
|
|
117
|
+
if (block.payloadStatus !== PayloadStatus.FULL) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Note: Here the forkChoice head may change due to a re-org, so the headChain reflects the canonical chain
|
|
122
|
+
// at the time of the start of the request. Spec is clear the chain of columns must be consistent, but on
|
|
123
|
+
// re-org there's no need to abort the request
|
|
124
|
+
// Spec: https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/specs/fulu/p2p-interface.md#L425-L429
|
|
125
|
+
const dataColumnSidecars = await chain.getSerializedDataColumnSidecars(
|
|
126
|
+
block.slot,
|
|
127
|
+
block.blockRoot,
|
|
128
|
+
availableColumns
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const unavailableColumnIndices: ColumnIndex[] = [];
|
|
132
|
+
for (let i = 0; i < dataColumnSidecars.length; i++) {
|
|
133
|
+
const dataColumnSidecarBytes = dataColumnSidecars[i];
|
|
134
|
+
if (dataColumnSidecarBytes) {
|
|
135
|
+
yield {
|
|
136
|
+
data: dataColumnSidecarBytes,
|
|
137
|
+
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// TODO: Check blobs for that block and respond resource_unavailable
|
|
142
|
+
// After we have consensus from other teams on the specs
|
|
143
|
+
else {
|
|
144
|
+
unavailableColumnIndices.push(availableColumns[i]);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (unavailableColumnIndices.length) {
|
|
149
|
+
await handleColumnSidecarUnavailability({
|
|
150
|
+
chain,
|
|
151
|
+
db,
|
|
152
|
+
metrics: chain.metrics,
|
|
153
|
+
unavailableColumnIndices,
|
|
154
|
+
blockRoot: fromHex(block.blockRoot),
|
|
155
|
+
slot: block.slot,
|
|
156
|
+
requestedColumns,
|
|
157
|
+
availableColumns,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
190
161
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
): Promise<boolean> {
|
|
197
|
-
if (blockRoot !== null) {
|
|
198
|
-
if (chain.seenPayloadEnvelopeInputCache.hasPayload(blockRoot)) return true;
|
|
199
|
-
if ((await db.executionPayloadEnvelope.getBinary(fromHex(blockRoot))) !== null) return true;
|
|
162
|
+
// If block is after endSlot, stop iterating
|
|
163
|
+
else if (block.slot >= endSlot) {
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
200
167
|
}
|
|
201
|
-
return (await db.executionPayloadEnvelopeArchive.getBinary(slot)) !== null;
|
|
202
168
|
}
|
|
203
169
|
|
|
204
170
|
export function validateDataColumnSidecarsByRangeRequest(
|
|
@@ -81,14 +81,12 @@ export async function* onDataColumnSidecarsByRoot(
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
if (unavailableColumnIndices.length) {
|
|
84
|
-
const finalized = !block || (await db.blockArchive.getSlotByRoot(blockRoot)) === slot;
|
|
85
84
|
await handleColumnSidecarUnavailability({
|
|
86
85
|
chain,
|
|
87
86
|
db,
|
|
88
87
|
metrics: chain.metrics,
|
|
89
88
|
slot,
|
|
90
89
|
blockRoot,
|
|
91
|
-
finalized,
|
|
92
90
|
unavailableColumnIndices,
|
|
93
91
|
requestedColumns,
|
|
94
92
|
availableColumns,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {BeaconConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkName} from "@lodestar/params";
|
|
2
|
+
import {ForkName, MAX_DATA_COLUMN_SIDECAR_SIZE, isForkPostGloas} from "@lodestar/params";
|
|
3
3
|
import {ContextBytesFactory, ContextBytesType, Encoding, TypeSizes} from "@lodestar/reqresp";
|
|
4
4
|
import {rateLimitQuotas} from "./rateLimit.js";
|
|
5
5
|
import {ProtocolNoHandler, ReqRespMethod, Version, requestSszTypeByMethod, responseSszTypeByMethod} from "./types.js";
|
|
@@ -151,18 +151,35 @@ function toProtocol(protocol: ProtocolSummary) {
|
|
|
151
151
|
encoding: Encoding.SSZ_SNAPPY,
|
|
152
152
|
contextBytes: toContextBytes(protocol.contextBytesType, config),
|
|
153
153
|
inboundRateLimits: rateLimitQuotas(fork, config)[protocol.method],
|
|
154
|
-
requestSizes: requestType === null ? null : clampTypeSizes(requestType, config),
|
|
155
|
-
responseSizes: (fork) =>
|
|
154
|
+
requestSizes: requestType === null ? null : clampTypeSizes(requestType, protocol.method, fork, config),
|
|
155
|
+
responseSizes: (fork) =>
|
|
156
|
+
clampTypeSizes(responseSszTypeByMethod[protocol.method](fork, protocol.version), protocol.method, fork, config),
|
|
156
157
|
};
|
|
157
158
|
};
|
|
158
159
|
}
|
|
159
160
|
|
|
160
161
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
162
|
+
* Bound the sizes accepted from the ssz-snappy length-prefix. Gloas progressive containers have broad
|
|
163
|
+
* theoretical SSZ max sizes so the preset p2p bounds must be used instead.
|
|
164
|
+
*
|
|
165
|
+
* The length-prefix must be within the size bounds derived from the payload SSZ type or `MAX_PAYLOAD_SIZE`,
|
|
166
|
+
* whichever is smaller, see
|
|
167
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.12/specs/phase0/p2p-interface.md#encoding-strategies.
|
|
168
|
+
* Type-specific SSZ bounds supersede the bounds derived from the SSZ type, see
|
|
169
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.12/specs/gloas/p2p-interface.md#type-specific-ssz-bounds.
|
|
163
170
|
*/
|
|
164
|
-
function clampTypeSizes(type: TypeSizes, config: BeaconConfig): TypeSizes {
|
|
165
|
-
|
|
171
|
+
function clampTypeSizes(type: TypeSizes, method: ReqRespMethod, fork: ForkName, config: BeaconConfig): TypeSizes {
|
|
172
|
+
let typeSpecificBound = config.MAX_PAYLOAD_SIZE;
|
|
173
|
+
if (isForkPostGloas(fork)) {
|
|
174
|
+
switch (method) {
|
|
175
|
+
case ReqRespMethod.DataColumnSidecarsByRange:
|
|
176
|
+
case ReqRespMethod.DataColumnSidecarsByRoot:
|
|
177
|
+
typeSpecificBound = MAX_DATA_COLUMN_SIDECAR_SIZE;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return {minSize: type.minSize, maxSize: Math.min(type.maxSize, typeSpecificBound)};
|
|
166
183
|
}
|
|
167
184
|
|
|
168
185
|
function toContextBytes(type: ContextBytesType, config: BeaconConfig): ContextBytesFactory {
|
|
@@ -16,14 +16,12 @@ export async function handleColumnSidecarUnavailability({
|
|
|
16
16
|
availableColumns,
|
|
17
17
|
slot,
|
|
18
18
|
blockRoot,
|
|
19
|
-
finalized,
|
|
20
19
|
}: {
|
|
21
20
|
chain: IBeaconChain;
|
|
22
21
|
db: IBeaconDb;
|
|
23
22
|
metrics: Metrics | null;
|
|
24
23
|
slot: Slot;
|
|
25
24
|
blockRoot?: Uint8Array;
|
|
26
|
-
finalized: boolean;
|
|
27
25
|
unavailableColumnIndices: ColumnIndex[];
|
|
28
26
|
requestedColumns: ColumnIndex[];
|
|
29
27
|
availableColumns: ColumnIndex[];
|
|
@@ -40,23 +38,17 @@ export async function handleColumnSidecarUnavailability({
|
|
|
40
38
|
|
|
41
39
|
chain.logger.debug("dataColumnSidecar requested unavailable", logData);
|
|
42
40
|
|
|
43
|
-
// Post-gloas, columns exist only for FULL blocks
|
|
44
|
-
//
|
|
45
|
-
if (chain.config.getForkSeq(slot) >= ForkSeq.gloas) {
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
48
|
-
const hotEnvelopeBytes = blockRoot ? await db.executionPayloadEnvelope.getBinary(blockRoot) : null;
|
|
49
|
-
const envelopeBytes =
|
|
50
|
-
hotEnvelopeBytes ?? (finalized ? await db.executionPayloadEnvelopeArchive.getBinary(slot) : null);
|
|
51
|
-
if (!envelopeBytes) return;
|
|
52
|
-
}
|
|
41
|
+
// Post-gloas, columns exist only for FULL blocks; a finalized block is FULL if its envelope was
|
|
42
|
+
// archived. Bid blobsCount is unreliable here since an EMPTY block's bid may still commit to blobs
|
|
43
|
+
if (blockRoot === undefined && chain.config.getForkSeq(slot) >= ForkSeq.gloas) {
|
|
44
|
+
const envelopeBytes = await db.executionPayloadEnvelopeArchive.getBinary(slot);
|
|
45
|
+
if (!envelopeBytes) return;
|
|
53
46
|
}
|
|
54
47
|
|
|
55
|
-
const
|
|
56
|
-
const blockBytes = hotBlockBytes ?? (finalized ? await db.blockArchive.getBinary(slot) : null);
|
|
48
|
+
const blockBytes = blockRoot ? await db.block.getBinary(blockRoot) : await db.blockArchive.getBinary(slot);
|
|
57
49
|
if (!blockBytes) {
|
|
58
50
|
chain.logger.verbose(
|
|
59
|
-
`Expected ${
|
|
51
|
+
`Expected ${blockRoot ? "unfinalized" : "finalized"} block not found while handling unavailable dataColumnSidecar`,
|
|
60
52
|
{
|
|
61
53
|
slot,
|
|
62
54
|
blockRoot: blockRoot ? toRootHex(blockRoot) : "unknown",
|
package/src/node/nodejs.ts
CHANGED
|
@@ -54,7 +54,6 @@ export type BeaconNodeInitModules = {
|
|
|
54
54
|
processShutdownCallback: ProcessShutdownCallback;
|
|
55
55
|
privateKey: PrivateKey;
|
|
56
56
|
dataDir: string;
|
|
57
|
-
dataColumnDir: string;
|
|
58
57
|
peerStoreDir?: string;
|
|
59
58
|
anchorState: IBeaconStateView;
|
|
60
59
|
isAnchorStateFinalized: boolean;
|
|
@@ -157,7 +156,6 @@ export class BeaconNode {
|
|
|
157
156
|
processShutdownCallback,
|
|
158
157
|
privateKey,
|
|
159
158
|
dataDir,
|
|
160
|
-
dataColumnDir,
|
|
161
159
|
peerStoreDir,
|
|
162
160
|
anchorState,
|
|
163
161
|
isAnchorStateFinalized,
|
|
@@ -183,7 +181,7 @@ export class BeaconNode {
|
|
|
183
181
|
metrics = createMetrics(opts.metrics, anchorState.genesisTime, metricsRegistries);
|
|
184
182
|
initBeaconMetrics(metrics, anchorState);
|
|
185
183
|
// Since the db is instantiated before this, metrics must be injected manually afterwards
|
|
186
|
-
db.setMetrics(metrics.db
|
|
184
|
+
db.setMetrics(metrics.db);
|
|
187
185
|
signal.addEventListener("abort", metrics.close, {once: true});
|
|
188
186
|
}
|
|
189
187
|
|
|
@@ -200,8 +198,6 @@ export class BeaconNode {
|
|
|
200
198
|
|
|
201
199
|
const clock = new Clock({config, genesisTime: anchorState.genesisTime, signal});
|
|
202
200
|
|
|
203
|
-
await db.init();
|
|
204
|
-
|
|
205
201
|
// Prune hot db repos
|
|
206
202
|
// TODO: Should this call be awaited?
|
|
207
203
|
await db.pruneHotDb();
|
|
@@ -248,7 +244,6 @@ export class BeaconNode {
|
|
|
248
244
|
clock,
|
|
249
245
|
pubkeyCache,
|
|
250
246
|
dataDir,
|
|
251
|
-
dataColumnDir,
|
|
252
247
|
db,
|
|
253
248
|
dbName: opts.db.name,
|
|
254
249
|
logger: logger.child({module: LoggerModule.chain}),
|
package/src/util/sszBytes.ts
CHANGED
|
@@ -754,7 +754,7 @@ export function getParentBlockRootFromSignedExecutionPayloadBidSerialized(data:
|
|
|
754
754
|
*
|
|
755
755
|
* If the high bytes are not zero, return null
|
|
756
756
|
*/
|
|
757
|
-
|
|
757
|
+
function getSlotFromOffset(data: Uint8Array, offset: number): Slot | null {
|
|
758
758
|
return checkSlotHighBytes(data, offset) ? getSlotFromOffsetTrusted(data, offset) : null;
|
|
759
759
|
}
|
|
760
760
|
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { ColumnIndex, DataColumnSidecar, RootHex, Slot } from "@lodestar/types";
|
|
2
|
-
import type { IFlatFileStore } from "./flatFileStore/interface.js";
|
|
3
|
-
import type { BlockArchiveRepository, DataColumnSidecarArchiveRepository, DataColumnSidecarRepository } from "./repositories/index.js";
|
|
4
|
-
export type DataColumnKey = {
|
|
5
|
-
slot: Slot;
|
|
6
|
-
blockRoot: RootHex;
|
|
7
|
-
};
|
|
8
|
-
export type IndexedDataColumnBytes = {
|
|
9
|
-
index: ColumnIndex;
|
|
10
|
-
data: Uint8Array;
|
|
11
|
-
};
|
|
12
|
-
type LegacyHotDataColumnStore = Pick<DataColumnSidecarRepository, "values" | "getManyBinary" | "deleteMany">;
|
|
13
|
-
type LegacyArchiveDataColumnStore = Pick<DataColumnSidecarArchiveRepository, "values" | "getManyBinary" | "keys" | "deleteMany">;
|
|
14
|
-
type BlockRootIndex = Pick<BlockArchiveRepository, "getSlotByRoot">;
|
|
15
|
-
export interface IDataColumnStore {
|
|
16
|
-
getAll(key: DataColumnKey): Promise<DataColumnSidecar[]>;
|
|
17
|
-
getManyBinary(key: DataColumnKey, indices: ColumnIndex[]): Promise<(Uint8Array | undefined)[]>;
|
|
18
|
-
putManyBinary(key: DataColumnKey, columns: IndexedDataColumnBytes[]): Promise<void>;
|
|
19
|
-
deleteMany(keys: DataColumnKey[]): Promise<void>;
|
|
20
|
-
pruneBefore(slot: Slot): Promise<Slot[]>;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Bridges pre-flat-file LevelDB columns during the supported in-place upgrade window.
|
|
24
|
-
* Remove the legacy repositories after upgrades from the last pre-flat-file release are no longer supported.
|
|
25
|
-
*/
|
|
26
|
-
export declare class LegacyDataColumnStore implements IDataColumnStore {
|
|
27
|
-
private readonly flatFiles;
|
|
28
|
-
private readonly legacyHot;
|
|
29
|
-
private readonly legacyArchive;
|
|
30
|
-
private readonly blockArchive;
|
|
31
|
-
constructor(flatFiles: IFlatFileStore, legacyHot: LegacyHotDataColumnStore, legacyArchive: LegacyArchiveDataColumnStore, blockArchive: BlockRootIndex);
|
|
32
|
-
getAll({ slot, blockRoot }: DataColumnKey): Promise<DataColumnSidecar[]>;
|
|
33
|
-
getManyBinary({ slot, blockRoot }: DataColumnKey, indices: ColumnIndex[]): Promise<(Uint8Array | undefined)[]>;
|
|
34
|
-
putManyBinary({ slot, blockRoot }: DataColumnKey, columns: IndexedDataColumnBytes[]): Promise<void>;
|
|
35
|
-
deleteMany(keys: DataColumnKey[]): Promise<void>;
|
|
36
|
-
pruneBefore(slot: Slot): Promise<Slot[]>;
|
|
37
|
-
}
|
|
38
|
-
export {};
|
|
39
|
-
//# sourceMappingURL=dataColumnStore.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dataColumnStore.d.ts","sourceRoot":"","sources":["../../src/db/dataColumnStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAE9E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EACV,sBAAsB,EACtB,kCAAkC,EAClC,2BAA2B,EAC5B,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAC,CAAC;AAC7D,MAAM,MAAM,sBAAsB,GAAG;IAAC,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAC,CAAC;AAE5E,KAAK,wBAAwB,GAAG,IAAI,CAAC,2BAA2B,EAAE,QAAQ,GAAG,eAAe,GAAG,YAAY,CAAC,CAAC;AAC7G,KAAK,4BAA4B,GAAG,IAAI,CACtC,kCAAkC,EAClC,QAAQ,GAAG,eAAe,GAAG,MAAM,GAAG,YAAY,CACnD,CAAC;AACF,KAAK,cAAc,GAAG,IAAI,CAAC,sBAAsB,EAAE,eAAe,CAAC,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACzD,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAC/F,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,gBAAgB;IAE1D,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJ/B,YACmB,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,wBAAwB,EACnC,aAAa,EAAE,4BAA4B,EAC3C,YAAY,EAAE,cAAc,EAC3C;IAEE,MAAM,CAAC,EAAC,IAAI,EAAE,SAAS,EAAC,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiB3E;IAEK,aAAa,CAAC,EAAC,IAAI,EAAE,SAAS,EAAC,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,CAAC,CAiBjH;IAEK,aAAa,CAAC,EAAC,IAAI,EAAE,SAAS,EAAC,EAAE,aAAa,EAAE,OAAO,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtG;IAEK,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrD;IAEK,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAM7C;CACF"}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { fromHex } from "@lodestar/utils";
|
|
2
|
-
/**
|
|
3
|
-
* Bridges pre-flat-file LevelDB columns during the supported in-place upgrade window.
|
|
4
|
-
* Remove the legacy repositories after upgrades from the last pre-flat-file release are no longer supported.
|
|
5
|
-
*/
|
|
6
|
-
export class LegacyDataColumnStore {
|
|
7
|
-
flatFiles;
|
|
8
|
-
legacyHot;
|
|
9
|
-
legacyArchive;
|
|
10
|
-
blockArchive;
|
|
11
|
-
constructor(flatFiles, legacyHot, legacyArchive, blockArchive) {
|
|
12
|
-
this.flatFiles = flatFiles;
|
|
13
|
-
this.legacyHot = legacyHot;
|
|
14
|
-
this.legacyArchive = legacyArchive;
|
|
15
|
-
this.blockArchive = blockArchive;
|
|
16
|
-
}
|
|
17
|
-
async getAll({ slot, blockRoot }) {
|
|
18
|
-
const sidecars = await this.flatFiles.getDataColumns(slot, blockRoot);
|
|
19
|
-
if (sidecars.length > 0)
|
|
20
|
-
return sidecars;
|
|
21
|
-
const sidecarsByIndex = new Map();
|
|
22
|
-
const root = fromHex(blockRoot);
|
|
23
|
-
for (const sidecar of await this.legacyHot.values(root)) {
|
|
24
|
-
if (!sidecarsByIndex.has(sidecar.index))
|
|
25
|
-
sidecarsByIndex.set(sidecar.index, sidecar);
|
|
26
|
-
}
|
|
27
|
-
if ((await this.blockArchive.getSlotByRoot(root)) === slot) {
|
|
28
|
-
for (const sidecar of await this.legacyArchive.values(slot)) {
|
|
29
|
-
if (!sidecarsByIndex.has(sidecar.index))
|
|
30
|
-
sidecarsByIndex.set(sidecar.index, sidecar);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return [...sidecarsByIndex.values()].sort((a, b) => a.index - b.index);
|
|
34
|
-
}
|
|
35
|
-
async getManyBinary({ slot, blockRoot }, indices) {
|
|
36
|
-
const flatFileSidecars = await this.flatFiles.getDataColumnsBinary(slot, blockRoot, indices);
|
|
37
|
-
if (flatFileSidecars !== null)
|
|
38
|
-
return flatFileSidecars;
|
|
39
|
-
if (indices.length === 0)
|
|
40
|
-
return [];
|
|
41
|
-
const root = fromHex(blockRoot);
|
|
42
|
-
const result = await this.legacyHot.getManyBinary(root, indices);
|
|
43
|
-
const missingPositions = getMissingPositions(result);
|
|
44
|
-
if (missingPositions.length === 0 || (await this.blockArchive.getSlotByRoot(root)) !== slot)
|
|
45
|
-
return result;
|
|
46
|
-
const archivedSidecars = await this.legacyArchive.getManyBinary(slot, missingPositions.map((position) => indices[position]));
|
|
47
|
-
fillMissing(result, missingPositions, archivedSidecars);
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
50
|
-
async putManyBinary({ slot, blockRoot }, columns) {
|
|
51
|
-
await this.flatFiles.putDataColumnsBinary(slot, blockRoot, columns);
|
|
52
|
-
}
|
|
53
|
-
async deleteMany(keys) {
|
|
54
|
-
await this.flatFiles.deleteMany(keys);
|
|
55
|
-
await this.legacyHot.deleteMany(keys.map(({ blockRoot }) => fromHex(blockRoot)));
|
|
56
|
-
}
|
|
57
|
-
async pruneBefore(slot) {
|
|
58
|
-
const flatFileSlots = await this.flatFiles.pruneBefore(slot);
|
|
59
|
-
const prefixedKeys = await this.legacyArchive.keys({ lt: { prefix: slot, id: 0 } });
|
|
60
|
-
const slots = [...new Set(prefixedKeys.map(({ prefix }) => prefix))];
|
|
61
|
-
if (slots.length > 0)
|
|
62
|
-
await this.legacyArchive.deleteMany(slots);
|
|
63
|
-
return [...new Set([...flatFileSlots, ...slots])].sort((a, b) => a - b);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function getMissingPositions(sidecars) {
|
|
67
|
-
const positions = [];
|
|
68
|
-
for (let i = 0; i < sidecars.length; i++) {
|
|
69
|
-
if (sidecars[i] === undefined)
|
|
70
|
-
positions.push(i);
|
|
71
|
-
}
|
|
72
|
-
return positions;
|
|
73
|
-
}
|
|
74
|
-
function fillMissing(result, missingPositions, sidecars) {
|
|
75
|
-
for (let i = 0; i < missingPositions.length; i++) {
|
|
76
|
-
const sidecar = sidecars[i];
|
|
77
|
-
if (sidecar != null)
|
|
78
|
-
result[missingPositions[i]] = sidecar;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
//# sourceMappingURL=dataColumnStore.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dataColumnStore.js","sourceRoot":"","sources":["../../src/db/dataColumnStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Atomic write: write to `.part` temp file -> datasync -> rename to target.
|
|
3
|
-
* This guarantees crash-safe writes — if the process crashes mid-write,
|
|
4
|
-
* only the `.part` file is corrupted, never the target.
|
|
5
|
-
*/
|
|
6
|
-
export declare function atomicWrite(targetPath: string, data: Uint8Array): Promise<void>;
|
|
7
|
-
export declare function mkdirDurable(dir: string): Promise<void>;
|
|
8
|
-
//# sourceMappingURL=atomicWrite.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"atomicWrite.d.ts","sourceRoot":"","sources":["../../../src/db/flatFileStore/atomicWrite.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrF;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB7D"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { mkdir, open, rename, rm } from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
const pendingDirectorySyncs = new Map();
|
|
4
|
-
/**
|
|
5
|
-
* Atomic write: write to `.part` temp file -> datasync -> rename to target.
|
|
6
|
-
* This guarantees crash-safe writes — if the process crashes mid-write,
|
|
7
|
-
* only the `.part` file is corrupted, never the target.
|
|
8
|
-
*/
|
|
9
|
-
export async function atomicWrite(targetPath, data) {
|
|
10
|
-
const dir = path.dirname(targetPath);
|
|
11
|
-
const partPath = `${targetPath}.part-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
12
|
-
await mkdirDurable(dir);
|
|
13
|
-
try {
|
|
14
|
-
const fd = await open(partPath, "wx");
|
|
15
|
-
try {
|
|
16
|
-
await fd.writeFile(data);
|
|
17
|
-
await fd.datasync();
|
|
18
|
-
}
|
|
19
|
-
finally {
|
|
20
|
-
await fd.close();
|
|
21
|
-
}
|
|
22
|
-
await rename(partPath, targetPath);
|
|
23
|
-
// Ensure rename metadata is durable on crash.
|
|
24
|
-
await syncDirectory(dir);
|
|
25
|
-
}
|
|
26
|
-
catch (e) {
|
|
27
|
-
await rm(partPath, { force: true }).catch(() => { });
|
|
28
|
-
throw e;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
export async function mkdirDurable(dir) {
|
|
32
|
-
const targetDir = path.resolve(dir);
|
|
33
|
-
let directoriesToSync = pendingDirectorySyncs.get(targetDir);
|
|
34
|
-
if (directoriesToSync === undefined) {
|
|
35
|
-
const firstCreatedDir = await mkdir(targetDir, { recursive: true });
|
|
36
|
-
if (firstCreatedDir === undefined)
|
|
37
|
-
return;
|
|
38
|
-
let createdDir = path.resolve(firstCreatedDir);
|
|
39
|
-
directoriesToSync = [path.dirname(createdDir)];
|
|
40
|
-
while (createdDir !== targetDir) {
|
|
41
|
-
directoriesToSync.push(createdDir);
|
|
42
|
-
const [nextSegment] = path.relative(createdDir, targetDir).split(path.sep);
|
|
43
|
-
createdDir = path.join(createdDir, nextSegment);
|
|
44
|
-
}
|
|
45
|
-
pendingDirectorySyncs.set(targetDir, directoriesToSync);
|
|
46
|
-
}
|
|
47
|
-
for (const directory of directoriesToSync) {
|
|
48
|
-
await syncDirectory(directory);
|
|
49
|
-
}
|
|
50
|
-
pendingDirectorySyncs.delete(targetDir);
|
|
51
|
-
}
|
|
52
|
-
async function syncDirectory(dir) {
|
|
53
|
-
const dirFd = await open(dir, "r");
|
|
54
|
-
try {
|
|
55
|
-
await dirFd.sync();
|
|
56
|
-
}
|
|
57
|
-
finally {
|
|
58
|
-
await dirFd.close();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=atomicWrite.js.map
|