Skip to content

Trie prunning async trigger#7800

Open
ssd04 wants to merge 6 commits intofeat/supernova-async-execfrom
async-trie-prunning-trigger
Open

Trie prunning async trigger#7800
ssd04 wants to merge 6 commits intofeat/supernova-async-execfrom
async-trie-prunning-trigger

Conversation

@ssd04
Copy link
Contributor

@ssd04 ssd04 commented Mar 24, 2026

Reasoning behind the pull request

Proposed changes

Testing procedure

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?

@ssd04 ssd04 self-assigned this Mar 24, 2026
@codecov
Copy link

codecov bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 55.10204% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.54%. Comparing base (8eab550) to head (1714b93).

Files with missing lines Patch % Lines
process/common.go 0.00% 17 Missing ⚠️
process/block/baseProcess.go 87.50% 2 Missing and 1 partial ⚠️
process/block/metablock.go 50.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@                      Coverage Diff                      @@
##           feat/supernova-async-exec    #7800      +/-   ##
=============================================================
- Coverage                      77.54%   77.54%   -0.01%     
=============================================================
  Files                            882      882              
  Lines                         123683   123726      +43     
=============================================================
+ Hits                           95908    95938      +30     
- Misses                         21429    21442      +13     
  Partials                        6346     6346              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

This PR introduces an async trigger for trie pruning (especially for header v3), wiring it through the async headers execution flow and updating the relevant interfaces/mocks/stubs accordingly.

Changes:

  • Add PruneTrieAsyncHeader(header data.HeaderHandler) to block processor interfaces and implement it in the base processor.
  • Stop triggering shard header v3 pruning from shardProcessor.updateState and trigger pruning from asyncExecution/headersExecutor.
  • Add process.GetHeaderWithNonce(...) helper to fetch headers by nonce for both shard and metachain paths.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
testscommon/processMocks/blockProcessorStub.go Extend async-execution stub with PruneTrieAsyncHeader.
testscommon/blockProcessorStub.go Extend test stub with PruneTrieAsyncHeader.
process/interface.go Add PruneTrieAsyncHeader to main process.BlockProcessor interface.
process/common.go Add GetHeaderWithNonce wrapper that dispatches to meta vs shard retrieval.
process/block/shardblock_test.go Update pruning test to pass a header (not exec results slice).
process/block/shardblock.go Remove sync v3 pruning from updateState; change v3 pruning API to accept a header.
process/block/metablock.go Rename/simplify v3 pruning path and fetch previous meta header on-demand.
process/block/interface.go Extend internal blockProcessor interface with pruneTrieHeaderV3(header).
process/block/export_test.go Update exported test helper PruneTrieHeaderV3 signature; add test-only getters/setters for last pruned nonce.
process/block/baseProcess_test.go Add unit tests for PruneTrieAsyncHeader.
process/block/baseProcess.go Add async pruning logic with intermediate nonce handling + last-pruned nonce tracking.
process/asyncExecution/interface.go Add PruneTrieAsyncHeader to async execution’s BlockProcessor interface.
process/asyncExecution/headersExecutor.go Trigger async trie pruning after execution result is persisted/tracked.
integrationTests/mock/blockProcessorMock.go Extend integration mock with PruneTrieAsyncHeader.

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

header3 := &block.HeaderV3{
Nonce: 10,
}
_ = header1.SetExecutionResultsHandlers(executionResultsHandlers)
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

In this test, execution results are set on header1 (nonce 8), but the method under test is called with header3 (nonce 10). This leaves header3 without execution results handlers, so PruneTrieAsyncHeader(header3) may not trigger pruning as expected and the assertions can become incorrect/flaky. Set the execution results handlers on header3 (or call pruning on the header you populated).

Suggested change
_ = header1.SetExecutionResultsHandlers(executionResultsHandlers)
_ = header3.SetExecutionResultsHandlers(executionResultsHandlers)

Copilot uses AI. Check for mistakes.
Comment on lines +1318 to 1321
// TODO: analyse based on current header to be committed, not last committed header
prevHeaderHash := sp.getCurrentBlockHeader().GetPrevHash()
prevHeader, err := process.GetShardHeader(prevHeaderHash, sp.dataPool.Headers(), sp.marshalizer, sp.store)
if err != nil {
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

getPreviousExecutionResult() uses sp.getCurrentBlockHeader().GetPrevHash() to find the previous header. With the new async pruning flow (including pruning of intermediate nonces), pruneTrieHeaderV3() can be called for headers that are not the current committed header, so this will fetch the wrong previous header and compute incorrect previous root hashes for pruning. Pass the header being pruned (or its PrevHash) into getPreviousExecutionResult() and use header.GetPrevHash() instead.

Copilot uses AI. Check for mistakes.
Comment on lines +4078 to +4082
}

