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
1 file src/popup/codex/erasure.ts+22 −6
src/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 }

view file