Skip to content

Conversation

@raduchis
Copy link
Contributor

@raduchis raduchis commented Feb 5, 2026

Reasoning behind the pull request

  • synching blocks on supernova is fast -> 10 blocks per second but it is still kinda slow

Proposed changes

  • looking in the logs for a meta node, commit account state took ~50-70 ms. Created an commitInMemory every 9 out of 10 blocks and the 10th block do a normal commit.

Testing procedure

  • Remove DB with and without the current branch and see that the current branch synchronizez ~5x faster

Pre-requisites

Based on the Contributing Guidelines the PR author and the reviewers must check the following requirements are met:

  • was the PR targeted to the correct branch?
  • if this is a larger feature that probably needs more than one PR, is there a feat branch created?
  • if this is a feat branch merging, do all satellite projects have a proper tag inside go.mod?

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an “in-memory commit” path to speed up node syncing by avoiding disk persistence on most blocks, while still computing root hashes and periodically performing full commits.

Changes:

  • Extend state.AccountsAdapter with CommitInMemory() and implement it across adapters/stubs.
  • Add AccountsDB.CommitInMemory() and integrate a sync-time commit interval optimization in baseProcessor.
  • Add unit tests for CommitInMemory() and for the sync commit interval decision logic.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
testscommon/state/accountsAdapterStub.go Extends accounts adapter stub with CommitInMemory() for tests.
state/interface.go Adds CommitInMemory() to AccountsAdapter interface.
state/accountsDB.go Implements CommitInMemory() and internal commitInMemory() flow.
state/accountsDB_test.go Adds tests for AccountsDB.CommitInMemory().
state/accountsDBApi.go Implements CommitInMemory() as not permitted for API adapter.
state/accountsDBApiWithHistory.go Implements CommitInMemory() as not permitted for API-with-history adapter.
process/transactionEvaluator/simulationAccountsDB.go Adds no-op CommitInMemory() for simulation DB.
epochStart/bootstrap/disabled/disabledAccountsAdapter.go Adds no-op CommitInMemory() for disabled adapter.
process/block/baseProcess.go Adds sync commit interval optimization + in-memory commit path during sync.
process/block/export_test.go Exposes constants/helpers for testing the new optimization logic.
process/block/baseProcess_test.go Adds tests for sync commit optimization and in-memory commit invocation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return nil, err
}
}
adb.dataTries.Reset()
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

commitInMemory() calls adb.dataTries.Reset(), which clears the holder map (see state/dataTriesHolder.go:70-82). This drops references to dirty data tries without committing them, so a subsequent full Commit() may no longer flush those data tries to disk, risking missing persistence / corrupted state. Consider not resetting dataTries in CommitInMemory (or tracking/retaining dirty tries until the next full commit).

Suggested change
adb.dataTries.Reset()

Copilot uses AI. Check for mistakes.
Comment on lines 2137 to 2140
if headerHandler.IsStartOfEpochBlock() {
bp.resetSyncCommitCounter()
return bp.commitInLastEpoch(headerHandler.GetEpoch())
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

In the start-of-epoch path, the deferred log will still print in memory=true because inMemory is initialized to true and never set to false before returning commitInLastEpoch(). This makes the log line misleading (epoch commits are persisted). Set inMemory=false before the early return, or initialize it to false and only set true on the in-memory path.

Copilot uses AI. Check for mistakes.
Comment on lines +3527 to +3528
accnt, _ := adb.LoadAccount(make([]byte, 32))
_ = adb.SaveAccount(accnt)
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

This test ignores the errors from LoadAccount and SaveAccount, which can mask a broken setup (e.g., TrieStub.UpdateCalled is unset so SaveAccount will error). Prefer asserting require.NoError and stubbing the trie to allow SaveAccount to succeed, so the test validates behavior under realistic conditions.

Copilot uses AI. Check for mistakes.
// Call 5 times - first 4 should return true (in-memory), 5th should return false (full commit)
for i := 0; i < 4; i++ {
result := sp.ShouldUseSyncCommitOptimization(header)
assert.True(t, result, "should return true for block %d", i+1)
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

assert.True(t, result, "should return true for block %d", i+1) will not format the message (testify doesn't treat this as printf-style). Use assert.Truef/require.Truef, or pre-format the string, to keep failure output correct.

Suggested change
assert.True(t, result, "should return true for block %d", i+1)
assert.Truef(t, result, "should return true for block %d", i+1)

Copilot uses AI. Check for mistakes.
Comment on lines +136 to +137
// CommitInMemory is a not permitted operation in this implementation and thus, will return an error
func (accountsDB *accountsDBApi) CommitInMemory() ([]byte, error) {
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

Comment grammar: "CommitInMemory is a not permitted operation" should be "CommitInMemory is not a permitted operation" (or "CommitInMemory is not permitted").

Copilot uses AI. Check for mistakes.
Comment on lines +2153 to +2156
// Disabled if syncCommitInterval is 0
if bp.syncCommitInterval == 0 {
return false
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

shouldUseSyncCommitOptimization() reads bp.syncCommitInterval without holding mutSyncCommit, but SetSyncCommitInterval() writes it under the mutex. This is an actual data race if the interval is ever updated at runtime (and also leaves blocksSinceLastCommit stale when interval is set to 0). Read syncCommitInterval under the same lock (or use atomics), and consider resetting the counter when disabling/changing the interval.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

Or if the SetSyncCommitInterval is meant to be used only in tests, move it to the export_test file.

Comment on lines +3498 to +3499
accnt, _ := adb.LoadAccount(make([]byte, 32))
_ = adb.SaveAccount(accnt)
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

This test ignores the errors from LoadAccount and SaveAccount, which can mask a broken setup (e.g., TrieStub.UpdateCalled is unset so SaveAccount will error). Prefer asserting require.NoError and stubbing the trie to allow SaveAccount to succeed, so the test validates behavior under realistic conditions.

Copilot uses AI. Check for mistakes.
Comment on lines +3585 to +3586
accnt, _ := adb.LoadAccount(make([]byte, 32))
_ = adb.SaveAccount(accnt)
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

This test ignores the errors from LoadAccount and SaveAccount, which can mask a broken setup (e.g., TrieStub.UpdateCalled is unset so SaveAccount will error). Prefer asserting require.NoError and stubbing the trie to allow SaveAccount to succeed, so the test validates behavior under realistic conditions.

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +78
// CommitInMemory is a not permitted operation in this implementation and thus, will return an error
func (accountsDB *accountsDBApiWithHistory) CommitInMemory() ([]byte, error) {
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

Comment grammar: "CommitInMemory is a not permitted operation" should be "CommitInMemory is not a permitted operation" (or "CommitInMemory is not permitted").

Copilot uses AI. Check for mistakes.
Comment on lines +2153 to +2156
// Disabled if syncCommitInterval is 0
if bp.syncCommitInterval == 0 {
return false
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Or if the SetSyncCommitInterval is meant to be used only in tests, move it to the export_test file.

return adb.commitInMemory()
}

func (adb *AccountsDB) commitInMemory() ([]byte, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

There a couple issues with this approach:

  1. The dataTries holder reset drops the reference to all of the changed data tries. When an account is loaded, it will have the new root hash, so it will try to load the data trie with that root hash from the db, but since the dataTrie was not commited, the recreate from db will fail. To fix this, you can remove the reset, but
  2. If a revert occurs, a recreateFromDb will happen - and will fail

Copy link
Contributor

Choose a reason for hiding this comment

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

Another solution would be to commit the data tries, but into a cache.

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.

2 participants