// prune trie for the provided header
bp.blockProcessor.pruneTrieHeaderV3(header)
bp.lastPrunedHeaderNonce = header.GetNonce()
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

If pruning an intermediate nonce fails (e.g. header not found and the loop continues), lastPrunedHeaderNonce is still advanced to the provided header’s nonce at the end. This permanently skips the failed intermediate nonce(s) and they will never be retried in later calls, which can lead to missing trie pruning. Consider only advancing lastPrunedHeaderNonce up to the last successfully pruned nonce, or track/retry failures instead of skipping them permanently.

Copilot uses AI. Check for mistakes.
Comment on lines +4061 to +4064
// should be available in pool, since trie prunning is triggered from
// execution flow; if there are no included blocks from execution flow
// (and not prunning triggerd) headers will not be removed from pool
intermHeader, _, err := process.GetHeaderWithNonce(
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

Spelling: several occurrences of "prunning" / "triggerd" in these comments (and the warn log below in this function) should be "pruning" / "triggered" for consistency and searchability.

Copilot uses AI. Check for mistakes.
sp.pruneTrieLegacy(headers)
} else {
sp.pruneTrieHeaderV3(currentHeader.GetExecutionResultsHandlers())
// for header v3, trie prunning is triggered in async mode from headers executor
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

Spelling: "trie prunning" should be "trie pruning".

Suggested change
// for header v3, trie prunning is triggered in async mode from headers executor
// for header v3, trie pruning is triggered in async mode from headers executor

Copilot uses AI. Check for mistakes.
Comment on lines +778 to +805
// GetHeaderWithNonce tries to get the header by nonce from pool first and if not found, searches for it through storer
func GetHeaderWithNonce(
nonce uint64,
shardId uint32,
headersCacher dataRetriever.HeadersPool,
marshalizer marshal.Marshalizer,
storageService dataRetriever.StorageService,
uint64Converter typeConverters.Uint64ByteSliceConverter,
) (data.HeaderHandler, []byte, error) {
if shardId == core.MetachainShardId {
return GetMetaHeaderWithNonce(
nonce,
headersCacher,
marshalizer,
storageService,
uint64Converter,
)
}

return GetShardHeaderWithNonce(
nonce,
shardId,
headersCacher,
marshalizer,
storageService,
uint64Converter,
)
}
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

GetHeaderWithNonce is a new public helper that adds branching behavior (meta vs shard) but currently has no direct unit tests. Since process/common_test.go already covers the underlying meta/shard helpers, consider adding a small test table for GetHeaderWithNonce to ensure the metachain branch and shard branch dispatch correctly.

Copilot uses AI. Check for mistakes.
sstanculeanu
sstanculeanu previously approved these changes Mar 25, 2026
@ssd04 ssd04 dismissed stale reviews from sstanculeanu and BeniaminDrasovean via 1714b93 March 25, 2026 15:38
)
} else {
mp.pruneTriesHeaderV3(metaBlock, prevMetaBlock)
mp.pruneTrieHeaderV3(metaBlock)
Copy link
Contributor

Choose a reason for hiding this comment

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

is this still supposed to be here?

// should be available in pool, since trie prunning is triggered from
// execution flow; if there are no included blocks from execution flow
// (and not prunning triggerd) headers will not be removed from pool
intermHeader, _, err := process.GetHeaderWithNonce(
Copy link
Contributor

Choose a reason for hiding this comment

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

can you get the headers by hash? (revert traversing and then go forward

)
if err != nil {
log.Warn("failed to get intermediate header for prunning", "error", err)
continue
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe in case of error here, should we just cancel prune for this one?
but then that header might have had more execution results
maybe simpler is just to clean up the eviction wait list and then it acts like on reset.

cc: @BeniaminDrasovean

return nil, err
}

if prevHeader.IsHeaderV3() {
Copy link
Contributor

Choose a reason for hiding this comment

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

this doesn't look ok when called repeatedly in the loop from func (sp *shardProcessor) pruneTrieHeaderV3
it always defaults to the same prevHeader, or if in the meantime the consensus advanced to a newer one.

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.

5 participants