@lodestar/beacon-node 1.36.0-dev.9dbc67b579 → 1.36.0-dev.9fe2e4d0bd
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 +41 -22
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +5 -4
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/options.d.ts +0 -2
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +0 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js +5 -1
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/gossip/encoding.js +1 -1
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/snappy_bun.d.ts +3 -0
- package/lib/network/gossip/snappy_bun.d.ts.map +1 -0
- package/lib/network/gossip/snappy_bun.js +3 -0
- package/lib/network/gossip/snappy_bun.js.map +1 -0
- package/lib/network/metadata.d.ts +1 -1
- package/lib/network/metadata.d.ts.map +1 -1
- package/lib/network/metadata.js +1 -0
- package/lib/network/metadata.js.map +1 -1
- package/lib/network/options.d.ts +0 -1
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js.map +1 -1
- package/lib/util/blobs.d.ts +1 -1
- package/lib/util/blobs.d.ts.map +1 -1
- package/lib/util/blobs.js +53 -20
- package/lib/util/blobs.js.map +1 -1
- package/package.json +19 -14
- package/src/api/impl/beacon/blocks/index.ts +47 -25
- package/src/chain/chain.ts +5 -5
- package/src/chain/options.ts +0 -3
- package/src/network/core/networkCore.ts +5 -1
- package/src/network/gossip/encoding.ts +1 -1
- package/src/network/gossip/snappy_bun.ts +2 -0
- package/src/network/metadata.ts +3 -1
- package/src/network/options.ts +0 -1
- package/src/util/blobs.ts +64 -20
package/src/util/blobs.ts
CHANGED
|
@@ -149,41 +149,85 @@ export async function dataColumnMatrixRecovery(
|
|
|
149
149
|
* Reconstruct blobs from a set of data columns, at least 50%+ of all the columns
|
|
150
150
|
* must be provided to allow to reconstruct the full data matrix
|
|
151
151
|
*/
|
|
152
|
-
export async function reconstructBlobs(sidecars: fulu.DataColumnSidecars): Promise<deneb.Blobs> {
|
|
152
|
+
export async function reconstructBlobs(sidecars: fulu.DataColumnSidecars, indices?: number[]): Promise<deneb.Blobs> {
|
|
153
153
|
if (sidecars.length < NUMBER_OF_COLUMNS / 2) {
|
|
154
154
|
throw Error(
|
|
155
155
|
`Expected at least ${NUMBER_OF_COLUMNS / 2} data columns to reconstruct blobs, received ${sidecars.length}`
|
|
156
156
|
);
|
|
157
157
|
}
|
|
158
|
+
const blobCount = sidecars[0].column.length;
|
|
158
159
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// Full columns, no need to recover
|
|
163
|
-
fullSidecars = sidecars;
|
|
164
|
-
} else {
|
|
165
|
-
const sidecarsByIndex = new Map<number, fulu.DataColumnSidecar>(sidecars.map((sc) => [sc.index, sc]));
|
|
166
|
-
const recoveredSidecars = await dataColumnMatrixRecovery(sidecarsByIndex);
|
|
167
|
-
if (recoveredSidecars === null) {
|
|
168
|
-
// Should not happen because we check the column count above
|
|
169
|
-
throw Error("Failed to reconstruct the full data matrix");
|
|
160
|
+
for (const index of indices ?? []) {
|
|
161
|
+
if (index < 0 || index >= blobCount) {
|
|
162
|
+
throw Error(`Invalid blob index ${index}, must be between 0 and ${blobCount - 1}`);
|
|
170
163
|
}
|
|
171
|
-
|
|
164
|
+
}
|
|
165
|
+
const indicesToReconstruct = indices ?? Array.from({length: blobCount}, (_, i) => i);
|
|
166
|
+
|
|
167
|
+
const recoveredCells = await recoverBlobCells(sidecars, indicesToReconstruct);
|
|
168
|
+
if (recoveredCells === null) {
|
|
169
|
+
// Should not happen because we check the column count above
|
|
170
|
+
throw Error("Failed to recover cells to reconstruct blobs");
|
|
172
171
|
}
|
|
173
172
|
|
|
174
|
-
const
|
|
175
|
-
const blobs: deneb.Blobs = new Array(blobCount);
|
|
173
|
+
const blobs: deneb.Blobs = new Array(indicesToReconstruct.length);
|
|
176
174
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
175
|
+
for (let i = 0; i < indicesToReconstruct.length; i++) {
|
|
176
|
+
const blobIndex = indicesToReconstruct[i];
|
|
177
|
+
const cells = recoveredCells.get(blobIndex);
|
|
178
|
+
if (!cells) {
|
|
179
|
+
throw Error(`Failed to get recovered cells for blob index ${blobIndex}`);
|
|
180
|
+
}
|
|
181
|
+
blobs[i] = cellsToBlob(cells);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
return blobs;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Recover cells for specific blob indices from a set of data columns
|
|
189
|
+
*/
|
|
190
|
+
async function recoverBlobCells(
|
|
191
|
+
partialSidecars: fulu.DataColumnSidecar[],
|
|
192
|
+
blobIndices: number[]
|
|
193
|
+
): Promise<Map<number, fulu.Cell[]> | null> {
|
|
194
|
+
const columnCount = partialSidecars.length;
|
|
195
|
+
if (columnCount < NUMBER_OF_COLUMNS / 2) {
|
|
196
|
+
// We don't have enough columns to recover
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const recoveredCells = new Map<number, fulu.Cell[]>();
|
|
201
|
+
// Sort data columns by index in ascending order
|
|
202
|
+
const partialSidecarsSorted = partialSidecars.slice().sort((a, b) => a.index - b.index);
|
|
203
|
+
|
|
204
|
+
if (columnCount === NUMBER_OF_COLUMNS) {
|
|
205
|
+
// Full columns, no need to recover
|
|
206
|
+
for (const blobIndex of blobIndices) {
|
|
207
|
+
// 128 cells that make up one "extended blob" row
|
|
208
|
+
const cells = partialSidecarsSorted.map((col) => col.column[blobIndex]);
|
|
209
|
+
recoveredCells.set(blobIndex, cells);
|
|
210
|
+
}
|
|
211
|
+
return recoveredCells;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
await Promise.all(
|
|
215
|
+
blobIndices.map(async (blobIndex) => {
|
|
216
|
+
const cellIndices: number[] = [];
|
|
217
|
+
const cells: fulu.Cell[] = [];
|
|
218
|
+
for (const dataColumn of partialSidecarsSorted) {
|
|
219
|
+
cellIndices.push(dataColumn.index);
|
|
220
|
+
cells.push(dataColumn.column[blobIndex]);
|
|
221
|
+
}
|
|
222
|
+
// Recover cells for this specific blob row
|
|
223
|
+
const recovered = await kzg.asyncRecoverCellsAndKzgProofs(cellIndices, cells);
|
|
224
|
+
recoveredCells.set(blobIndex, recovered.cells);
|
|
225
|
+
})
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
return recoveredCells;
|
|
229
|
+
}
|
|
230
|
+
|
|
187
231
|
/**
|
|
188
232
|
* Concatenate the systematic half (columns 0‑63) of a row of cells into
|
|
189
233
|
* the original 131072 byte blob. The parity half (64‑127) is ignored as
|