6a3d7192abc1
derive shard size from scanned chunks in decodeWithErasure — restores old Codexes after CHUNK_SIZE bump
- time
- 2026-05-17 14:58 UTC · 5 months ago
- machine
- koh2
- parent
- f89c3b5b9a6c
↓ peach-browser-6a3d7192.tar.gzatlas at this save
files changed1 file
src/popup/codex/erasure.ts+22 −6src/popup/codex/erasure.ts+22 −6
@@ -131,8 +131,14 @@131131 /**132132 * Reassemble the data-shard region from a partial set of chunks. Missing133133 * shards are reconstructed from parity. The returned buffer is exactly134- * `dataShards * CHUNK_SIZE` bytes long, including any trailing pad bytes134+ * `dataShards * shardSize` bytes long, including any trailing pad bytes135135 * — callers strip the pad using their out-of-band length information.136+ *137+ * Shard size is derived from the actual chunks rather than the current138+ * `CHUNK_SIZE` constant so that Codexes printed under an older constant139+ * (e.g. 1024-byte shards) still restore on a build whose constant has moved.140+ * Reed-Solomon requires all shards to share one length; the first chunk141+ * establishes it and every other chunk must match.136142 */137143 export async function decodeWithErasure(138144 chunks: Map<number, Uint8Array>,@@ -154,8 +160,18 @@154160 );155161 }156162 163+ // First scanned chunk fixes the shard size for the whole reconstruction.164+ const firstChunk = chunks.values().next().value;165+ if (!firstChunk || firstChunk.length === 0) {166+ throw new CodexError(167+ "ERASURE_CODING_VERIFICATION_FAILED",168+ "First chunk is empty; cannot determine shard size",169+ );170+ }171+ const shardSize = firstChunk.length;172+157173 const rs = await freshReedSolomon();158- const buffer = new Uint8Array(totalShards * CHUNK_SIZE);174+ const buffer = new Uint8Array(totalShards * shardSize);159175 const available: boolean[] = new Array(totalShards).fill(false);160176 161177 for (const [index, chunk] of chunks) {@@ -165,13 +181,13 @@165181 `Chunk index ${index} out of range [0, ${totalShards})`,166182 );167183 }168- if (chunk.length !== CHUNK_SIZE) {184+ if (chunk.length !== shardSize) {169185 throw new CodexError(170186 "ERASURE_CODING_VERIFICATION_FAILED",171- `Chunk ${index} has length ${chunk.length}, expected ${CHUNK_SIZE}`,187+ `Chunk ${index} has length ${chunk.length}, expected ${shardSize}`,172188 );173189 }174- buffer.set(chunk, index * CHUNK_SIZE);190+ buffer.set(chunk, index * shardSize);175191 available[index] = true;176192 }177193 @@ -192,5 +208,5 @@192208 );193209 }194210 195- return buffer.slice(0, dataShards * CHUNK_SIZE);211+ return buffer.slice(0, dataShards * shardSize);196212 }