Skip to content

fix(FileStore): deduplicate merkle leaves in readMerkleFile to preven…#12

Closed
es-kt wants to merge 3 commits into
mainfrom
fix/filestore-merkle-leaf-duplicate-cid
Closed

fix(FileStore): deduplicate merkle leaves in readMerkleFile to preven…#12
es-kt wants to merge 3 commits into
mainfrom
fix/filestore-merkle-leaf-duplicate-cid

Conversation

@es-kt

@es-kt es-kt commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator

…t wrong leaf lookup

The JSONL merkle leaves file can accumulate duplicate CID entries when appendMerkleLeaves is called after a process restart re-syncs an overlapping range. Since getMerkleLeaf uses the CID as an array index (rows[cid]), duplicates shift all subsequent lookups — causing buildLocalProofPath to retrieve wrong leaf commitments and produce invalid merkle proofs.

After sorting by CID, deduplicate adjacent entries keeping the last occurrence of each CID.

Summary

Brief description of changes.

Changes

Testing

  • pnpm run test passes
  • pnpm run build succeeds
  • pnpm run type-check passes

Related Issues

Closes #

…t wrong leaf lookup

The JSONL merkle leaves file can accumulate duplicate CID entries when
appendMerkleLeaves is called after a process restart re-syncs an
overlapping range. Since getMerkleLeaf uses the CID as an array index
(rows[cid]), duplicates shift all subsequent lookups — causing
buildLocalProofPath to retrieve wrong leaf commitments and produce
invalid merkle proofs.

After sorting by CID, deduplicate adjacent entries keeping the last
occurrence of each CID.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces deduplication logic for entries in the FileStore to prevent incorrect leaf retrieval caused by duplicate CID entries. The reviewer suggested refactoring the manual loop implementation into a more idiomatic reduce-based approach to improve readability.

Comment thread src/store/fileStore.ts
Comment on lines +125 to +136
if (out.length > 0) {
const deduped: typeof out = [out[0]!];
for (let i = 1; i < out.length; i++) {
if (out[i]!.cid === deduped[deduped.length - 1]!.cid) {
deduped[deduped.length - 1] = out[i]!;
} else {
deduped.push(out[i]!);
}
}
return deduped;
}
return undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The deduplication logic is correct, but it can be implemented more concisely using the reduce method. This would make the code more idiomatic and potentially easier to read for developers familiar with functional programming patterns.

Suggested change
if (out.length > 0) {
const deduped: typeof out = [out[0]!];
for (let i = 1; i < out.length; i++) {
if (out[i]!.cid === deduped[deduped.length - 1]!.cid) {
deduped[deduped.length - 1] = out[i]!;
} else {
deduped.push(out[i]!);
}
}
return deduped;
}
return undefined;
if (out.length === 0) {
return undefined;
}
return out.reduce((acc, current) => {
const last = acc[acc.length - 1];
if (last?.cid === current.cid) {
acc[acc.length - 1] = current;
} else {
acc.push(current);
}
return acc;
}, [] as typeof out);

es-kt and others added 2 commits April 10, 2026 04:01
…NextCid

getMerkleNextCid catches all errors and returns 0, which tells
appendMerkleLeaves the file is empty. On a transient I/O error this
causes every incoming leaf to be re-appended, creating duplicate CID
entries in the JSONL file. Since getMerkleLeaf uses cid as an array
index (rows[cid]), the duplicates shift all lookups — buildLocalProofPath
retrieves wrong commitments and produces invalid merkle proofs.

Only return 0 for ENOENT (file genuinely missing). Propagate all other
errors so appendMerkleLeaves skips the write instead of corrupting the file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@es-kt es-kt closed this Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant