Skip to content

Prune existing consensus db - #474

Open
n8mgr wants to merge 2 commits into
masterfrom
nate/db-prune
Open

n8mgr wants to merge 2 commits into
masterfrom
nate/db-prune

Conversation

@n8mgr

@n8mgr n8mgr commented Sep 15, 2026

Copy link
Copy Markdown
Member

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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.Rename cannot 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.

Comment thread chain/prune.go
Comment thread db.go
Copilot AI review requested due to automatic review settings September 15, 2026 17:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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

Comment thread db.go
Copilot AI review requested due to automatic review settings September 15, 2026 17:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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 exported chain.CopyPrunedDB API. 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

Comment thread chain/prune.go
Copilot AI review requested due to automatic review settings September 15, 2026 17:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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 exported chain.CopyPrunedDB API. Please edit the release note so consumers of the chain package are told about both public additions.
# Added `coreutils.PruneBoltChainDB` to shrink the size of an existing consensus database.

db.go:179

  • Closing src releases bbolt's exclusive lock before the rename. A second call can acquire the lock, remove/recreate this same .tmp path, 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 through os.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

Comment thread db.go
Copilot AI review requested due to automatic review settings September 15, 2026 18:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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 exported chain.CopyPrunedDB API. 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.Open creates 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 .tmp database can remain behind despite the function's guarantee that temporary files are removed on failure. Remove tmpPath before 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

Comment thread chain/prune.go
Comment thread chain/prune.go
Copilot AI review requested due to automatic review settings September 16, 2026 15:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread db.go
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})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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 peterjan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me, only nit I had is the file permissions one.

Comment thread chain/prune.go
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 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: len(network) != 0 && string(network) != n.Name like in NewDBStore and NewDBStoreAtCheckpoint

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

6 participants