Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved block-copy correctness and Windows replacement issues remain, along with test and release-documentation gaps.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds support for pruning an existing consensus BoltDB into a compact replacement.
Changes:
- Adds pruned database copying and replacement.
- Adds validation, progress logging, and pruning tests.
- Covers database integrity, reorgs, and lifecycle behavior.
File summaries
| File | Summary and findings |
|---|---|
db.go |
Adds BoltDB pruning and replacement. Windows replacement is unsupported (moderate, 1 vote); a Knope changeset is needed (nit, 3 votes). |
db_test.go |
Tests the pruning workflow. Should verify the resulting file is smaller (moderate, 1 vote). |
chain/prune.go |
Implements chain-state copying. Header-only records can be copied as successful full blocks (critical, 2 votes). |
chain/db_test.go |
Tests copied database integrity and reorg support. |
Review details
Suppressed comments (2)
db.go:180
- This replacement does not work on Windows:
os.Renamecannot replace an existing destination there, so pruning an existing database will always fail after doing the full copy. Use a platform-appropriate atomic replacement operation or explicitly restrict this API to platforms where replacement rename is supported.
} else if err := os.Rename(tmpPath, path); err != nil {
return fmt.Errorf("failed to replace database: %w", err)
db_test.go:44
- This integration test verifies the copied chain contents but never checks the user-visible purpose of this API: that the replacement file is actually smaller. A regression that accidentally keeps the original file while preserving all queried data would pass; please compare the file sizes before and after pruning.
if err := coreutils.PruneBoltChainDB(path, n, 50, nil); err != nil {
t.Fatal(err)
} else if _, err := os.Stat(path + ".tmp"); !errors.Is(err, os.ErrNotExist) {
t.Fatal("expected temporary database to be removed")
}
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🟡 Changes recommended
Resolve concurrent same-path pruning and strengthen size-reduction coverage; update the release note.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
db_test.go:40
- This test verifies that the retained chain remains usable, but it never checks the behavior this API is introduced for: reducing the on-disk BoltDB size to the checkpoint layout. A regression that copied the full source database or failed to reclaim the old pages would still pass; compare the rewritten file with the original and/or a freshly created checkpoint database.
if err := coreutils.PruneBoltChainDB(path, n, 50, nil); err != nil {
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Lite
9467cbb to
63bfd42
Compare
63bfd42 to
56367aa
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Address the nil-network panic and update the release note to document both public APIs.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
.changeset/added_coreutilspruneboltchaindb_to_shrink_the_size_of_an_existing_consensus_database.md:5
- This release note documents only
coreutils.PruneBoltChainDB, but the PR also adds the exportedchain.CopyPrunedDBAPI. Please update the changeset manually to describe both public entry points and the checkpoint/pruning behavior so the release notes reflect the complete API change.
# Added `coreutils.PruneBoltChainDB` to shrink the size of an existing consensus database.
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved database safety issues and release-note updates remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (4)
.changeset/added_coreutilspruneboltchaindb_to_shrink_the_size_of_an_existing_consensus_database.md:5
- Please manually revise this KNope-generated changeset entry to make the release note actionable: the new API atomically replaces an existing, closed Bolt database and retains data from the selected prune height through the tip, not merely shrinking an unspecified database.
# Added `coreutils.PruneBoltChainDB` to shrink the size of an existing consensus database.
.changeset/added_coreutilspruneboltchaindb_to_shrink_the_size_of_an_existing_consensus_database.md:5
- This generated changeset mentions only
coreutils.PruneBoltChainDB, but the PR also adds the exportedchain.CopyPrunedDBAPI. Please edit the release note so consumers of thechainpackage are told about both public additions.
# Added `coreutils.PruneBoltChainDB` to shrink the size of an existing consensus database.
db.go:179
- Closing
srcreleases bbolt's exclusive lock before the rename. A second call can acquire the lock, remove/recreate this same.tmppath, and let this call rename its in-progress file (or make the rename fail), so the lock does not serialize the replacement window. Hold a per-path lock throughos.Rename(including across processes if this API is used that way), or otherwise coordinate the temporary file and replacement.
} else if err := src.Close(); err != nil {
return fmt.Errorf("failed to close database: %w", err)
} else if err := os.Rename(tmpPath, path); err != nil {
db_test.go:40
- This test verifies the logical contents after rewriting, but not the advertised file-size reduction. A regression that copies the full database or otherwise fails to reclaim Bolt pages would still pass; record the size before pruning and assert that the replacement is smaller.
if err := coreutils.PruneBoltChainDB(path, n, 50, nil); err != nil {
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🟡 Changes recommended
A critical panic-handling issue and moderate cleanup and documentation issues remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (3)
Previously missed (1) — in code that hasn't changed since the last review.
db_test.go:44
- This test verifies the logical contents after replacement but never checks the property this API is introduced for: reclaiming the oversized Bolt file. A regression that prunes records while leaving the original file's allocated pages would pass. Record the size before pruning and assert that the resulting file is smaller.
.changeset/added_coreutilspruneboltchaindb_to_shrink_the_size_of_an_existing_consensus_database.md:5
- The generated changeset only advertises
coreutils.PruneBoltChainDB, but this PR also adds the exportedchain.CopyPrunedDBAPI. Please update the release note so downstream users are informed about both public entry points.
# Added `coreutils.PruneBoltChainDB` to shrink the size of an existing consensus database.
db.go:167
- If
bbolt.Opencreates the new file and then fails during initialization (for example, while mapping or allocating it), this branch returns without the cleanup defer below ever being installed, so the failed.tmpdatabase can remain behind despite the function's guarantee that temporary files are removed on failure. RemovetmpPathbefore returning from this error path (or install cleanup before opening it).
dst, err := bbolt.Open(tmpPath, 0600, &bbolt.Options{NoSync: true, Timeout: time.Second})
if err != nil {
return fmt.Errorf("failed to create temporary database: %w", err)
- Files reviewed: 6/6 changed files
- Comments generated: 1
- Review effort level: Lite
bc10db1 to
cfee49c
Compare
| if _, err := os.Stat(path); err != nil { | ||
| return fmt.Errorf("failed to stat database: %w", err) | ||
| } | ||
| src, err := bbolt.Open(path, 0600, &bbolt.Options{Timeout: time.Second}) |
There was a problem hiding this comment.
Since we added the stat, should we copy the original file's mode so it doesn't change after pruning. Or call os.Chmod after the rename.
peterjan
left a comment
There was a problem hiding this comment.
Looks good to me, only nit I had is the file permissions one.
| return errors.New("source database is not initialized") | ||
| } else if version[0] != 4 { | ||
| return fmt.Errorf("source database version (%d) must be migrated before pruning", version[0]) | ||
| } else if network := readBucket(ss, bNetwork).getRaw(bNetwork); string(network) != n.Name { |
There was a problem hiding this comment.
nit: len(network) != 0 && string(network) != n.Name like in NewDBStore and NewDBStoreAtCheckpoint
Prunes an existing consensus db to match the size of a newly instant synced db at the same height. This is necessary because bbolt cannot shrink the database size.