Skip to content

Conversation

@sstanculeanu
Copy link
Collaborator

Reasoning behind the pull request

  • when some pending mini blocks from a different meta were added into the proposal, after selecting the outgoing transactions, the second meta header was not referenced on the proposal

Proposed changes

  • save more pending mini blocks and reference all new meta headers where needed

Testing procedure

  • with feat branch

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?

@sstanculeanu sstanculeanu self-assigned this Dec 23, 2025
…ersx/mx-chain-go into fix-multiple-headers-not-being-referenced

# Conflicts:
#	process/block/gasConsumption.go
#	testscommon/gasComputationMock.go
@codecov
Copy link

codecov bot commented Dec 23, 2025

Codecov Report

❌ Patch coverage is 83.07692% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.66%. Comparing base (49af3c3) to head (75782c2).
⚠️ Report is 11 commits behind head on feat/supernova-async-exec.

Files with missing lines Patch % Lines
process/block/gasConsumption.go 80.64% 4 Missing and 2 partials ⚠️
process/block/shardblockProposal.go 83.87% 2 Missing and 3 partials ⚠️
Additional details and impacted files
@@                    Coverage Diff                     @@
##           feat/supernova-async-exec    #7581   +/-   ##
==========================================================
  Coverage                      77.66%   77.66%           
==========================================================
  Files                            874      874           
  Lines                         120635   120689   +54     
==========================================================
+ Hits                           93694    93739   +45     
- Misses                         20768    20777    +9     
  Partials                        6173     6173           

☔ 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 fixes an issue where multiple meta headers were not being properly referenced in proposals when pending mini blocks from different meta blocks were added. The fix ensures that when outgoing transactions are selected and pending mini blocks are included, all corresponding meta headers are tracked and referenced.

Key Changes:

  • Added a new method CanAddPendingIncomingMiniBlocks() to the GasComputation interface to check if more pending mini blocks can fit in the remaining block space
  • Introduced pendingMiniBlocksAfterSelection struct to associate pending mini blocks with their originating meta headers
  • Enhanced the logic to reference all meta headers when pending mini blocks are added after transaction selection
  • Added comprehensive test coverage for the new gas computation check

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
process/interface.go Added CanAddPendingIncomingMiniBlocks() method to GasComputation interface
testscommon/gasComputationMock.go Mock implementation of the new interface method
process/coordinator/processProposal.go Fixed transaction count calculation when mini blocks become pending; corrected typo in comment
process/coordinator/processProposal_test.go Updated comment typo and adjusted expected transaction count in test
process/block/shardblockProposal.go Core fix: tracks pending mini blocks with their headers and references all headers when pending blocks are added
process/block/shardblockProposal_test.go Enhanced test to verify multiple meta headers are referenced correctly
process/block/gasConsumption.go Implemented pending gas tracking and the new CanAddPendingIncomingMiniBlocks() method
process/block/gasConsumption_test.go Added comprehensive tests for the new gas computation functionality
process/block/export_test.go Exported internal types and methods for testing

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

Comment on lines +541 to +545
pendingMiniBlocks = append(pendingMiniBlocks, &pendingMiniBlocksAfterSelection{
headerHash: currentMetaBlockHash,
header: currentMetaBlock,
pendingMiniBlocksAndHashes: createIncomingMbsResult.PendingMiniBlocks,
})
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The code unconditionally appends to pendingMiniBlocks even when createIncomingMbsResult.PendingMiniBlocks is empty. This could result in appending unnecessary empty entries to the slice. Consider only appending when there are actual pending mini blocks to track.

Suggested change
pendingMiniBlocks = append(pendingMiniBlocks, &pendingMiniBlocksAfterSelection{
headerHash: currentMetaBlockHash,
header: currentMetaBlock,
pendingMiniBlocksAndHashes: createIncomingMbsResult.PendingMiniBlocks,
})
if len(createIncomingMbsResult.PendingMiniBlocks) > 0 {
pendingMiniBlocks = append(pendingMiniBlocks, &pendingMiniBlocksAfterSelection{
headerHash: currentMetaBlockHash,
header: currentMetaBlock,
pendingMiniBlocksAndHashes: createIncomingMbsResult.PendingMiniBlocks,
})
}

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

should be ok

hashStr := string(mb.GetHash())
gc.transactionsForPendingMiniBlocks[hashStr] = transactions[hashStr]

transactionsForMB, found := transactions[string(mb.GetHash())]
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 merge this line and L128?

both appear to be reading the same transactions

e.g do the gc.transactionsForPendingMiniBlocks[hashStr] = transactionsForMB after the !found check?
or do we need to set nil explicitly in the map?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated, missed it


gasConsumedByIncomingAfter := gc.totalGasConsumed[incoming]
gasConsumedByMiniBlock := gasConsumedByIncomingAfter - gasConsumedByIncomingBefore
if gasConsumedByMiniBlock < gc.totalGasConsumed[pending] {
Copy link
Contributor

Choose a reason for hiding this comment

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

for the last pending miniblock I think this condition would be equal.

this relates to the comment below

// should never be false

but for the last one, it will be false.

maybe the conditon should be <= gc.totalGasConsumed[pending]

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated

gasConsumedByPendingMb, errCheckPending := gc.checkGasConsumedByMiniBlock(mb, transactionsForMB)
if errCheckPending != nil {
log.Warn("failed to check gas consumed by pending mini block", "hash", mb.GetHash(), "error", errCheckPending)
continue
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it should break instead of continuing, as that means that it can create miniblock gaps when there's a problem, which would not be ok.

Same with the above continue, I think it should break there as well, as we don't want to create gaps.

Or even better returning error instead of breaking, as we rely now on the computed pending miniblocks consumed gas in the next steps.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

right, updated

}

for referencedHash, referencedHeader := range extraHeadersReferenced {
sp.miniBlocksSelectionSession.AddReferencedHeader(referencedHeader, []byte(referencedHash))
Copy link
Contributor

Choose a reason for hiding this comment

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

the miniblockSelectionSession assumes the referenced headers are added in order, and here you are iterating over a map which does not ensure a specific iteration order.

Can you ensure that the AddReferencedHeader is called in the order of referencing the metablocks? maybe adding the reference into the above loop?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated as suggested


gasLeft := maxGasLimitPerBlock - totalGasConsumed
maxGasLimitPerMiniBlock := gc.maxGasLimitPerMiniBlock(gc.shardCoordinator.SelfId())
return totalGasToBeConsumedByPending+maxGasLimitPerMiniBlock < gasLeft
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we add the maxGasLimitPerMiniBlock to the total gas to be consumed by pending?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this method checks if there is space for one more mini block left in the block.. checking against the max gas limit, as it does not receive a specific mini block to know how much it would consume

Copy link
Contributor

Choose a reason for hiding this comment

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

but the miniblock does not necessarily need to be of max size, it can be of any size below the maximum size.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

removed it

return nil
}

func getIndexOfPendingMiniBlock(
Copy link
Contributor

Choose a reason for hiding this comment

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

this is called getIndexOfPending.... but it is not getting any index right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

renamed

@sstanculeanu sstanculeanu merged commit 80647ed into feat/supernova-async-exec Dec 30, 2025
13 checks passed
@sstanculeanu sstanculeanu deleted the fix-multiple-headers-not-being-referenced branch December 30, 2025 08:28
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.

4 participants