Merge master into rc/supernova 2026.04.24#7837
Merge master into rc/supernova 2026.04.24#7837sstanculeanu wants to merge 72 commits intorc/supernovafrom
Conversation
Advisory fix 1
Co-authored-by: Darius <dariussuirab@gmail.com>
small fixes here and there. hardening.
update vm common
flags compressed
…to rc/supernova # Conflicts: # common/constants.go # common/enablers/enableEpochsHandler_test.go # config/config.go # config/tomlConfig_test.go # dataRetriever/requestHandlers/requestHandler.go # dataRetriever/requestHandlers/requestHandler_test.go # epochStart/bootstrap/metaStorageHandler.go # epochStart/bootstrap/metaStorageHandler_test.go # epochStart/bootstrap/process.go # epochStart/bootstrap/process_test.go # factory/processing/blockProcessorCreator.go # go.mod # go.sum # node/chainSimulator/process/processor.go # process/block/export_test.go # process/block/interceptedBlocks/interceptedEquivalentProof_test.go # process/block/metablock.go # process/block/metablock_test.go # process/block/pendingMb/pendingMiniBlocks.go # process/block/pendingMb/pendingMiniBlocks_test.go # process/common.go # process/coordinator/process.go # process/coordinator/process_test.go # process/errors.go # process/interceptors/factory/interceptedEquivalentProofsFactory_test.go # process/sync/baseSync_test.go
| return bootstrapHdrInfo, nil | ||
| } | ||
|
|
||
| func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeededForBootstrap) error { |
There was a problem hiding this comment.
not sure if we should remove this flow entirely, saveIntermediateMetaBlocksToStorage will save intermediate headers based on epoch start header, but i think in syncedHeaders there are also other headers that might need to be saved (from the other flows)
There was a problem hiding this comment.
added back, I think this was a merge issue
There was a problem hiding this comment.
Pull request overview
Merges master into rc/supernova 2026.04.24, bringing in protocol- and bootstrap-related changes around proofs handling, epoch-start validation, shard-data validation, and error/flag gating.
Changes:
- Tightens equivalent-proof handling by validating proofs against headers (introduces HeadersPool plumbing) and adds configurable delays for proof-by-nonce requests.
- Adds/extends epoch-start and meta/shard processing validations (epoch-start miniblock types, shard-info constraints, shard-data vs header consistency).
- Improves bootstrap/sync correctness (completing missing self-notarized headers, additional sync test coverage, miniblock execution checks).
Reviewed changes
Copilot reviewed 72 out of 73 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| vm/systemSmartContracts/validator.go | Adjusts error propagation under ConsumedGasInEconomicsFlag during BLS key registration. |
| testscommon/doubleTransactionsDetector.go | Reworks test double-tx detector to return an error instead of panicking. |
| process/sync/storageBootstrap/shardStorageBootstrapper.go | Adds no-op completeSelfNotarizedHeaders implementation for shard bootstrapper. |
| process/sync/storageBootstrap/metaStorageBootstrapper_test.go | Extends mocks for blockTracker last self-notarized header retrieval. |
| process/sync/storageBootstrap/metaStorageBootstrapper.go | Completes missing self-notarized headers during meta bootstrap from storage. |
| process/sync/storageBootstrap/interface.go | Extends bootstrapper handler interface with completeSelfNotarizedHeaders. |
| process/sync/storageBootstrap/baseStorageBootstrapper.go | Invokes completeSelfNotarizedHeaders after applying boot infos. |
| process/sync/baseSync_test.go | Adds tests ensuring missing proofs are requested and updates test stubs/imports. |
| process/sync/baseSync.go | Requests equivalent proofs when missing (hash/nonce confirmation paths). |
| process/smartContract/processorV2/process_test.go | Updates SCR-on-error tests to match new async parsing and fee behavior. |
| process/smartContract/processorV2/processV2.go | Fixes async-arg parsing, built-in execution error handling, fee accounting, and invariant handling (flag-gated). |
| process/interface.go | Updates DoubleTransactionDetector interface to return error; extends ProofsPool API. |
| process/interceptors/factory/interceptedShardHeaderDataFactory.go | Import formatting cleanup. |
| process/interceptors/factory/interceptedMetaHeaderDataFactory.go | Import formatting cleanup. |
| process/interceptors/factory/interceptedEquivalentProofsFactory_test.go | Adds HeadersPool to equivalent proofs factory args in tests. |
| process/interceptors/factory/interceptedEquivalentProofsFactory.go | Wires HeadersPool into equivalent proofs intercepted-data creation. |
| process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go | Passes HeadersPool from datapool into equivalent proofs interceptor factory. |
| process/errors.go | Adds new process errors and fixes typo (“economics”). |
| process/coordinator/process_test.go | Updates tx coordinator tests for new detector behavior and miniblock validation. |
| process/coordinator/process.go | Makes double-tx detection return an error; adds miniblock shard/type validation. |
| process/coordinator/doubleTransactionsDetector_test.go | Renames/refactors detector tests for new constructor and error-returning API. |
| process/coordinator/doubleTransactionsDetector.go | Renames detector, adds critical-vs-not-critical behavior gated by flags, returns error when enforcement active. |
| process/common.go | Adds CompleteMissingSelfNotarizedHeaders + helpers (lookback derivation). |
| process/block/shardblock.go | Propagates errors from getIndexOfFirstMiniBlockToBeExecuted. |
| process/block/preprocess/validatorInfoPreProcessor_test.go | Updates peer miniblock receiver shard expectation to AllShardId. |
| process/block/preprocess/validatorInfoPreProcessor.go | Enforces peer miniblocks are meta->all. |
| process/block/preprocess/transactions.go | Formatting-only change. |
| process/block/pendingMb/nilPendingMiniblocks.go | Import formatting cleanup. |
| process/block/metablock_test.go | Updates tests for shard-data fields and blockTracker self-notarized behavior; adds shard-data verification gating tests. |
| process/block/metablockProposal.go | Validates epoch-start shard-info is empty and epoch-start miniblock types are allowed. |
| process/block/metablock.go | Adds epoch-start validations, shard-data/header full validation (flag-gated), refined cross-shard miniblock checks, and economics checks on epoch start. |
| process/block/interceptedBlocks/interceptedEquivalentProof_test.go | Adds HeadersPool usage and new validity-path tests. |
| process/block/interceptedBlocks/interceptedEquivalentProof.go | Validates equivalent proof against the referenced header via HeadersPool before accepting. |
| process/block/export_test.go | Exposes helpers for shard-data verification tests; updates GetIndexOfFirstMiniBlockToBeExecuted signature. |
| process/block/baseProcess_test.go | Adapts tests to new double-tx detector and new getIndex signature; adds scheduled execution stub. |
| process/block/baseProcess.go | Adds FullShardDataValidationFlag to compatibility list; strengthens header/body correlation; makes getIndex return (int, error) and checks executed state. |
| node/chainSimulator/configs/configs.go | Sets RequestProofByNonceDelayMs to 0 for simulator configs. |
| node/chainSimulator/chainSimulator.go | Reorders proof broadcast after header/MB/tx broadcast and adds a small delay. |
| integrationTests/vm/txsFee/scCalls_test.go | Adds an additional tx to assert accumulated fees behavior. |
| integrationTests/testProcessorNode.go | Updates requester creation signature; switches to new DoubleTransactionsDetector. |
| integrationTests/testInitializer.go | Changes proof creation/broadcast flow to broadcast after commit; removes pre-broadcast pool injection. |
| integrationTests/testHeartbeatNode.go | Updates requester creation signature. |
| integrationTests/multiShard/endOfEpoch/startInEpoch/startInEpoch_test.go | Extends blockTracker stub with GetLastSelfNotarizedHeader. |
| go.sum | Updates VM dependency checksums. |
| go.mod | Bumps mx-chain-vm-common-go and mx-chain-vm-go versions. |
| genesis/process/shardGenesisBlockCreator.go | Switches to NewDoubleTransactionsDetector constructor/args. |
| genesis/process/metaGenesisBlockCreator.go | Switches to NewDoubleTransactionsDetector constructor/args. |
| factory/processing/processComponents.go | Passes RequestProofByNonceDelayMs-derived duration into request handler creation. |
| factory/processing/blockProcessorCreator.go | Switches to NewDoubleTransactionsDetector constructor/args. |
| epochStart/errors.go | Adds ErrNilHeadersDataPool. |
| epochStart/bootstrap/syncEpochStartMeta_test.go | Passes HeadersPool into epoch-start syncer args. |
| epochStart/bootstrap/syncEpochStartMeta.go | Adds HeadersPool to equivalent proofs factory args. |
| epochStart/bootstrap/storageProcess.go | Passes HeadersPool; threads RequestProofByNonceDelayMs into requester creation. |
| epochStart/bootstrap/process_test.go | Adds extensive tests for header sync helpers and self-notarized meta syncing. |
| epochStart/bootstrap/process.go | Refactors header sync flow, syncs additional referenced metablocks, and adds self-notarized meta syncing helpers. |
| epochStart/bootstrap/metaStorageHandler_test.go | Adds tests for pending miniblocks derivation and intermediate meta storage save path. |
| epochStart/bootstrap/metaStorageHandler.go | Derives pending miniblocks from epoch-start data; saves intermediate meta blocks; adds helper for first-pending self-notarized meta. |
| epochStart/bootstrap/interface.go | Adds HeadersPool interface. |
| epochStart/bootstrap/epochStartMetaBlockProcessor_test.go | Extends constructor tests to cover nil proofs/headers pools. |
| epochStart/bootstrap/epochStartMetaBlockProcessor.go | Requires HeadersPool, registers meta header in pool before waiting for proof (Andromeda). |
| epochStart/bootstrap/baseStorageHandler.go | Removes legacy groupMiniBlocksByShard logic (replaced by computePendingMiniBlocks). |
| dataRetriever/resolvers/trieNodeResolver.go | Fixes chunkIndex bounds check (>= maxChunks). |
| dataRetriever/requestHandlers/requestHandler_test.go | Updates constructor calls and adapts tests for async proof-by-nonce requests. |
| dataRetriever/requestHandlers/requestHandler.go | Adds requestProofByNonceDelay and delays proof-by-nonce requests asynchronously. |
| consensus/spos/worker.go | Rejects headers on consensus topic after Andromeda flag activation. |
| config/tomlConfig_test.go | Adds ConsumedGasInEconomicsFixEnableEpoch and shifts Supernova epoch in test config. |
| config/epochConfig.go | Adds FullShardDataValidationEnableEpoch and ConsumedGasInEconomicsFixEnableEpoch fields. |
| config/config.go | Adds RequestProofByNonceDelayMs to requester config. |
| common/enablers/enableEpochsHandler_test.go | Updates enable-epochs test config and activation assertions for new flags. |
| common/enablers/enableEpochsHandler.go | Registers FullShardDataValidationFlag and ConsumedGasInEconomicsFlag. |
| common/constants.go | Adds metric + new enable-epoch flags for shard-data validation and economics gas fix. |
| cmd/node/config/enableEpochs.toml | Adds FullShardDataValidationEnableEpoch and ConsumedGasInEconomicsFixEnableEpoch defaults. |
| cmd/node/config/config.toml | Adds RequestProofByNonceDelayMs config entry. |
Comments suppressed due to low confidence (1)
process/coordinator/doubleTransactionsDetector.go:67
- checkArgsDoubleTransactionsDetector validates handler compatibility only for AddFailedRelayedTxToInvalidMBsFlag, but ProcessBlockBody also calls IsFlagEnabled(RelayedTransactionsV1V2DisableFlag). Include RelayedTransactionsV1V2DisableFlag in the compatibility check to prevent using an EnableEpochsHandler implementation that doesn’t define this flag.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| go func(requestEpoch uint32) { | ||
| key := common.GetEquivalentProofNonceShardKey(headerNonce, headerShard) | ||
| if !rrh.testIfRequestIsNeeded([]byte(key), uniqueEquivalentProofSuffix) { | ||
| return | ||
| } | ||
|
|
||
| log.Debug("requesting equivalent proof by nonce from network", | ||
| "headerNonce", headerNonce, | ||
| "headerShard", headerShard, | ||
| "epoch", epoch, | ||
| ) | ||
| time.Sleep(rrh.requestProofByNonceDelay) | ||
|
|
||
| requester, err := rrh.getEquivalentProofsRequester(headerShard) | ||
| if err != nil { | ||
| log.Error("RequestEquivalentProofByNonceForEpoch.getEquivalentProofsRequester", | ||
| "error", err.Error(), | ||
| log.Debug("requesting equivalent proof by nonce from network", | ||
| "headerNonce", headerNonce, | ||
| "headerShard", headerShard, | ||
| "epoch", epoch, | ||
| ) | ||
| return | ||
| } | ||
|
|
||
| proofsRequester, ok := requester.(EquivalentProofsRequester) | ||
| if !ok { | ||
| log.Warn("wrong assertion type when creating equivalent proofs requester") | ||
| return | ||
| } | ||
| requester, err := rrh.getEquivalentProofsRequester(headerShard) | ||
| if err != nil { | ||
| log.Error("RequestEquivalentProofByNonceForEpoch.getEquivalentProofsRequester", | ||
| "error", err.Error(), | ||
| "headerNonce", headerNonce, | ||
| ) | ||
| return | ||
| } | ||
|
|
||
| rrh.whiteList.Add([][]byte{[]byte(key)}) | ||
| proofsRequester, ok := requester.(EquivalentProofsRequester) | ||
| if !ok { | ||
| log.Warn("wrong assertion type when creating equivalent proofs requester") | ||
| return | ||
| } | ||
|
|
||
| err = proofsRequester.RequestDataFromNonce([]byte(key), epoch) | ||
| if err != nil { | ||
| log.Debug("RequestEquivalentProofByNonceForEpoch.RequestDataFromNonce", | ||
| "error", err.Error(), | ||
| "headerNonce", headerNonce, | ||
| "headerShard", headerShard, | ||
| "epoch", epoch, | ||
| ) | ||
| return | ||
| } | ||
| rrh.whiteList.Add([][]byte{[]byte(key)}) | ||
|
|
||
| err = proofsRequester.RequestDataFromNonce([]byte(key), epoch) | ||
| if err != nil { | ||
| log.Debug("RequestEquivalentProofByNonceForEpoch.RequestDataFromNonce", | ||
| "error", err.Error(), | ||
| "headerNonce", headerNonce, | ||
| "headerShard", headerShard, | ||
| "epoch", epoch, | ||
| ) | ||
| return | ||
| } | ||
|
|
||
| rrh.addRequestedItems([][]byte{[]byte(key)}, uniqueEquivalentProofSuffix) | ||
| rrh.addRequestedItems([][]byte{[]byte(key)}, uniqueEquivalentProofSuffix) | ||
| }(epoch) |
There was a problem hiding this comment.
RequestEquivalentProofByNonceForEpoch now spawns a new goroutine per call and sleeps before requesting. This can create unbounded goroutine growth under load (and some callers already invoke RequestEquivalentProofByNonce in their own goroutines), increasing memory/CPU usage and making shutdown harder. Consider scheduling the delayed request via a shared timer/worker (e.g., time.AfterFunc with deduplication) instead of starting a goroutine on every request.
There was a problem hiding this comment.
intended from master
| if !check.IfNil(pair.Proof) { | ||
| time.Sleep(time.Millisecond * 5) // small delay to ensure proof is not dropped as being received before header | ||
| err = s.nodes[shardID].GetBroadcastMessenger().BroadcastEquivalentProof(pair.Proof, pair.LeaderKey) | ||
| if err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
The chain simulator introduces a hard-coded 5ms sleep before broadcasting equivalent proofs to avoid them being dropped when received before the header. This timing-based workaround is fragile across different environments and can still flake under load/slow CI. Prefer an explicit ordering/ack mechanism (or reusing the configurable RequestProofByNonceDelayMs) rather than a fixed sleep.
There was a problem hiding this comment.
intended from master
| if !v.enableEpochsHandler.IsFlagEnabled(common.ConsumedGasInEconomicsFlag) { | ||
| return nil, nil, err | ||
| } | ||
| return nil, nil, errExec |
There was a problem hiding this comment.
In the errExec != nil branch, the function returns err when ConsumedGasInEconomicsFlag is disabled. At this point err is the earlier error from getNewValidKeys (and is nil here), so this path can silently swallow the staking SC execution error and allow the caller to continue as if registration succeeded. Return the actual execution error (or another non-nil error that preserves legacy behavior) instead of err.
There was a problem hiding this comment.
expected from master
| errCheck := sc.checkSCRSizeInvariant(scrTxs) | ||
| if errCheck != nil { | ||
| return nil, err | ||
| if !sc.enableEpochsHandler.IsFlagEnabled(common.ConsumedGasInEconomicsFlag) { | ||
| return nil, err | ||
| } | ||
| return nil, errCheck |
There was a problem hiding this comment.
errCheck is the result of checkSCRSizeInvariant, but when it’s non-nil the code returns err in the flag-disabled branch. Here err is the previous error variable and will be nil, so this can return (nil, nil) and hide an invariant violation. Return errCheck (or propagate it consistently) in this branch as well, and avoid returning a nil error with a nil SCR slice.
There was a problem hiding this comment.
expected from master
| return err | ||
| } | ||
|
|
||
| if mbHdr.GetTypeInt32() != int32(miniBlock.Type) { |
There was a problem hiding this comment.
This check is missing from checkHeaderBodyCorrelationProposal which is used for Supernova
There was a problem hiding this comment.
this is already handled in another fixes branch for Supernova
| return nil | ||
| } | ||
|
|
||
| func (tc *transactionCoordinator) checkMiniBlock( |
There was a problem hiding this comment.
For Supernova this is called from ProcessBlockProposal. Should it be also added or moved to VerifyBlockProposal?
There was a problem hiding this comment.
added a TODO as it will require a bigger refactor
| return err | ||
| } | ||
|
|
||
| err = mp.verifyAccumulatedFeesInEpochOnEpochStart(header) |
There was a problem hiding this comment.
This check is also missing from the Supernova execution flow.
There was a problem hiding this comment.
not needed for supernova
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:
featbranch created?featbranch merging, do all satellite projects have a proper tag insidego.mod?