From a40d8e39e59adbc25342d723d262fce19d92834d Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Fri, 17 Oct 2025 12:07:53 +0300 Subject: [PATCH 01/51] update trigger removing the current round. --- .../disabled/disabledEpochStartTrigger.go | 7 +--- epochStart/interface.go | 3 +- epochStart/metachain/trigger.go | 33 +++++-------------- epochStart/metachain/triggerRegistry.go | 3 +- epochStart/shardchain/trigger.go | 9 ++--- factory/mock/epochStartTriggerStub.go | 15 +++------ .../mock/endOfEpochTriggerStub.go | 15 +++------ node/mock/endOfEpochTriggerStub.go | 14 ++------ process/interface.go | 3 +- process/mock/endOfEpochTriggerStub.go | 14 ++------ testscommon/epochStartTriggerStub.go | 14 ++------ 11 files changed, 32 insertions(+), 98 deletions(-) diff --git a/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go b/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go index 4a5c64680d9..b5fbc67fa6e 100644 --- a/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go +++ b/epochStart/bootstrap/disabled/disabledEpochStartTrigger.go @@ -22,13 +22,8 @@ func (e *epochStartTrigger) ShouldProposeEpochChange(_ uint64, _ uint64) bool { return false } -// UpdateRound - -func (e *epochStartTrigger) UpdateRound(_ uint64) { - -} - // SetEpochChange - -func (e *epochStartTrigger) SetEpochChange() {} +func (e *epochStartTrigger) SetEpochChange(_ uint64) {} // ReceivedHeader - func (e *epochStartTrigger) ReceivedHeader(_ data.HeaderHandler) { diff --git a/epochStart/interface.go b/epochStart/interface.go index d86c52e5518..9f75157381e 100644 --- a/epochStart/interface.go +++ b/epochStart/interface.go @@ -21,8 +21,7 @@ type TriggerHandler interface { Epoch() uint32 MetaEpoch() uint32 Update(round uint64, nonce uint64) - UpdateRound(round uint64) - SetEpochChange() + SetEpochChange(round uint64) ShouldProposeEpochChange(round uint64, nonce uint64) bool EpochStartRound() uint64 EpochStartMetaHdrHash() []byte diff --git a/epochStart/metachain/trigger.go b/epochStart/metachain/trigger.go index ce16e66c383..a1e8b06a596 100644 --- a/epochStart/metachain/trigger.go +++ b/epochStart/metachain/trigger.go @@ -15,13 +15,14 @@ import ( "github.com/multiversx/mx-chain-core-go/display" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/storage" - logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("epochStart/metachain") @@ -54,7 +55,6 @@ type trigger struct { isEpochStart bool epoch uint32 epochStartMeta data.HeaderHandler - currentRound uint64 epochFinalityAttestingRound uint64 currEpochStartRound uint64 prevEpochStartRound uint64 @@ -212,14 +212,6 @@ func (t *trigger) getMinRoundsBetweenEpochs(epoch uint32) uint64 { return uint64(chainParametersForEpoch.MinRoundsBetweenEpochs) } -// UpdateRound will set the current round -func (t *trigger) UpdateRound(round uint64) { - t.mutTrigger.Lock() - defer t.mutTrigger.Unlock() - - t.currentRound = round -} - // ShouldProposeEpochChange will return true if an epoch change event should be trigger func (t *trigger) ShouldProposeEpochChange(currentRound uint64, currentNonce uint64) bool { t.mutTrigger.RLock() @@ -241,33 +233,30 @@ func (t *trigger) shouldTriggerEpochStart(currentRound uint64, currentNonce uint func (t *trigger) Update(round uint64, nonce uint64) { t.mutTrigger.Lock() defer t.mutTrigger.Unlock() - - t.currentRound = round - if t.isEpochStart { return } if t.shouldTriggerEpochStart(round, nonce) { - t.setEpochChange() + t.setEpochChange(round) } } // SetEpochChange will increment the epoch field and all fields related with epoch change -func (t *trigger) SetEpochChange() { +func (t *trigger) SetEpochChange(round uint64) { t.mutTrigger.Lock() defer t.mutTrigger.Unlock() - t.setEpochChange() + t.setEpochChange(round) } -func (t *trigger) setEpochChange() { +func (t *trigger) setEpochChange(round uint64) { t.epoch += 1 t.isEpochStart = true t.prevEpochStartRound = t.currEpochStartRound - t.currEpochStartRound = t.currentRound + t.currEpochStartRound = round - msg := fmt.Sprintf("EPOCH %d BEGINS IN ROUND (%d)", t.epoch, t.currentRound) + msg := fmt.Sprintf("EPOCH %d BEGINS IN ROUND (%d)", t.epoch, t.currEpochStartRound) log.Debug(display.Headline(msg, "", "#")) log.Debug("trigger.Update", "isEpochStart", t.isEpochStart) logger.SetCorrelationEpoch(t.epoch) @@ -300,7 +289,6 @@ func (t *trigger) SetProcessed(header data.HeaderHandler, body data.BodyHandler) t.currEpochStartRound = metaBlock.Round t.epoch = metaBlock.Epoch t.isEpochStart = false - t.currentRound = metaBlock.Round t.epochStartMeta = metaBlock t.epochStartMetaHash = metaHash @@ -367,10 +355,6 @@ func (t *trigger) RevertStateToBlock(header data.HeaderHandler) error { return err } - t.mutTrigger.Lock() - t.currentRound = header.GetRound() - t.mutTrigger.Unlock() - return nil } @@ -500,7 +484,6 @@ func (t *trigger) SetEpochStartMetaHdrHash(metaHdrHash []byte) { func (t *trigger) SetCurrentEpochStartRound(round uint64) { t.mutTrigger.Lock() t.currEpochStartRound = round - t.currentRound = round t.saveCurrentState(round) t.mutTrigger.Unlock() } diff --git a/epochStart/metachain/triggerRegistry.go b/epochStart/metachain/triggerRegistry.go index 82451e9aae9..badac850bc6 100644 --- a/epochStart/metachain/triggerRegistry.go +++ b/epochStart/metachain/triggerRegistry.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/epochStart" ) @@ -26,7 +27,6 @@ func (t *trigger) LoadState(key []byte) error { t.mutTrigger.Lock() t.triggerStateKey = key - t.currentRound = state.CurrentRound t.epochFinalityAttestingRound = state.EpochFinalityAttestingRound t.currEpochStartRound = state.CurrEpochStartRound t.prevEpochStartRound = state.PrevEpochStartRound @@ -64,7 +64,6 @@ func (t *trigger) saveState(key []byte) error { return epochStart.ErrWrongTypeAssertion } registry := &block.MetaTriggerRegistry{} - registry.CurrentRound = t.currentRound registry.EpochFinalityAttestingRound = t.epochFinalityAttestingRound registry.CurrEpochStartRound = t.currEpochStartRound registry.PrevEpochStartRound = t.prevEpochStartRound diff --git a/epochStart/shardchain/trigger.go b/epochStart/shardchain/trigger.go index 2f28b423488..1db78124c66 100644 --- a/epochStart/shardchain/trigger.go +++ b/epochStart/shardchain/trigger.go @@ -19,12 +19,13 @@ import ( "github.com/multiversx/mx-chain-core-go/display" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/storage" - logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("epochStart/shardchain") @@ -1231,12 +1232,8 @@ func (t *trigger) GetSavedStateKey() []byte { func (t *trigger) Update(_ uint64, _ uint64) { } -// UpdateRound will do nothing -func (t *trigger) UpdateRound(_ uint64) { -} - // SetEpochChange will do nothing -func (t *trigger) SetEpochChange() { +func (t *trigger) SetEpochChange(_ uint64) { } // ShouldProposeEpochChange will always return false diff --git a/factory/mock/epochStartTriggerStub.go b/factory/mock/epochStartTriggerStub.go index 4687fc68f98..17d5409030f 100644 --- a/factory/mock/epochStartTriggerStub.go +++ b/factory/mock/epochStartTriggerStub.go @@ -4,6 +4,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/epochStart" ) @@ -20,21 +21,13 @@ type EpochStartTriggerStub struct { ProcessedCalled func(header data.HeaderHandler) EpochStartRoundCalled func() uint64 ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool - UpdateRoundCalled func(round uint64) - SetEpochChangeCalled func() -} - -// UpdateRound - -func (e *EpochStartTriggerStub) UpdateRound(round uint64) { - if e.UpdateRoundCalled != nil { - e.UpdateRoundCalled(round) - } + SetEpochChangeCalled func(round uint64) } // SetEpochChange - -func (e *EpochStartTriggerStub) SetEpochChange() { +func (e *EpochStartTriggerStub) SetEpochChange(round uint64) { if e.SetEpochChangeCalled != nil { - e.SetEpochChangeCalled() + e.SetEpochChangeCalled(round) } } diff --git a/integrationTests/mock/endOfEpochTriggerStub.go b/integrationTests/mock/endOfEpochTriggerStub.go index 956825f9c2e..13f78aedf5e 100644 --- a/integrationTests/mock/endOfEpochTriggerStub.go +++ b/integrationTests/mock/endOfEpochTriggerStub.go @@ -4,6 +4,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/epochStart" ) @@ -20,21 +21,13 @@ type EpochStartTriggerStub struct { ProcessedCalled func(header data.HeaderHandler) EpochStartRoundCalled func() uint64 ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool - UpdateRoundCalled func(round uint64) - SetEpochChangeCalled func() -} - -// UpdateRound - -func (e *EpochStartTriggerStub) UpdateRound(round uint64) { - if e.UpdateRoundCalled != nil { - e.UpdateRoundCalled(round) - } + SetEpochChangeCalled func(round uint64) } // SetEpochChange - -func (e *EpochStartTriggerStub) SetEpochChange() { +func (e *EpochStartTriggerStub) SetEpochChange(round uint64) { if e.SetEpochChangeCalled != nil { - e.SetEpochChangeCalled() + e.SetEpochChangeCalled(round) } } diff --git a/node/mock/endOfEpochTriggerStub.go b/node/mock/endOfEpochTriggerStub.go index 4a86a81352b..b695a90a45e 100644 --- a/node/mock/endOfEpochTriggerStub.go +++ b/node/mock/endOfEpochTriggerStub.go @@ -19,21 +19,13 @@ type EpochStartTriggerStub struct { ProcessedCalled func(header data.HeaderHandler) EpochStartRoundCalled func() uint64 ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool - UpdateRoundCalled func(round uint64) - SetEpochChangeCalled func() -} - -// UpdateRound - -func (e *EpochStartTriggerStub) UpdateRound(round uint64) { - if e.UpdateRoundCalled != nil { - e.UpdateRoundCalled(round) - } + SetEpochChangeCalled func(round uint64) } // SetEpochChange - -func (e *EpochStartTriggerStub) SetEpochChange() { +func (e *EpochStartTriggerStub) SetEpochChange(round uint64) { if e.SetEpochChangeCalled != nil { - e.SetEpochChangeCalled() + e.SetEpochChangeCalled(round) } } diff --git a/process/interface.go b/process/interface.go index b49081fe4e4..f0a3199c8ed 100644 --- a/process/interface.go +++ b/process/interface.go @@ -516,8 +516,7 @@ type VirtualMachinesContainerFactory interface { // EpochStartTriggerHandler defines that actions which are needed by processor for start of epoch type EpochStartTriggerHandler interface { Update(round uint64, nonce uint64) - UpdateRound(round uint64) - SetEpochChange() + SetEpochChange(round uint64) ShouldProposeEpochChange(round uint64, nonce uint64) bool IsEpochStart() bool Epoch() uint32 diff --git a/process/mock/endOfEpochTriggerStub.go b/process/mock/endOfEpochTriggerStub.go index a190b63b492..3b66a6dd411 100644 --- a/process/mock/endOfEpochTriggerStub.go +++ b/process/mock/endOfEpochTriggerStub.go @@ -21,21 +21,13 @@ type EpochStartTriggerStub struct { EpochFinalityAttestingRoundCalled func() uint64 EpochStartMetaHdrHashCalled func() []byte ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool - UpdateRoundCalled func(round uint64) - SetEpochChangeCalled func() -} - -// UpdateRound - -func (e *EpochStartTriggerStub) UpdateRound(round uint64) { - if e.UpdateRoundCalled != nil { - e.UpdateRoundCalled(round) - } + SetEpochChangeCalled func(round uint64) } // SetEpochChange - -func (e *EpochStartTriggerStub) SetEpochChange() { +func (e *EpochStartTriggerStub) SetEpochChange(round uint64) { if e.SetEpochChangeCalled != nil { - e.SetEpochChangeCalled() + e.SetEpochChangeCalled(round) } } diff --git a/testscommon/epochStartTriggerStub.go b/testscommon/epochStartTriggerStub.go index 4a2de6e9ecc..2578dd62d59 100644 --- a/testscommon/epochStartTriggerStub.go +++ b/testscommon/epochStartTriggerStub.go @@ -21,21 +21,13 @@ type EpochStartTriggerStub struct { EpochFinalityAttestingRoundCalled func() uint64 EpochStartMetaHdrHashCalled func() []byte ShouldProposeEpochChangeCalled func(round uint64, nonce uint64) bool - UpdateRoundCalled func(round uint64) - SetEpochChangeCalled func() -} - -// UpdateRound - -func (e *EpochStartTriggerStub) UpdateRound(round uint64) { - if e.UpdateRoundCalled != nil { - e.UpdateRoundCalled(round) - } + SetEpochChangeCalled func(round uint64) } // SetEpochChange - -func (e *EpochStartTriggerStub) SetEpochChange() { +func (e *EpochStartTriggerStub) SetEpochChange(round uint64) { if e.SetEpochChangeCalled != nil { - e.SetEpochChangeCalled() + e.SetEpochChangeCalled(round) } } From 9feb6b17573e856d7217f0c911949864aa668859 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Fri, 17 Oct 2025 17:58:24 +0300 Subject: [PATCH 02/51] update create new block header and sketch meta block proposal --- epochStart/metachain/triggerRegistry_test.go | 7 +- epochStart/metachain/trigger_test.go | 18 +-- process/block/baseProcess.go | 63 ++++++++- process/block/metablock.go | 18 +-- process/block/metablockProposal.go | 130 +++++++++++++++++++ process/block/metablock_test.go | 37 +++++- process/block/shardblockProposal.go | 83 ++++-------- process/block/shardblockProposal_test.go | 2 +- 8 files changed, 255 insertions(+), 103 deletions(-) diff --git a/epochStart/metachain/triggerRegistry_test.go b/epochStart/metachain/triggerRegistry_test.go index 33a4afe5ed5..e2689eef849 100644 --- a/epochStart/metachain/triggerRegistry_test.go +++ b/epochStart/metachain/triggerRegistry_test.go @@ -6,12 +6,13 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/storage" "github.com/multiversx/mx-chain-go/testscommon/genericMocks" storageStubs "github.com/multiversx/mx-chain-go/testscommon/storage" - "github.com/stretchr/testify/require" ) func cloneTrigger(t *trigger) *trigger { @@ -19,7 +20,6 @@ func cloneTrigger(t *trigger) *trigger { rt.isEpochStart = t.isEpochStart rt.epoch = t.epoch - rt.currentRound = t.currentRound rt.epochFinalityAttestingRound = t.epochFinalityAttestingRound rt.currEpochStartRound = t.currEpochStartRound rt.prevEpochStartRound = t.prevEpochStartRound @@ -59,7 +59,6 @@ func TestTrigger_LoadStateAfterSave(t *testing.T) { key := []byte("key") epochStartTrigger1.triggerStateKey = key epochStartTrigger1.epoch = 6 - epochStartTrigger1.currentRound = 1000 epochStartTrigger1.epochFinalityAttestingRound = 998 epochStartTrigger1.currEpochStartRound = 800 epochStartTrigger1.prevEpochStartRound = 650 @@ -92,7 +91,6 @@ func TestTrigger_LoadStateBackwardsCompatibility(t *testing.T) { key := []byte("key") epochStartTrigger1.triggerStateKey = key epochStartTrigger1.epoch = 6 - epochStartTrigger1.currentRound = 1000 epochStartTrigger1.epochFinalityAttestingRound = 998 epochStartTrigger1.currEpochStartRound = 800 epochStartTrigger1.prevEpochStartRound = 650 @@ -124,7 +122,6 @@ func createLegacyTriggerRegistryFromTrigger(t *trigger) *legacyTriggerRegistry { metaBlock, _ := t.epochStartMeta.(*block.MetaBlock) return &legacyTriggerRegistry{ Epoch: t.epoch, - CurrentRound: t.currentRound, EpochFinalityAttestingRound: t.epochFinalityAttestingRound, CurrEpochStartRound: t.currEpochStartRound, PrevEpochStartRound: t.prevEpochStartRound, diff --git a/epochStart/metachain/trigger_test.go b/epochStart/metachain/trigger_test.go index 84c2a195d91..8bf3f146fa5 100644 --- a/epochStart/metachain/trigger_test.go +++ b/epochStart/metachain/trigger_test.go @@ -11,6 +11,9 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/epochStart" @@ -23,8 +26,6 @@ import ( statusHandlerMock "github.com/multiversx/mx-chain-go/testscommon/statusHandler" storageStubs "github.com/multiversx/mx-chain-go/testscommon/storage" vic "github.com/multiversx/mx-chain-go/testscommon/validatorInfoCacher" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func createMockEpochStartTriggerArguments() *ArgsNewMetaEpochStartTrigger { @@ -168,18 +169,13 @@ func TestNewEpochStartTrigger_UpdateRoundAndSetEpochChange(t *testing.T) { require.Nil(t, err) epoch := uint32(0) - round := uint64(0) + round := uint64(2) nonce := uint64(100) - epochStartTrigger.UpdateRound(round) - round++ - epochStartTrigger.UpdateRound(round) - round++ - epochStartTrigger.UpdateRound(round) shouldProposeEpochChange := epochStartTrigger.ShouldProposeEpochChange(round, nonce) require.True(t, shouldProposeEpochChange) - epochStartTrigger.SetEpochChange() + epochStartTrigger.SetEpochChange(round) currentEpoch := epochStartTrigger.Epoch() require.Equal(t, epoch+1, currentEpoch) require.True(t, epochStartTrigger.IsEpochStart()) @@ -228,7 +224,6 @@ func TestTrigger_ForceEpochStartCloseToNormalEpochStartShouldNotForce(t *testing arguments := createMockEpochStartTriggerArguments() epochStartTrigger, _ := NewEpochStartTrigger(arguments) - epochStartTrigger.currentRound = 20 epochStartTrigger.ForceEpochStart(201) assert.Equal(t, uint64(math.MaxUint64), epochStartTrigger.nextEpochStartRound) @@ -247,7 +242,6 @@ func TestTrigger_ForceEpochStartUnderMinimumBetweenEpochs(t *testing.T) { }, } epochStartTrigger, _ := NewEpochStartTrigger(arguments) - epochStartTrigger.currentRound = 1 epochStartTrigger.ForceEpochStart(10) assert.Equal(t, uint64(20), epochStartTrigger.nextEpochStartRound) @@ -271,8 +265,6 @@ func TestTrigger_ForceEpochStartShouldOk(t *testing.T) { epochStartTrigger, err := NewEpochStartTrigger(arguments) require.Nil(t, err) - epochStartTrigger.currentRound = 50 - expectedRound := uint64(60) epochStartTrigger.ForceEpochStart(60) diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index d19642ea7b2..1163b7685e7 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -20,6 +20,8 @@ import ( "github.com/multiversx/mx-chain-core-go/display" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + nodeFactory "github.com/multiversx/mx-chain-go/cmd/node/factory" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/errChan" @@ -43,7 +45,6 @@ import ( "github.com/multiversx/mx-chain-go/state/parsers" "github.com/multiversx/mx-chain-go/storage" "github.com/multiversx/mx-chain-go/storage/storageunit" - logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("process/block") @@ -2659,3 +2660,63 @@ func getStorageUnitFromBlockType(blockType block.Type) (dataRetriever.UnitType, } return 0, process.ErrInvalidBlockType } + +func (bp *baseProcessor) checkInclusionEstimationForExecutionResults(header data.HeaderHandler) error { + prevBlockLastExecutionResult, err := process.GetPrevBlockLastExecutionResult(bp.blockChain) + if err != nil { + return err + } + + lastResultData, err := process.CreateDataForInclusionEstimation(prevBlockLastExecutionResult) + if err != nil { + return err + } + executionResults := header.GetExecutionResultsHandlers() + allowed := bp.executionResultsInclusionEstimator.Decide(lastResultData, executionResults, header.GetRound()) + if allowed != len(executionResults) { + log.Warn("number of execution results included in the header is not correct", + "expected", allowed, + "actual", len(executionResults), + ) + return process.ErrInvalidNumberOfExecutionResultsInHeader + } + + return nil +} + +func (bp *baseProcessor) addExecutionResultsOnHeader(header data.HeaderHandler) error { + pendingExecutionResults, err := bp.executionResultsTracker.GetPendingExecutionResults() + if err != nil { + return err + } + + lastExecutionResultHandler, err := process.GetPrevBlockLastExecutionResult(bp.blockChain) + if err != nil { + return err + } + + lastNotarizedExecutionResultInfo, err := process.CreateDataForInclusionEstimation(lastExecutionResultHandler) + if err != nil { + return err + } + + var lastExecutionResultForCurrentBlock data.LastExecutionResultHandler + numToInclude := bp.executionResultsInclusionEstimator.Decide(lastNotarizedExecutionResultInfo, pendingExecutionResults, header.GetRound()) + + executionResultsToInclude := pendingExecutionResults[:numToInclude] + lastExecutionResultForCurrentBlock = lastExecutionResultHandler + if len(executionResultsToInclude) > 0 { + lastExecutionResult := executionResultsToInclude[len(executionResultsToInclude)-1] + lastExecutionResultForCurrentBlock, err = process.CreateLastExecutionResultInfoFromExecutionResult(header.GetRound(), lastExecutionResult, bp.shardCoordinator.SelfId()) + if err != nil { + return err + } + } + + err = header.SetLastExecutionResultHandler(lastExecutionResultForCurrentBlock) + if err != nil { + return err + } + + return header.SetExecutionResultsHandlers(executionResultsToInclude) +} diff --git a/process/block/metablock.go b/process/block/metablock.go index 7df526c23f7..9034c52ce6e 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -319,15 +319,6 @@ func (mp *metaProcessor) ProcessBlock( return nil } -// TODO: move this to the ProcessBlockProposal for meta chain -func (mp *metaProcessor) updateEpochStartTrigger(round, nonce uint64) { - if common.IsAsyncExecutionEnabled(mp.enableEpochsHandler, mp.enableRoundsHandler) { - mp.epochStartTrigger.UpdateRound(round) - } else { - mp.epochStartTrigger.Update(round, nonce) - } -} - func (mp *metaProcessor) processEpochStartMetaBlock( header *block.MetaBlock, body *block.Body, @@ -2205,9 +2196,7 @@ func (mp *metaProcessor) verifyValidatorStatisticsRootHash(header *block.MetaBlo // CreateNewHeader creates a new header func (mp *metaProcessor) CreateNewHeader(round uint64, nonce uint64) (data.HeaderHandler, error) { - mp.updateEpochStartTrigger(round, nonce) - - epochChangeProposed := mp.epochStartTrigger.ShouldProposeEpochChange(round, nonce) + mp.epochStartTrigger.Update(round, nonce) epoch := mp.epochStartTrigger.Epoch() header := mp.versionedHeaderFactory.Create(epoch, round) @@ -2217,7 +2206,7 @@ func (mp *metaProcessor) CreateNewHeader(round uint64, nonce uint64) (data.Heade } if metaHeader.IsHeaderV3() { - metaHeader.SetEpochChangeProposed(epochChangeProposed) + return nil, process.ErrInvalidHeader } err := metaHeader.SetRound(round) @@ -2278,9 +2267,6 @@ func (mp *metaProcessor) setHeaderVersionData(metaHeader data.MetaHeaderHandler) if check.IfNil(metaHeader) { return process.ErrNilHeaderHandler } - if metaHeader.IsHeaderV3() { - return nil - } rootHash, err := mp.accountsDB[state.UserAccountsState].RootHash() if err != nil { diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index e2787e0f132..954160272fe 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -3,9 +3,107 @@ package block import ( "time" + "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-core-go/data/block" + + "github.com/multiversx/mx-chain-go/common" + "github.com/multiversx/mx-chain-go/process" ) +// CreateNewHeaderProposal creates a new header +func (mp *metaProcessor) CreateNewHeaderProposal(round uint64, nonce uint64) (data.HeaderHandler, error) { + epoch := mp.epochStartTrigger.Epoch() + + header := mp.versionedHeaderFactory.Create(epoch, round) + metaHeader, ok := header.(data.MetaHeaderHandler) + if !ok { + return nil, process.ErrWrongTypeAssertion + } + + if !metaHeader.IsHeaderV3() { + return nil, process.ErrInvalidHeader + } + + epochChangeProposed := mp.epochStartTrigger.ShouldProposeEpochChange(round, nonce) + metaHeader.SetEpochChangeProposed(epochChangeProposed) + err := metaHeader.SetRound(round) + if err != nil { + return nil, err + } + + err = metaHeader.SetNonce(nonce) + if err != nil { + return nil, err + } + + err = mp.addExecutionResultsOnHeader(metaHeader) + if err != nil { + return nil, err + } + + hasEpochStartResults, err := mp.hasStartOfEpochExecutionResults(metaHeader) + if err != nil { + return nil, err + } + if hasEpochStartResults { + err := metaHeader.SetEpoch(epoch + 1) + if err != nil { + return nil, err + } + } + + // TODO: the trigger would need to be changed upon commit of a block with the epoch start results + + return metaHeader, nil +} + +// CreateBlockProposal creates a block proposal without executing any of the transactions +func (mp *metaProcessor) CreateBlockProposal( + initialHdr data.HeaderHandler, + haveTime func() bool, +) (data.HeaderHandler, data.BodyHandler, error) { + if check.IfNil(initialHdr) { + return nil, nil, process.ErrNilBlockHeader + } + if !initialHdr.IsHeaderV3() { + return nil, nil, process.ErrInvalidHeader + } + + metaHdr, ok := initialHdr.(*block.MetaBlockV3) + if !ok { + return nil, nil, process.ErrWrongTypeAssertion + } + + metaHdr.SoftwareVersion = []byte(mp.headerIntegrityVerifier.GetVersion(metaHdr.Epoch, metaHdr.Round)) + + // var body data.BodyHandler + // err := mp.updateHeaderForEpochStartIfNeeded(metaHdr) + // if err != nil { + // return nil, nil, err + // } + // + // err = mp.blockChainHook.SetCurrentHeader(metaHdr) + // if err != nil { + // return nil, nil, err + // } + // + // body, err = mp.createBody(metaHdr, haveTime) + // if err != nil { + // return nil, nil, err + // } + // + // body, err = mp.applyBodyToHeader(metaHdr, body) + // if err != nil { + // return nil, nil, err + // } + // + // mp.requestHandler.SetEpoch(metaHdr.GetEpoch()) + // return metaHdr, body, nil + + return nil, nil, nil +} + // VerifyBlockProposal will be implemented in a further PR func (mp *metaProcessor) VerifyBlockProposal( _ data.HeaderHandler, @@ -14,3 +112,35 @@ func (mp *metaProcessor) VerifyBlockProposal( ) error { return nil } + +// ProcessBlockProposal processes the proposed block. It returns nil if all ok or the specific error +func (mp *metaProcessor) ProcessBlockProposal( + headerHandler data.HeaderHandler, + bodyHandler data.BodyHandler, +) (data.BaseExecutionResultHandler, error) { + return nil, nil +} + +func (mp *metaProcessor) hasStartOfEpochExecutionResults(metaHeader data.MetaHeaderHandler) (bool, error) { + execResults := metaHeader.GetExecutionResultsHandlers() + for _, execResult := range execResults { + mbHeaders, err := mp.extractMiniBlocksHeaderHandlersFromExecResult(execResult, common.MetachainShardId) + if err != nil { + return false, err + } + if hasRewardMiniBlocks(mbHeaders) { + return true, nil + } + } + return false, nil +} + +func hasRewardMiniBlocks(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { + for _, mbHeader := range miniBlockHeaders { + if mbHeader.GetTypeInt32() == int32(block.RewardsBlock) || + mbHeader.GetTypeInt32() == int32(block.PeerBlock) { + return true + } + } + return false +} diff --git a/process/block/metablock_test.go b/process/block/metablock_test.go index b61c5a1d199..bcd52c1ea15 100644 --- a/process/block/metablock_test.go +++ b/process/block/metablock_test.go @@ -3185,7 +3185,7 @@ func TestMetaProcessor_CreateNewHeaderValsOK(t *testing.T) { assert.Equal(t, zeroInt, metaHeader.DevFeesInEpoch) } -func TestCreateNewHeaderV3(t *testing.T) { +func TestCreateNewHeaderProposal(t *testing.T) { t.Parallel() rootHash := []byte("root") @@ -3219,14 +3219,41 @@ func TestCreateNewHeaderV3(t *testing.T) { } arguments := createMockMetaArguments(coreComponents, dataComponents, boostrapComponents, statusComponents) + dataComponents = &mock.DataComponentsMock{ + BlockChain: &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &block.MetaBlockV3{ + Epoch: epoch, + LastExecutionResult: &block.MetaExecutionResultInfo{ + NotarizedInRound: 10, + ExecutionResult: &block.BaseMetaExecutionResult{ + BaseExecutionResult: &block.BaseExecutionResult{ + HeaderHash: []byte("hash2"), + HeaderNonce: 9, + HeaderRound: 9, + HeaderEpoch: epoch, + RootHash: []byte("root hash"), + GasUsed: 1000, + }, + }, + }, + } + }, + GetCurrentBlockHeaderHashCalled: func() []byte { + return []byte("hash") + }, + }, + DataPool: arguments.DataComponents.Datapool(), + Storage: arguments.DataComponents.StorageService(), + } + arguments.DataComponents = dataComponents arguments.AccountsDB[state.UserAccountsState] = &stateMock.AccountsStub{ RootHashCalled: func() ([]byte, error) { return rootHash, nil }, } - updateRoundCalled := false arguments.EpochStartTrigger = &mock.EpochStartTriggerStub{ EpochCalled: func() uint32 { return epoch @@ -3234,19 +3261,15 @@ func TestCreateNewHeaderV3(t *testing.T) { ShouldProposeEpochChangeCalled: func(round uint64, nonce uint64) bool { return true }, - UpdateRoundCalled: func(round uint64) { - updateRoundCalled = true - }, } mp, err := blproc.NewMetaProcessor(arguments) assert.Nil(t, err) - newHeader, err := mp.CreateNewHeader(round, nonce) + newHeader, err := mp.CreateNewHeaderProposal(round, nonce) require.Nil(t, err) require.IsType(t, &block.MetaBlockV3{}, newHeader) require.Equal(t, epoch, newHeader.GetEpoch()) - require.True(t, updateRoundCalled) } func TestMetaProcessor_ProcessEpochStartMetaBlock(t *testing.T) { diff --git a/process/block/shardblockProposal.go b/process/block/shardblockProposal.go index 2cd0005525d..5468dfbbd7b 100644 --- a/process/block/shardblockProposal.go +++ b/process/block/shardblockProposal.go @@ -20,6 +20,29 @@ import ( // TODO: maybe move this to config const maxBlockProcessingTime = 3 * time.Second +// CreateNewHeaderProposal creates a new header proposal +func (sp *shardProcessor) CreateNewHeaderProposal(round uint64, nonce uint64) (data.HeaderHandler, error) { + epoch := sp.epochStartTrigger.MetaEpoch() + header := sp.versionedHeaderFactory.Create(epoch, round) + + shardHeader, ok := header.(data.ShardHeaderHandler) + if !ok { + return nil, process.ErrWrongTypeAssertion + } + + err := shardHeader.SetRound(round) + if err != nil { + return nil, err + } + + err = shardHeader.SetNonce(nonce) + if err != nil { + return nil, err + } + + return header, nil +} + // CreateBlockProposal creates a block proposal without executing any of the transactions func (sp *shardProcessor) CreateBlockProposal( initialHdr data.HeaderHandler, @@ -444,29 +467,6 @@ func (sp *shardProcessor) getTransactionsForMiniBlock( return mbForHeaderPtr.TxHashes, txs, nil } -func (sp *shardProcessor) checkInclusionEstimationForExecutionResults(header data.HeaderHandler) error { - prevBlockLastExecutionResult, err := process.GetPrevBlockLastExecutionResult(sp.blockChain) - if err != nil { - return err - } - - lastResultData, err := process.CreateDataForInclusionEstimation(prevBlockLastExecutionResult) - if err != nil { - return err - } - executionResults := header.GetExecutionResultsHandlers() - allowed := sp.executionResultsInclusionEstimator.Decide(lastResultData, executionResults, header.GetRound()) - if allowed != len(executionResults) { - log.Warn("number of execution results included in the header is not correct", - "expected", allowed, - "actual", len(executionResults), - ) - return process.ErrInvalidNumberOfExecutionResultsInHeader - } - - return nil -} - func computeTxTotalTxCount(miniBlockHeaders []data.MiniBlockHeaderHandler) uint32 { totalTxCount := uint32(0) for i := range miniBlockHeaders { @@ -485,43 +485,6 @@ func checkMiniBlocksAndMiniBlockHeadersConsistency(miniBlocks block.MiniBlockSli return nil } -func (sp *shardProcessor) addExecutionResultsOnHeader(shardHeader data.HeaderHandler) error { - pendingExecutionResults, err := sp.executionResultsTracker.GetPendingExecutionResults() - if err != nil { - return err - } - - lastExecutionResultHandler, err := process.GetPrevBlockLastExecutionResult(sp.blockChain) - if err != nil { - return err - } - - lastNotarizedExecutionResultInfo, err := process.CreateDataForInclusionEstimation(lastExecutionResultHandler) - if err != nil { - return err - } - - var lastExecutionResultForCurrentBlock data.LastExecutionResultHandler - numToInclude := sp.executionResultsInclusionEstimator.Decide(lastNotarizedExecutionResultInfo, pendingExecutionResults, shardHeader.GetRound()) - - executionResultsToInclude := pendingExecutionResults[:numToInclude] - lastExecutionResultForCurrentBlock = lastExecutionResultHandler - if len(executionResultsToInclude) > 0 { - lastExecutionResult := executionResultsToInclude[len(executionResultsToInclude)-1] - lastExecutionResultForCurrentBlock, err = process.CreateLastExecutionResultInfoFromExecutionResult(shardHeader.GetRound(), lastExecutionResult, sp.shardCoordinator.SelfId()) - if err != nil { - return err - } - } - - err = shardHeader.SetLastExecutionResultHandler(lastExecutionResultForCurrentBlock) - if err != nil { - return err - } - - return shardHeader.SetExecutionResultsHandlers(executionResultsToInclude) -} - func (sp *shardProcessor) createBlockBodyProposal( shardHdr data.HeaderHandler, haveTime func() bool, diff --git a/process/block/shardblockProposal_test.go b/process/block/shardblockProposal_test.go index 62061bc8064..7506d635b3b 100644 --- a/process/block/shardblockProposal_test.go +++ b/process/block/shardblockProposal_test.go @@ -10,9 +10,9 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/data/transaction" - "github.com/multiversx/mx-chain-go/common" "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" retriever "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/dataRetriever/blockchain" "github.com/multiversx/mx-chain-go/process" From 52e4b1e08ba7dcfbf5970cbe8b635ebe6a9fe9f6 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 20 Oct 2025 10:01:13 +0300 Subject: [PATCH 03/51] deactivate supernova in relay txs tests --- integrationTests/chainSimulator/relayedTx/relayedTx_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integrationTests/chainSimulator/relayedTx/relayedTx_test.go b/integrationTests/chainSimulator/relayedTx/relayedTx_test.go index 96e598ff1ed..61e94ca226a 100644 --- a/integrationTests/chainSimulator/relayedTx/relayedTx_test.go +++ b/integrationTests/chainSimulator/relayedTx/relayedTx_test.go @@ -110,13 +110,13 @@ func testRelayedV3MoveBalance( cfg.EpochConfig.EnableEpochs.RelayedTransactionsV3EnableEpoch = providedActivationEpoch cfg.EpochConfig.EnableEpochs.RelayedTransactionsV3FixESDTTransferEnableEpoch = providedActivationEpoch - cfg.EpochConfig.EnableEpochs.SupernovaEnableEpoch = 0 + cfg.EpochConfig.EnableEpochs.SupernovaEnableEpoch = 10 cfg.RoundConfig.RoundActivations = map[string]config.ActivationRoundByName{ "DisableAsyncCallV1": { Round: "0", }, "SupernovaEnableRound": { - Round: "0", + Round: "10000", }, } } From 17eda289aaaf29a03e3ccdac958a5e9cbd331706 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 21 Oct 2025 18:20:58 +0300 Subject: [PATCH 04/51] renaming interface methods, move common func to base processor --- process/block/baseProcess.go | 55 +++++++++++++++++++++++++++++ process/block/interface.go | 8 ++--- process/block/shardblockProposal.go | 54 +++++----------------------- 3 files changed, 67 insertions(+), 50 deletions(-) diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 1163b7685e7..1362ff80760 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -2720,3 +2720,58 @@ func (bp *baseProcessor) addExecutionResultsOnHeader(header data.HeaderHandler) return header.SetExecutionResultsHandlers(executionResultsToInclude) } + +func (bp *baseProcessor) createMbsCrossShardDstMe( + currentBlockHash []byte, + currentBlock data.HeaderHandler, + miniBlockProcessingInfo map[string]*processedMb.ProcessedMiniBlockInfo, + allOrNothing bool, +) (bool, []block.MiniblockAndHash, error) { + currMiniBlocksAdded, pendingMiniBlocks, currNumTxsAdded, hdrFinished, errCreate := bp.txCoordinator.CreateMbsCrossShardDstMe( + currentBlock, + miniBlockProcessingInfo, + ) + if errCreate != nil { + return false, nil, errCreate + } + + if allOrNothing && len(pendingMiniBlocks) > 0 { + log.Debug("block cannot be fully processed", + "round", currentBlock.GetRound(), + "nonce", currentBlock.GetNonce(), + "hash", currentBlockHash) + bp.revertGasForCrossShardDstMeMiniBlocks(currMiniBlocksAdded, pendingMiniBlocks) + + return false, pendingMiniBlocks, nil + } + + err := bp.miniBlocksSelectionSession.AddMiniBlocksAndHashes(currMiniBlocksAdded) + if err != nil { + return false, nil, err + } + + if !hdrFinished { + log.Debug("block cannot be fully processed", + "round", currentBlock.GetRound(), + "nonce", currentBlock.GetNonce(), + "hash", currentBlockHash, + "num mbs added", len(currMiniBlocksAdded), + "num txs added", currNumTxsAdded) + + return false, pendingMiniBlocks, nil + } + + return true, pendingMiniBlocks, nil +} + +func (bp *baseProcessor) revertGasForCrossShardDstMeMiniBlocks(added, pending []block.MiniblockAndHash) { + miniBlockHashesToRevert := make([][]byte, 0, len(added)) + for _, mbAndHash := range added { + miniBlockHashesToRevert = append(miniBlockHashesToRevert, mbAndHash.Hash) + } + for _, mbAndHash := range pending { + miniBlockHashesToRevert = append(miniBlockHashesToRevert, mbAndHash.Hash) + } + + bp.gasComputation.RevertIncomingMiniBlocks(miniBlockHashesToRevert) +} diff --git a/process/block/interface.go b/process/block/interface.go index 00284c07d0e..c9189edf1a8 100644 --- a/process/block/interface.go +++ b/process/block/interface.go @@ -60,10 +60,10 @@ type MiniBlocksSelectionSession interface { GetMiniBlockHeaderHandlers() []data.MiniBlockHeaderHandler GetMiniBlocks() block.MiniBlockSlice GetMiniBlockHashes() [][]byte - AddReferencedMetaBlock(metaBlock data.HeaderHandler, metaBlockHash []byte) - GetReferencedMetaBlockHashes() [][]byte - GetReferencedMetaBlocks() []data.HeaderHandler - GetLastMetaBlock() data.HeaderHandler + AddReferencedHeader(header data.HeaderHandler, headerHash []byte) + GetReferencedHeaderHashes() [][]byte + GetReferencedHeaders() []data.HeaderHandler + GetLastHeader() data.HeaderHandler GetGasProvided() uint64 GetNumTxsAdded() uint32 AddMiniBlocksAndHashes(miniBlocksAndHashes []block.MiniblockAndHash) error diff --git a/process/block/shardblockProposal.go b/process/block/shardblockProposal.go index 5468dfbbd7b..1f4156cfb00 100644 --- a/process/block/shardblockProposal.go +++ b/process/block/shardblockProposal.go @@ -78,7 +78,7 @@ func (sp *shardProcessor) CreateBlockProposal( return nil, nil, err } - err = shardHdr.SetMetaBlockHashes(sp.miniBlocksSelectionSession.GetReferencedMetaBlockHashes()) + err = shardHdr.SetMetaBlockHashes(sp.miniBlocksSelectionSession.GetReferencedHeaderHashes()) if err != nil { return nil, nil, err } @@ -526,12 +526,6 @@ func (sp *shardProcessor) selectIncomingMiniBlocksForProposal( return nil, err } - referencedMetaBlocks := sp.miniBlocksSelectionSession.GetReferencedMetaBlocks() - numHeadersAdded := uint32(len(referencedMetaBlocks)) - if numHeadersAdded > 0 { - go sp.requestMetaHeadersIfNeeded(numHeadersAdded, referencedMetaBlocks[numHeadersAdded-1]) - } - miniBlockHeaderHandlers := sp.miniBlocksSelectionSession.GetMiniBlockHeaderHandlers() for _, miniBlockHeader := range miniBlockHeaderHandlers { log.Debug("mini block info", @@ -543,7 +537,7 @@ func (sp *shardProcessor) selectIncomingMiniBlocksForProposal( log.Debug("selectIncomingMiniBlocksForProposal has been finished", "num txs added", sp.miniBlocksSelectionSession.GetNumTxsAdded(), - "num referenced meta blocks", len(sp.miniBlocksSelectionSession.GetReferencedMetaBlocks())) + "num referenced meta blocks", len(sp.miniBlocksSelectionSession.GetReferencedHeaders())) return pendingMiniBlocks, nil } @@ -567,9 +561,9 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( break } - if len(sp.miniBlocksSelectionSession.GetReferencedMetaBlocks()) >= process.MaxMetaHeadersAllowedInOneShardBlock { + if len(sp.miniBlocksSelectionSession.GetReferencedHeaders()) >= process.MaxMetaHeadersAllowedInOneShardBlock { log.Debug("maximum meta headers allowed to be included in one shard block has been reached", - "meta headers added", len(sp.miniBlocksSelectionSession.GetReferencedMetaBlocks()), + "meta headers added", len(sp.miniBlocksSelectionSession.GetReferencedHeaders()), ) break } @@ -598,57 +592,25 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( } if len(currentMetaBlock.GetMiniBlockHeadersWithDst(sp.shardCoordinator.SelfId())) == 0 { - sp.miniBlocksSelectionSession.AddReferencedMetaBlock(orderedMetaBlocks[i], orderedMetaBlocksHashes[i]) + sp.miniBlocksSelectionSession.AddReferencedHeader(orderedMetaBlocks[i], orderedMetaBlocksHashes[i]) continue } currProcessedMiniBlocksInfo := sp.processedMiniBlocksTracker.GetProcessedMiniBlocksInfo(currentMetaBlockHash) - shouldContinue, pendingMiniBlocks, errCreated = sp.createMbsCrossShardDstMe(currentMetaBlockHash, metaBlock, currProcessedMiniBlocksInfo) + shouldContinue, pendingMiniBlocks, errCreated = sp.createMbsCrossShardDstMe(currentMetaBlockHash, metaBlock, currProcessedMiniBlocksInfo, false) if errCreated != nil { return nil, errCreated } + + sp.miniBlocksSelectionSession.AddReferencedHeader(currentMetaBlock, currentMetaBlockHash) if !shouldContinue { break } - - sp.miniBlocksSelectionSession.AddReferencedMetaBlock(currentMetaBlock, currentMetaBlockHash) } return pendingMiniBlocks, nil } -func (sp *shardProcessor) createMbsCrossShardDstMe( - currentMetaBlockHash []byte, - currentMetaBlock data.MetaHeaderHandler, - miniBlockProcessingInfo map[string]*processedMb.ProcessedMiniBlockInfo, -) (bool, []block.MiniblockAndHash, error) { - currMiniBlocksAdded, pendingMiniBlocks, currNumTxsAdded, hdrFinished, errCreate := sp.txCoordinator.CreateMbsCrossShardDstMe( - currentMetaBlock, - miniBlockProcessingInfo, - ) - if errCreate != nil { - return false, nil, errCreate - } - - err := sp.miniBlocksSelectionSession.AddMiniBlocksAndHashes(currMiniBlocksAdded) - if err != nil { - return false, nil, err - } - - if !hdrFinished { - log.Debug("meta block cannot be fully processed", - "round", currentMetaBlock.GetRound(), - "nonce", currentMetaBlock.GetNonce(), - "hash", currentMetaBlockHash, - "num mbs added", len(currMiniBlocksAdded), - "num txs added", currNumTxsAdded) - - return false, pendingMiniBlocks, nil - } - - return true, pendingMiniBlocks, nil -} - func (sp *shardProcessor) createProposalMiniBlocks(haveTime func() bool) error { if !haveTime() { log.Debug("shardProcessor.createProposalMiniBlocks", "error", process.ErrTimeIsOut) From a534f5ab290146bf9ac3ec60dd3814dc647efd60 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 21 Oct 2025 18:23:27 +0300 Subject: [PATCH 05/51] refactor miniblock selection session (renaming) --- process/block/mbsSelectionSession.go | 82 +++++++++---------- process/block/mbsSelectionSession_test.go | 40 ++++----- process/block/pendingMb/pendingMiniBlocks.go | 3 +- process/track/blockNotarizer.go | 1 + .../mbSelection/mbSelectionSessionStub.go | 8 +- 5 files changed, 68 insertions(+), 66 deletions(-) diff --git a/process/block/mbsSelectionSession.go b/process/block/mbsSelectionSession.go index 3962471f47e..2101c7c949a 100644 --- a/process/block/mbsSelectionSession.go +++ b/process/block/mbsSelectionSession.go @@ -20,15 +20,15 @@ type miniBlocksSelectionConfig struct { } type miniBlocksSelectionResult struct { - miniBlockHeaderHandlers []data.MiniBlockHeaderHandler - miniBlocks block.MiniBlockSlice - miniBlockHashes [][]byte - referencedMetaBlockHashes [][]byte - referencedMetaBlocks []data.HeaderHandler - lastMetaBlock data.HeaderHandler - gasProvided uint64 - numTxsAdded uint32 - mut sync.RWMutex + miniBlockHeaderHandlers []data.MiniBlockHeaderHandler + miniBlocks block.MiniBlockSlice + miniBlockHashes [][]byte + referencedHeaderHashes [][]byte + referencedHeader []data.HeaderHandler + lastHeader data.HeaderHandler + gasProvided uint64 + numTxsAdded uint32 + mut sync.RWMutex } type miniBlocksSelectionSession struct { @@ -54,14 +54,14 @@ func NewMiniBlocksSelectionSession(shardID uint32, marshaller marshal.Marshalize hasher: hasher, }, miniBlocksSelectionResult: &miniBlocksSelectionResult{ - miniBlockHeaderHandlers: make([]data.MiniBlockHeaderHandler, 0, defaultCapacity), - miniBlocks: make(block.MiniBlockSlice, 0, defaultCapacity), - miniBlockHashes: make([][]byte, 0, defaultCapacity), - referencedMetaBlockHashes: make([][]byte, 0, defaultCapacity), - referencedMetaBlocks: make([]data.HeaderHandler, 0, defaultCapacity), - lastMetaBlock: nil, - gasProvided: 0, - numTxsAdded: 0, + miniBlockHeaderHandlers: make([]data.MiniBlockHeaderHandler, 0, defaultCapacity), + miniBlocks: make(block.MiniBlockSlice, 0, defaultCapacity), + miniBlockHashes: make([][]byte, 0, defaultCapacity), + referencedHeaderHashes: make([][]byte, 0, defaultCapacity), + referencedHeader: make([]data.HeaderHandler, 0, defaultCapacity), + lastHeader: nil, + gasProvided: 0, + numTxsAdded: 0, }, }, nil } @@ -74,9 +74,9 @@ func (s *miniBlocksSelectionSession) ResetSelectionSession() { s.miniBlockHeaderHandlers = make([]data.MiniBlockHeaderHandler, 0, defaultCapacity) s.miniBlocks = make(block.MiniBlockSlice, 0, defaultCapacity) s.miniBlockHashes = make([][]byte, 0, defaultCapacity) - s.referencedMetaBlockHashes = make([][]byte, 0, defaultCapacity) - s.referencedMetaBlocks = make([]data.HeaderHandler, 0, defaultCapacity) - s.lastMetaBlock = nil + s.referencedHeaderHashes = make([][]byte, 0, defaultCapacity) + s.referencedHeader = make([]data.HeaderHandler, 0, defaultCapacity) + s.lastHeader = nil s.gasProvided = 0 s.numTxsAdded = 0 } @@ -126,56 +126,56 @@ func (s *miniBlocksSelectionSession) GetMiniBlockHashes() [][]byte { return miniBlockHashes } -// AddReferencedMetaBlock adds a meta block and its hash to the session -func (s *miniBlocksSelectionSession) AddReferencedMetaBlock(metaBlock data.HeaderHandler, metaBlockHash []byte) { +// AddReferencedHeader adds a header and its hash to the session +func (s *miniBlocksSelectionSession) AddReferencedHeader(header data.HeaderHandler, headerHash []byte) { s.mut.Lock() defer s.mut.Unlock() - if check.IfNil(metaBlock) || len(metaBlockHash) == 0 { + if check.IfNil(header) || len(headerHash) == 0 { return } - s.referencedMetaBlocks = append(s.referencedMetaBlocks, metaBlock) - s.referencedMetaBlockHashes = append(s.referencedMetaBlockHashes, metaBlockHash) - s.lastMetaBlock = metaBlock + s.referencedHeader = append(s.referencedHeader, header) + s.referencedHeaderHashes = append(s.referencedHeaderHashes, headerHash) + s.lastHeader = header } -// GetReferencedMetaBlockHashes returns the hashes of the referenced meta blocks -func (s *miniBlocksSelectionSession) GetReferencedMetaBlockHashes() [][]byte { +// GetReferencedHeaderHashes returns the hashes of the referenced headers +func (s *miniBlocksSelectionSession) GetReferencedHeaderHashes() [][]byte { s.mut.RLock() defer s.mut.RUnlock() - if len(s.referencedMetaBlockHashes) == 0 { + if len(s.referencedHeaderHashes) == 0 { return nil } - referencedMetaBlockHashes := make([][]byte, len(s.referencedMetaBlockHashes)) - copy(referencedMetaBlockHashes, s.referencedMetaBlockHashes) + referencedHeaderHashes := make([][]byte, len(s.referencedHeaderHashes)) + copy(referencedHeaderHashes, s.referencedHeaderHashes) - return referencedMetaBlockHashes + return referencedHeaderHashes } -// GetReferencedMetaBlocks returns the referenced meta blocks -func (s *miniBlocksSelectionSession) GetReferencedMetaBlocks() []data.HeaderHandler { +// GetReferencedHeaders returns the referenced headers +func (s *miniBlocksSelectionSession) GetReferencedHeaders() []data.HeaderHandler { s.mut.RLock() defer s.mut.RUnlock() - if len(s.referencedMetaBlocks) == 0 { + if len(s.referencedHeader) == 0 { return nil } - referencedMetaBlocks := make([]data.HeaderHandler, len(s.referencedMetaBlocks)) - copy(referencedMetaBlocks, s.referencedMetaBlocks) + referencedHeaders := make([]data.HeaderHandler, len(s.referencedHeader)) + copy(referencedHeaders, s.referencedHeader) - return referencedMetaBlocks + return referencedHeaders } -// GetLastMetaBlock returns the last meta block -func (s *miniBlocksSelectionSession) GetLastMetaBlock() data.HeaderHandler { +// GetLastHeader returns the last header +func (s *miniBlocksSelectionSession) GetLastHeader() data.HeaderHandler { s.mut.RLock() defer s.mut.RUnlock() - return s.lastMetaBlock + return s.lastHeader } // GetGasProvided returns the gas provided for the mini blocks diff --git a/process/block/mbsSelectionSession_test.go b/process/block/mbsSelectionSession_test.go index 10f29d5aed8..3d453812432 100644 --- a/process/block/mbsSelectionSession_test.go +++ b/process/block/mbsSelectionSession_test.go @@ -52,9 +52,9 @@ func TestMiniBlockSelectionSession_ResetSelectionSession(t *testing.T) { require.Empty(t, session.GetMiniBlocks()) require.Empty(t, session.GetMiniBlockHeaderHandlers()) require.Empty(t, session.GetMiniBlockHashes()) - require.Empty(t, session.GetReferencedMetaBlockHashes()) - require.Empty(t, session.GetReferencedMetaBlocks()) - require.Nil(t, session.GetLastMetaBlock()) + require.Empty(t, session.GetReferencedHeaderHashes()) + require.Empty(t, session.GetReferencedHeaders()) + require.Nil(t, session.GetLastHeader()) require.Equal(t, uint64(0), session.GetGasProvided()) require.Equal(t, uint32(0), session.GetNumTxsAdded()) } @@ -67,9 +67,9 @@ func TestMiniBlockSelectionSession_Getters(t *testing.T) { require.Len(t, session.GetMiniBlockHeaderHandlers(), 1) require.Len(t, session.GetMiniBlocks(), 1) require.Len(t, session.GetMiniBlockHashes(), 1) - require.Len(t, session.GetReferencedMetaBlockHashes(), 1) - require.Len(t, session.GetReferencedMetaBlocks(), 1) - require.NotNil(t, session.GetLastMetaBlock()) + require.Len(t, session.GetReferencedHeaderHashes(), 1) + require.Len(t, session.GetReferencedHeaders(), 1) + require.NotNil(t, session.GetLastHeader()) require.Equal(t, uint64(100), session.GetGasProvided()) require.Equal(t, uint32(2), session.GetNumTxsAdded()) } @@ -210,31 +210,31 @@ func TestMiniBlocksSelectionSession_AddReferencedMetaBlock(t *testing.T) { session, _ := NewMiniBlocksSelectionSession(1, marshaller, hasher) metaBlock := &block.MetaBlock{Epoch: 1, Round: 1} metaBlockHash := []byte("metaHash") - session.AddReferencedMetaBlock(metaBlock, metaBlockHash) + session.AddReferencedHeader(metaBlock, metaBlockHash) - require.Len(t, session.GetReferencedMetaBlocks(), 1) - require.Len(t, session.GetReferencedMetaBlockHashes(), 1) - require.Equal(t, metaBlock, session.GetReferencedMetaBlocks()[0]) - require.Equal(t, metaBlockHash, session.GetReferencedMetaBlockHashes()[0]) + require.Len(t, session.GetReferencedHeaders(), 1) + require.Len(t, session.GetReferencedHeaderHashes(), 1) + require.Equal(t, metaBlock, session.GetReferencedHeaders()[0]) + require.Equal(t, metaBlockHash, session.GetReferencedHeaderHashes()[0]) }) t.Run("should not add nil meta block", func(t *testing.T) { t.Parallel() session, _ := NewMiniBlocksSelectionSession(1, marshaller, hasher) - session.AddReferencedMetaBlock(nil, []byte("metaHash")) + session.AddReferencedHeader(nil, []byte("metaHash")) - require.Empty(t, session.GetReferencedMetaBlocks()) - require.Empty(t, session.GetReferencedMetaBlockHashes()) + require.Empty(t, session.GetReferencedHeaders()) + require.Empty(t, session.GetReferencedHeaderHashes()) }) t.Run("should not add empty meta block hash", func(t *testing.T) { t.Parallel() session, _ := NewMiniBlocksSelectionSession(1, marshaller, hasher) metaBlock := &block.MetaBlock{Epoch: 1, Round: 1} - session.AddReferencedMetaBlock(metaBlock, nil) + session.AddReferencedHeader(metaBlock, nil) - require.Empty(t, session.GetReferencedMetaBlocks()) - require.Empty(t, session.GetReferencedMetaBlockHashes()) + require.Empty(t, session.GetReferencedHeaders()) + require.Empty(t, session.GetReferencedHeaderHashes()) }) } @@ -277,9 +277,9 @@ func createDummyFilledSession() *miniBlocksSelectionSession { session.miniBlocks = append(session.miniBlocks, miniBlock) session.miniBlockHashes = append(session.miniBlockHashes, miniBlockHash) session.miniBlockHeaderHandlers = append(session.miniBlockHeaderHandlers, miniBlockHeader) - session.referencedMetaBlockHashes = append(session.referencedMetaBlockHashes, metaBlockHash) - session.referencedMetaBlocks = append(session.referencedMetaBlocks, metaBlock) - session.lastMetaBlock = metaBlock + session.referencedHeaderHashes = append(session.referencedHeaderHashes, metaBlockHash) + session.referencedHeader = append(session.referencedHeader, metaBlock) + session.lastHeader = metaBlock session.gasProvided = 100 session.numTxsAdded = 2 diff --git a/process/block/pendingMb/pendingMiniBlocks.go b/process/block/pendingMb/pendingMiniBlocks.go index ee3625bfca3..2a7d9b99010 100644 --- a/process/block/pendingMb/pendingMiniBlocks.go +++ b/process/block/pendingMb/pendingMiniBlocks.go @@ -7,8 +7,9 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" - "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-logger-go" + + "github.com/multiversx/mx-chain-go/process" ) var _ process.PendingMiniBlocksHandler = (*pendingMiniBlocks)(nil) diff --git a/process/track/blockNotarizer.go b/process/track/blockNotarizer.go index 0d6b581fd6e..6520d3ff810 100644 --- a/process/track/blockNotarizer.go +++ b/process/track/blockNotarizer.go @@ -9,6 +9,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/sharding" ) diff --git a/testscommon/mbSelection/mbSelectionSessionStub.go b/testscommon/mbSelection/mbSelectionSessionStub.go index 31ee247f893..8ba5741351d 100644 --- a/testscommon/mbSelection/mbSelectionSessionStub.go +++ b/testscommon/mbSelection/mbSelectionSessionStub.go @@ -53,14 +53,14 @@ func (mbss *MiniBlockSelectionSessionStub) GetMiniBlockHashes() [][]byte { } // AddReferencedMetaBlock - -func (mbss *MiniBlockSelectionSessionStub) AddReferencedMetaBlock(metaBlock data.HeaderHandler, metaBlockHash []byte) { +func (mbss *MiniBlockSelectionSessionStub) AddReferencedHeader(metaBlock data.HeaderHandler, metaBlockHash []byte) { if mbss.AddReferencedMetaBlockCalled != nil { mbss.AddReferencedMetaBlockCalled(metaBlock, metaBlockHash) } } // GetReferencedMetaBlockHashes - -func (mbss *MiniBlockSelectionSessionStub) GetReferencedMetaBlockHashes() [][]byte { +func (mbss *MiniBlockSelectionSessionStub) GetReferencedHeaderHashes() [][]byte { if mbss.GetReferencedMetaBlockHashesCalled != nil { return mbss.GetReferencedMetaBlockHashesCalled() } @@ -68,7 +68,7 @@ func (mbss *MiniBlockSelectionSessionStub) GetReferencedMetaBlockHashes() [][]by } // GetReferencedMetaBlocks - -func (mbss *MiniBlockSelectionSessionStub) GetReferencedMetaBlocks() []data.HeaderHandler { +func (mbss *MiniBlockSelectionSessionStub) GetReferencedHeaders() []data.HeaderHandler { if mbss.GetReferencedMetaBlocksCalled != nil { return mbss.GetReferencedMetaBlocksCalled() } @@ -76,7 +76,7 @@ func (mbss *MiniBlockSelectionSessionStub) GetReferencedMetaBlocks() []data.Head } // GetLastMetaBlock - -func (mbss *MiniBlockSelectionSessionStub) GetLastMetaBlock() data.HeaderHandler { +func (mbss *MiniBlockSelectionSessionStub) GetLastHeader() data.HeaderHandler { if mbss.GetLastMetaBlockCalled != nil { return mbss.GetLastMetaBlockCalled() } From dc614f0122b53b6f58d9532a46126fa91489b55b Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 21 Oct 2025 18:27:43 +0300 Subject: [PATCH 06/51] add component to create shard info for meta blocks --- factory/processing/blockProcessorCreator.go | 12 + process/block/metablock.go | 112 ++++---- process/block/metablock_test.go | 33 ++- process/block/shardInfo.go | 274 ++++++++++++++++++++ process/interface.go | 7 + 5 files changed, 373 insertions(+), 65 deletions(-) create mode 100644 process/block/shardInfo.go diff --git a/factory/processing/blockProcessorCreator.go b/factory/processing/blockProcessorCreator.go index 37c4aa847a6..81af499f059 100644 --- a/factory/processing/blockProcessorCreator.go +++ b/factory/processing/blockProcessorCreator.go @@ -1190,6 +1190,17 @@ func (pcf *processComponentsFactory) newMetaBlockProcessor( return nil, err } + shardInfoCreator, err := block.NewShardInfoCreateData( + pcf.coreData.EnableEpochsHandler(), + pcf.data.Datapool().Headers(), + pcf.data.Datapool().Proofs(), + pendingMiniBlocksHandler, + blockTracker, + ) + if err != nil { + return nil, err + } + arguments := block.ArgMetaProcessor{ ArgBaseProcessor: argumentsBaseProcessor, SCToProtocol: smartContractToProtocol, @@ -1200,6 +1211,7 @@ func (pcf *processComponentsFactory) newMetaBlockProcessor( EpochValidatorInfoCreator: validatorInfoCreator, ValidatorStatisticsProcessor: validatorStatisticsProcessor, EpochSystemSCProcessor: epochStartSystemSCProcessor, + ShardInfoCreator: shardInfoCreator, } metaProcessor, err := block.NewMetaProcessor(arguments) diff --git a/process/block/metablock.go b/process/block/metablock.go index 9034c52ce6e..54ea01b81f8 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -32,6 +32,14 @@ const firstHeaderNonce = uint64(1) var _ process.BlockProcessor = (*metaProcessor)(nil) // metaProcessor implements metaProcessor interface, and actually it tries to execute block + +// ShardHeaderInfo holds info about a shard header +type ShardHeaderInfo struct { + Header data.HeaderHandler + Hash []byte + UsedInBlock bool +} + type metaProcessor struct { *baseProcessor scToProtocol process.SmartContractToProtocolHandler @@ -45,6 +53,10 @@ type metaProcessor struct { shardsHeadersNonce *sync.Map shardBlockFinality uint32 headersCounter *headersCounter + // TODO: fill this up on execution of epoch start + epochStartData *block.EpochStart + // TODO: initialize this + shardInfoCreateData process.ShardInfoCreator } // NewMetaProcessor creates a new metaProcessor object @@ -92,6 +104,7 @@ func NewMetaProcessor(arguments ArgMetaProcessor) (*metaProcessor, error) { validatorStatisticsProcessor: arguments.ValidatorStatisticsProcessor, validatorInfoCreator: arguments.EpochValidatorInfoCreator, epochSystemSCProcessor: arguments.EpochSystemSCProcessor, + shardInfoCreateData: arguments.ShardInfoCreator, } argsTransactionCounter := ArgsTransactionCounter{ @@ -971,7 +984,7 @@ func (mp *metaProcessor) createAndProcessCrossMiniBlocksDstMe( "num shard headers", len(orderedHdrs), ) - lastShardHdr, err := mp.getLastCrossNotarizedShardHdrs() + lastShardHdr, err := mp.getLastCrossNotarizedShardHdrsAndAddToCurrentBlock() if err != nil { return nil, 0, 0, err } @@ -1686,8 +1699,23 @@ func (mp *metaProcessor) saveLastNotarizedHeader(header *block.MetaBlock) error return nil } -func (mp *metaProcessor) getLastCrossNotarizedShardHdrs() (map[uint32]data.HeaderHandler, error) { - lastCrossNotarizedHeader := make(map[uint32]data.HeaderHandler, mp.shardCoordinator.NumberOfShards()) +func (mp *metaProcessor) getLastCrossNotarizedShardHdrsAndAddToCurrentBlock() (map[uint32]data.HeaderHandler, error) { + lastCrossNotarizedHeader, err := mp.getLastCrossNotarizedShardHdrs() + if err != nil { + return nil, err + } + mp.addHeaders(lastCrossNotarizedHeader) + + headers := make(map[uint32]data.HeaderHandler, len(lastCrossNotarizedHeader)) + for k, v := range lastCrossNotarizedHeader { + headers[k] = v.Header + } + + return headers, nil +} + +func (mp *metaProcessor) getLastCrossNotarizedShardHdrs() (map[uint32]ShardHeaderInfo, error) { + lastCrossNotarizedHeader := make(map[uint32]ShardHeaderInfo, mp.shardCoordinator.NumberOfShards()) for shardID := uint32(0); shardID < mp.shardCoordinator.NumberOfShards(); shardID++ { lastCrossNotarizedHeaderForShard, hash, err := mp.blockTracker.GetLastCrossNotarizedHeader(shardID) if err != nil { @@ -1695,15 +1723,27 @@ func (mp *metaProcessor) getLastCrossNotarizedShardHdrs() (map[uint32]data.Heade } log.Debug("lastCrossNotarizedHeader for shard", "shardID", shardID, "hash", hash) - lastCrossNotarizedHeader[shardID] = lastCrossNotarizedHeaderForShard usedInBlock := mp.isGenesisShardBlockAndFirstMeta(lastCrossNotarizedHeaderForShard.GetNonce()) - - mp.addHeader(hash, lastCrossNotarizedHeaderForShard, usedInBlock) + lastCrossNotarizedHeader[shardID] = ShardHeaderInfo{ + Header: lastCrossNotarizedHeaderForShard, + Hash: hash, + UsedInBlock: usedInBlock, + } } return lastCrossNotarizedHeader, nil } +func (mp *metaProcessor) addHeaders(shardHeadersInfo map[uint32]ShardHeaderInfo) { + for shardID := uint32(0); shardID < mp.shardCoordinator.NumberOfShards(); shardID++ { + shardHdrInfo, ok := shardHeadersInfo[shardID] + if !ok { + continue + } + mp.addHeader(shardHdrInfo.Hash, shardHdrInfo.Header, shardHdrInfo.UsedInBlock) + } +} + func (mp *metaProcessor) addHeader(hash []byte, header data.HeaderHandler, usedInBlock bool) { if usedInBlock { mp.hdrsForCurrBlock.AddHeaderUsedInBlock(string(hash), header) @@ -1716,7 +1756,7 @@ func (mp *metaProcessor) addHeader(hash []byte, header data.HeaderHandler, usedI // check if shard headers were signed and constructed correctly and returns headers which has to be // checked for finality func (mp *metaProcessor) checkShardHeadersValidity(metaHdr *block.MetaBlock) (map[uint32]data.HeaderHandler, error) { - lastCrossNotarizedHeader, err := mp.getLastCrossNotarizedShardHdrs() + lastCrossNotarizedHeader, err := mp.getLastCrossNotarizedShardHdrsAndAddToCurrentBlock() if err != nil { return nil, err } @@ -1896,13 +1936,15 @@ func (mp *metaProcessor) checkShardHeaderFinalityBasedOnProofs(shardHdr data.Hea return true, nil } -func (mp *metaProcessor) createShardInfo() ([]data.ShardDataHandler, error) { +func (mp *metaProcessor) createShardInfo(metaHdr data.MetaHeaderHandler) ([]data.ShardDataHandler, error) { var shardInfo []data.ShardDataHandler - if mp.epochStartTrigger.IsEpochStart() { + if metaHdr.IsStartOfEpochBlock() { return shardInfo, nil } hdrHashAndInfo := mp.hdrsForCurrBlock.GetHeadersInfoMap() + headers := make([]data.ShardHeaderHandler, 0, len(hdrHashAndInfo)) + headerHashes := make([][]byte, 0, len(hdrHashAndInfo)) for hdrHash, headerInfo := range hdrHashAndInfo { if !headerInfo.UsedInBlock() { continue @@ -1920,52 +1962,16 @@ func (mp *metaProcessor) createShardInfo() ([]data.ShardDataHandler, error) { return nil, process.ErrWrongTypeAssertion } - shardData := block.ShardData{} - shardData.TxCount = shardHdr.GetTxCount() - shardData.ShardID = shardHdr.GetShardID() - shardData.HeaderHash = []byte(hdrHash) - shardData.Round = shardHdr.GetRound() - shardData.PrevHash = shardHdr.GetPrevHash() - shardData.Nonce = shardHdr.GetNonce() - shardData.PrevRandSeed = shardHdr.GetPrevRandSeed() - shardData.PubKeysBitmap = shardHdr.GetPubKeysBitmap() - if mp.enableEpochsHandler.IsFlagEnabledInEpoch(common.AndromedaFlag, shardHdr.GetEpoch()) { - shardData.Epoch = shardHdr.GetEpoch() - } - shardData.NumPendingMiniBlocks = uint32(len(mp.pendingMiniBlocksHandler.GetPendingMiniBlocks(shardData.ShardID))) - header, _, err := mp.blockTracker.GetLastSelfNotarizedHeader(shardHdr.GetShardID()) - if err != nil { - return nil, err - } - shardData.LastIncludedMetaNonce = header.GetNonce() - shardData.AccumulatedFees = shardHdr.GetAccumulatedFees() - shardData.DeveloperFees = shardHdr.GetDeveloperFees() - - for i := 0; i < len(shardHdr.GetMiniBlockHeaderHandlers()); i++ { - if mp.enableEpochsHandler.IsFlagEnabled(common.ScheduledMiniBlocksFlag) { - miniBlockHeader := shardHdr.GetMiniBlockHeaderHandlers()[i] - if !miniBlockHeader.IsFinal() { - log.Debug("metaProcessor.createShardInfo: do not create shard data with mini block which is not final", "mb hash", miniBlockHeader.GetHash()) - continue - } - } - - shardMiniBlockHeader := block.MiniBlockHeader{} - shardMiniBlockHeader.SenderShardID = shardHdr.GetMiniBlockHeaderHandlers()[i].GetSenderShardID() - shardMiniBlockHeader.ReceiverShardID = shardHdr.GetMiniBlockHeaderHandlers()[i].GetReceiverShardID() - shardMiniBlockHeader.Hash = shardHdr.GetMiniBlockHeaderHandlers()[i].GetHash() - shardMiniBlockHeader.TxCount = shardHdr.GetMiniBlockHeaderHandlers()[i].GetTxCount() - shardMiniBlockHeader.Type = block.Type(shardHdr.GetMiniBlockHeaderHandlers()[i].GetTypeInt32()) - - shardData.ShardMiniBlockHeaders = append(shardData.ShardMiniBlockHeaders, shardMiniBlockHeader) - } + headers = append(headers, shardHdr) + headerHashes = append(headerHashes, []byte(hdrHash)) + } - shardInfo = append(shardInfo, &shardData) + shardInfo, err := mp.shardInfoCreateData.CreateShardInfoFromLegacyMeta(metaHdr, headers, headerHashes) + if err != nil { + return nil, err } - log.Debug("created shard data", - "size", len(shardInfo), - ) + log.Debug("created shard data", "size", len(shardInfo)) return shardInfo, nil } @@ -2051,7 +2057,7 @@ func (mp *metaProcessor) applyBodyToHeader(metaHdr data.MetaHeaderHandler, bodyH }() sw.Start("createShardInfo") - shardInfo, err := mp.createShardInfo() + shardInfo, err := mp.createShardInfo(metaHdr) sw.Stop("createShardInfo") if err != nil { return nil, err diff --git a/process/block/metablock_test.go b/process/block/metablock_test.go index bcd52c1ea15..582a1da12f9 100644 --- a/process/block/metablock_test.go +++ b/process/block/metablock_test.go @@ -195,6 +195,14 @@ func createMockMetaArguments( } gasComputation, _ := blproc.NewGasConsumption(argsGasConsumption) + shardInfoCreator, _ := blproc.NewShardInfoCreateData( + coreComponents.EnableEpochsHandler(), + dataComponents.Datapool().Headers(), + dataComponents.Datapool().Proofs(), + &mock.PendingMiniBlocksHandlerStub{}, + blockTracker, + ) + arguments := blproc.ArgMetaProcessor{ ArgBaseProcessor: blproc.ArgBaseProcessor{ CoreComponents: coreComponents, @@ -243,6 +251,7 @@ func createMockMetaArguments( EpochValidatorInfoCreator: &testscommon.EpochValidatorInfoCreatorStub{}, ValidatorStatisticsProcessor: &testscommon.ValidatorStatisticsProcessorStub{}, EpochSystemSCProcessor: &testscommon.EpochStartSystemSCStub{}, + ShardInfoCreator: shardInfoCreator, } return arguments } @@ -1395,16 +1404,16 @@ func TestMetaProcessor_CreateShardInfoShouldWorkNoHdrAddataRetrieverMockdedNotVa mp, _ := blproc.NewMetaProcessor(arguments) round := uint64(10) - shardInfo, err := mp.CreateShardInfo() + metaHdr := &block.MetaBlock{Round: round} + shardInfo, err := mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 0, len(shardInfo)) - metaHdr := &block.MetaBlock{Round: round} _, err = mp.CreateBlockBody(metaHdr, func() bool { return true }) assert.Nil(t, err) - shardInfo, err = mp.CreateShardInfo() + shardInfo, err = mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 1, len(shardInfo)) } @@ -1500,14 +1509,14 @@ func TestMetaProcessor_CreateShardInfoShouldWorkNoHdrAddedNotFinal(t *testing.T) mp.SetShardBlockFinality(0) round := uint64(40) - shardInfo, err := mp.CreateShardInfo() + metaHdr := &block.MetaBlock{Round: round} + shardInfo, err := mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 0, len(shardInfo)) - metaHdr := &block.MetaBlock{Round: round} _, err = mp.CreateBlockBody(metaHdr, haveTimeHandler) assert.Nil(t, err) - shardInfo, err = mp.CreateShardInfo() + shardInfo, err = mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 3, len(shardInfo)) } @@ -1652,14 +1661,14 @@ func TestMetaProcessor_CreateShardInfoShouldWorkHdrsAdded(t *testing.T) { mp.SetShardBlockFinality(1) round := uint64(15) - shardInfo, err := mp.CreateShardInfo() + metaHdr := &block.MetaBlock{Round: round} + shardInfo, err := mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 0, len(shardInfo)) - metaHdr := &block.MetaBlock{Round: round} _, err = mp.CreateBlockBody(metaHdr, haveTimeHandler) assert.Nil(t, err) - shardInfo, err = mp.CreateShardInfo() + shardInfo, err = mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 3, len(shardInfo)) } @@ -1805,14 +1814,14 @@ func TestMetaProcessor_CreateShardInfoEmptyBlockHDRRoundTooHigh(t *testing.T) { mp.SetShardBlockFinality(1) round := uint64(20) - shardInfo, err := mp.CreateShardInfo() + metaHdr := &block.MetaBlock{Round: round} + shardInfo, err := mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 0, len(shardInfo)) - metaHdr := &block.MetaBlock{Round: round} _, err = mp.CreateBlockBody(metaHdr, haveTimeHandler) assert.Nil(t, err) - shardInfo, err = mp.CreateShardInfo() + shardInfo, err = mp.CreateShardInfo(metaHdr) assert.Nil(t, err) assert.Equal(t, 3, len(shardInfo)) } diff --git a/process/block/shardInfo.go b/process/block/shardInfo.go new file mode 100644 index 00000000000..9e5cacfb110 --- /dev/null +++ b/process/block/shardInfo.go @@ -0,0 +1,274 @@ +package block + +import ( + "encoding/hex" + "fmt" + + "github.com/multiversx/mx-chain-core-go/core/check" + "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-core-go/data/block" + + "github.com/multiversx/mx-chain-go/common" + "github.com/multiversx/mx-chain-go/dataRetriever" + "github.com/multiversx/mx-chain-go/process" +) + +// ShardInfoCreateData is a component used to create shard info from shard headers +type ShardInfoCreateData struct { + enableEpochsHandler common.EnableEpochsHandler + headersPool dataRetriever.HeadersPool + proofsPool dataRetriever.ProofsPool + pendingMiniBlocksHandler process.PendingMiniBlocksHandler + blockTracker process.BlockTracker +} + +// NewShardInfoCreateData creates a new ShardInfoCreateData instance +func NewShardInfoCreateData( + enableEpochsHandler common.EnableEpochsHandler, + headersPool dataRetriever.HeadersPool, + proofsPool dataRetriever.ProofsPool, + pendingMiniBlocksHandler process.PendingMiniBlocksHandler, + blockTracker process.BlockTracker, +) (*ShardInfoCreateData, error) { + if check.IfNil(enableEpochsHandler) { + return nil, process.ErrNilEnableEpochsHandler + } + if check.IfNil(headersPool) { + return nil, process.ErrNilHeadersDataPool + } + if check.IfNil(proofsPool) { + return nil, process.ErrNilProofsPool + } + if check.IfNil(pendingMiniBlocksHandler) { + return nil, process.ErrNilPendingMiniBlocksHandler + } + if check.IfNil(blockTracker) { + return nil, process.ErrNilBlockTracker + } + + return &ShardInfoCreateData{ + enableEpochsHandler: enableEpochsHandler, + headersPool: headersPool, + proofsPool: proofsPool, + pendingMiniBlocksHandler: pendingMiniBlocksHandler, + blockTracker: blockTracker, + }, nil +} + +// CreateShardInfoV3 creates shard info for V3 metablock headers +func (sic *ShardInfoCreateData) CreateShardInfoV3( + metaHeader data.MetaHeaderHandler, + shardHeaders []data.HeaderHandler, + shardHeaderHashes [][]byte, +) ([]data.ShardDataHandler, error) { + if !metaHeader.IsHeaderV3() { + return nil, process.ErrInvalidHeader + } + + var shardInfo []data.ShardDataHandler + if len(shardHeaders) != len(shardHeaderHashes) { + return nil, process.ErrInconsistentShardHeadersAndHashes + } + + for i := 0; i < len(shardHeaders); i++ { + shardData, err := sic.createShardInfoFromHeader(shardHeaders[i], shardHeaderHashes[i]) + if err != nil { + return nil, err + } + shardInfo = append(shardInfo, shardData...) + } + + return shardInfo, nil +} + +// CreateShardInfoFromLegacyMeta creates shard info for legacy meta header +func (sic *ShardInfoCreateData) CreateShardInfoFromLegacyMeta( + metaHeader data.MetaHeaderHandler, + shardHeaders []data.ShardHeaderHandler, + shardHeaderHashes [][]byte, +) ([]data.ShardDataHandler, error) { + if metaHeader.IsHeaderV3() { + return nil, process.ErrInvalidHeader + } + + if len(shardHeaders) != len(shardHeaderHashes) { + return nil, process.ErrInconsistentShardHeadersAndHashes + } + + shardInfo := make([]data.ShardDataHandler, 0) + for i := 0; i < len(shardHeaders); i++ { + shardData, err := sic.createShardDataFromLegacyHeader(shardHeaders[i], shardHeaderHashes[i]) + if err != nil { + return nil, err + } + shardInfo = append(shardInfo, shardData...) + } + + return shardInfo, nil +} + +func (sic *ShardInfoCreateData) createShardInfoFromHeader(shardHeader data.HeaderHandler, hdrHash []byte) ([]data.ShardDataHandler, error) { + if check.IfNil(shardHeader) { + return nil, process.ErrNilHeaderHandler + } + if len(hdrHash) == 0 { + return nil, process.ErrInvalidHash + } + + hasMissingShardHdrProof := shardHeader.GetNonce() >= 1 && !sic.proofsPool.HasProof(shardHeader.GetShardID(), hdrHash) + if hasMissingShardHdrProof { + return nil, fmt.Errorf("%w for shard header with hash %s", process.ErrMissingHeaderProof, hex.EncodeToString(hdrHash)) + } + + if !shardHeader.IsHeaderV3() { + return sic.createShardDataFromLegacyHeader(shardHeader, hdrHash) + } + + return sic.createShardDataFromV3Header(shardHeader) +} + +func (sic *ShardInfoCreateData) createShardDataFromLegacyHeader(shardHdr data.HeaderHandler, hdrHash []byte) ([]data.ShardDataHandler, error) { + shardData := &block.ShardData{} + shardData.TxCount = shardHdr.GetTxCount() + shardData.ShardID = shardHdr.GetShardID() + shardData.HeaderHash = hdrHash + shardData.Round = shardHdr.GetRound() + shardData.PrevHash = shardHdr.GetPrevHash() + shardData.Nonce = shardHdr.GetNonce() + shardData.PrevRandSeed = shardHdr.GetPrevRandSeed() + shardData.PubKeysBitmap = shardHdr.GetPubKeysBitmap() + if sic.enableEpochsHandler.IsFlagEnabledInEpoch(common.AndromedaFlag, shardHdr.GetEpoch()) { + shardData.Epoch = shardHdr.GetEpoch() + } + shardData.AccumulatedFees = shardHdr.GetAccumulatedFees() + shardData.DeveloperFees = shardHdr.GetDeveloperFees() + shardData.ShardMiniBlockHeaders = createShardMiniBlockHeaderFromHeader(shardHdr, sic.enableEpochsHandler) + err := sic.updateShardDataWithCrossShardInfo(shardData, shardHdr) + if err != nil { + return nil, err + } + + return []data.ShardDataHandler{shardData}, nil +} + +func (sic *ShardInfoCreateData) createShardDataFromV3Header(shardHeader data.HeaderHandler) ([]data.ShardDataHandler, error) { + if check.IfNil(shardHeader) { + return nil, process.ErrNilHeaderHandler + } + executionResults := shardHeader.GetExecutionResultsHandlers() + if len(executionResults) == 0 { + return []data.ShardDataHandler{}, nil + } + + shardDataHandlers := make([]data.ShardDataHandler, len(executionResults)) + for i, execResult := range executionResults { + shardData, err := sic.createShardDataFromExecutionResult(execResult) + if err != nil { + return nil, err + } + shardDataHandlers[i] = shardData + } + + return shardDataHandlers, nil +} + +func (sic *ShardInfoCreateData) createShardDataFromExecutionResult( + execResult data.BaseExecutionResultHandler, +) (data.ShardDataHandler, error) { + if check.IfNil(execResult) { + return nil, process.ErrNilExecutionResultHandler + } + + execResultHandler, ok := execResult.(data.ExecutionResultHandler) + if !ok { + return nil, process.ErrWrongTypeAssertion + } + + execResultHandler.GetMiniBlockHeadersHandlers() + header, err := sic.headersPool.GetHeaderByHash(execResultHandler.GetHeaderHash()) + if err != nil { + return nil, err + } + + shardData := &block.ShardData{} + shardData.TxCount = uint32(execResultHandler.GetExecutedTxCount()) + shardData.ShardID = header.GetShardID() + shardData.HeaderHash = execResultHandler.GetHeaderHash() + shardData.Round = execResultHandler.GetHeaderRound() + shardData.PrevHash = header.GetPrevHash() + shardData.Nonce = execResultHandler.GetHeaderNonce() + shardData.PrevRandSeed = header.GetPrevRandSeed() + shardData.PubKeysBitmap = header.GetPubKeysBitmap() + shardData.Epoch = header.GetEpoch() + shardData.AccumulatedFees = execResultHandler.GetAccumulatedFees() + shardData.DeveloperFees = execResultHandler.GetDeveloperFees() + shardData.ShardMiniBlockHeaders = createShardMiniBlockHeaderFromExecutionResultHandler(execResultHandler) + err = sic.updateShardDataWithCrossShardInfo(shardData, header) + if err != nil { + return nil, err + } + + return shardData, nil +} + +func createShardMiniBlockHeaderFromHeader( + shardHdr data.HeaderHandler, + enableEpochsHandler common.EnableEpochsHandler, +) []block.MiniBlockHeader { + shardMiniBlockHeaders := make([]block.MiniBlockHeader, 0) + for i := 0; i < len(shardHdr.GetMiniBlockHeaderHandlers()); i++ { + if enableEpochsHandler.IsFlagEnabled(common.ScheduledMiniBlocksFlag) { + miniBlockHeader := shardHdr.GetMiniBlockHeaderHandlers()[i] + if !miniBlockHeader.IsFinal() { + log.Debug("metaProcessor.createShardInfo: do not create shard data with mini block which is not final", "mb hash", miniBlockHeader.GetHash()) + continue + } + } + + shardMiniBlockHeader := miniBlockHeaderFromMiniBlockHeaderHandler(shardHdr.GetMiniBlockHeaderHandlers()[i]) + shardMiniBlockHeaders = append(shardMiniBlockHeaders, shardMiniBlockHeader) + } + return shardMiniBlockHeaders +} + +func createShardMiniBlockHeaderFromExecutionResultHandler( + execResultHandler data.ExecutionResultHandler, +) []block.MiniBlockHeader { + mbHeaderHandlers := execResultHandler.GetMiniBlockHeadersHandlers() + shardMiniBlockHeaders := make([]block.MiniBlockHeader, 0) + for i := 0; i < len(mbHeaderHandlers); i++ { + shardMiniBlockHeader := miniBlockHeaderFromMiniBlockHeaderHandler(mbHeaderHandlers[i]) + shardMiniBlockHeaders = append(shardMiniBlockHeaders, shardMiniBlockHeader) + } + return shardMiniBlockHeaders +} + +func miniBlockHeaderFromMiniBlockHeaderHandler(miniBlockHeaderHandler data.MiniBlockHeaderHandler) block.MiniBlockHeader { + shardMiniBlockHeader := block.MiniBlockHeader{} + shardMiniBlockHeader.SenderShardID = miniBlockHeaderHandler.GetSenderShardID() + shardMiniBlockHeader.ReceiverShardID = miniBlockHeaderHandler.GetReceiverShardID() + shardMiniBlockHeader.Hash = miniBlockHeaderHandler.GetHash() + shardMiniBlockHeader.TxCount = miniBlockHeaderHandler.GetTxCount() + shardMiniBlockHeader.Type = block.Type(miniBlockHeaderHandler.GetTypeInt32()) + + return shardMiniBlockHeader +} + +func (sic *ShardInfoCreateData) updateShardDataWithCrossShardInfo(shardData *block.ShardData, header data.HeaderHandler) error { + // TODO: pendingMiniBlocksHandler should be updated + shardData.NumPendingMiniBlocks = uint32(len(sic.pendingMiniBlocksHandler.GetPendingMiniBlocks(header.GetShardID()))) + + // TODO: the last self notarized header should be fetched based on the nonce from the execution result + metaHeader, _, err := sic.blockTracker.GetLastSelfNotarizedHeader(header.GetShardID()) + if err != nil { + return err + } + shardData.LastIncludedMetaNonce = metaHeader.GetNonce() + + return nil +} + +// IsInterfaceNil returns true if there is no value under the interface +func (sic *ShardInfoCreateData) IsInterfaceNil() bool { + return sic == nil +} diff --git a/process/interface.go b/process/interface.go index f0a3199c8ed..430d09a486e 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1532,6 +1532,7 @@ type GasComputation interface { transactions []data.TransactionHandler, ) (addedTxHashes [][]byte, pendingMiniBlocksAdded []data.MiniBlockHeaderHandler, err error) GetBandwidthForTransactions() uint64 + RevertIncomingMiniBlocks(miniBlockHashes [][]byte) TotalGasConsumed() uint64 DecreaseIncomingLimit() DecreaseOutgoingLimit() @@ -1576,3 +1577,9 @@ type InclusionEstimator interface { Decide(lastNotarised *estimator.LastExecutionResultForInclusion, pending []data.BaseExecutionResultHandler, currentHeaderRound uint64) (allowed int) IsInterfaceNil() bool } + +// ShardInfoCreator defines the functionality to create shard info +type ShardInfoCreator interface { + CreateShardInfoV3(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) + CreateShardInfoFromLegacyMeta(metaHeader data.MetaHeaderHandler, shardHeaders []data.ShardHeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) +} From 1b1eaf5461bc4cf4716a70c6747b07c27eea0423 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 21 Oct 2025 18:28:08 +0300 Subject: [PATCH 07/51] update metablock proposal --- go.mod | 2 +- go.sum | 4 +- process/block/argProcessor.go | 1 + process/block/export_test.go | 4 +- process/block/gasConsumption.go | 6 + process/block/metablockProposal.go | 215 +++++++++++++++++++++++++---- process/errors.go | 6 + testscommon/gasComputationMock.go | 8 ++ 8 files changed, 215 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index 17907cb34e0..654036a2b05 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.13.0 github.com/mitchellh/mapstructure v1.5.0 github.com/multiversx/mx-chain-communication-go v1.3.0 - github.com/multiversx/mx-chain-core-go v1.4.1-0.20251008130922-c1e8eb2b3a8a + github.com/multiversx/mx-chain-core-go v1.4.1-0.20251020075533-46c8ae554d44 github.com/multiversx/mx-chain-crypto-go v1.3.0 github.com/multiversx/mx-chain-es-indexer-go v1.9.1 github.com/multiversx/mx-chain-logger-go v1.1.0 diff --git a/go.sum b/go.sum index dbee0641c7d..936b2d7ab26 100644 --- a/go.sum +++ b/go.sum @@ -401,8 +401,8 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-communication-go v1.3.0 h1:ziNM1dRuiR/7al2L/jGEA/a/hjurtJ/HEqgazHNt9P8= github.com/multiversx/mx-chain-communication-go v1.3.0/go.mod h1:gDVWn6zUW6aCN1YOm/FbbT5MUmhgn/L1Rmpl8EoH3Yg= -github.com/multiversx/mx-chain-core-go v1.4.1-0.20251008130922-c1e8eb2b3a8a h1:hP3LyKlbu9P9FPU1wM/s7lJ4UvOAdzby45p20MAnkrg= -github.com/multiversx/mx-chain-core-go v1.4.1-0.20251008130922-c1e8eb2b3a8a/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= +github.com/multiversx/mx-chain-core-go v1.4.1-0.20251020075533-46c8ae554d44 h1:oAxNDn87sRvUOA2/0CmFCjDPzDUB9FPvQKMkcIxOe84= +github.com/multiversx/mx-chain-core-go v1.4.1-0.20251020075533-46c8ae554d44/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= github.com/multiversx/mx-chain-crypto-go v1.3.0 h1:0eK2bkDOMi8VbSPrB1/vGJSYT81IBtfL4zw+C4sWe/k= github.com/multiversx/mx-chain-crypto-go v1.3.0/go.mod h1:nPIkxxzyTP8IquWKds+22Q2OJ9W7LtusC7cAosz7ojM= github.com/multiversx/mx-chain-es-indexer-go v1.9.1 h1:Jg/4CLzIiwyrjuy+ZccEJ4TcvlHXnBUr5o3pclVitGo= diff --git a/process/block/argProcessor.go b/process/block/argProcessor.go index 81b9a54d76a..99757ff160a 100644 --- a/process/block/argProcessor.go +++ b/process/block/argProcessor.go @@ -124,4 +124,5 @@ type ArgMetaProcessor struct { EpochValidatorInfoCreator process.EpochStartValidatorInfoCreator EpochSystemSCProcessor process.EpochStartSystemSCProcessor ValidatorStatisticsProcessor process.ValidatorStatisticsProcessor + ShardInfoCreator process.ShardInfoCreator } diff --git a/process/block/export_test.go b/process/block/export_test.go index 883e9cb94e8..0a259808562 100644 --- a/process/block/export_test.go +++ b/process/block/export_test.go @@ -275,8 +275,8 @@ func (mp *metaProcessor) IsHdrMissing(hdrHash []byte) bool { } // CreateShardInfo - -func (mp *metaProcessor) CreateShardInfo() ([]data.ShardDataHandler, error) { - return mp.createShardInfo() +func (mp *metaProcessor) CreateShardInfo(metaHeader data.MetaHeaderHandler) ([]data.ShardDataHandler, error) { + return mp.createShardInfo(metaHeader) } // SaveMetricCrossCheckBlockHeight - diff --git a/process/block/gasConsumption.go b/process/block/gasConsumption.go index ed59a18895d..c7417584b0d 100644 --- a/process/block/gasConsumption.go +++ b/process/block/gasConsumption.go @@ -6,6 +6,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-go/process" ) @@ -524,6 +525,11 @@ func (gc *gasConsumption) maxGasLimitPerMiniBlock(shardID uint32) uint64 { return gc.economicsFee.MaxGasLimitPerMiniBlock(shardID) } +// RevertIncomingMiniBlocks reverts the gas consumption for the given incoming mini blocks +func (gc *gasConsumption) RevertIncomingMiniBlocks(miniBlockHashes [][]byte) { + // TODO: implement this +} + // IsInterfaceNil checks if the interface is nil func (gc *gasConsumption) IsInterfaceNil() bool { return gc == nil diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 954160272fe..efe805602b8 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -3,9 +3,11 @@ package block import ( "time" + "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + logger "github.com/multiversx/mx-chain-logger-go" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" @@ -46,13 +48,22 @@ func (mp *metaProcessor) CreateNewHeaderProposal(round uint64, nonce uint64) (da if err != nil { return nil, err } - if hasEpochStartResults { - err := metaHeader.SetEpoch(epoch + 1) - if err != nil { - return nil, err - } + if !hasEpochStartResults { + return metaHeader, nil } + err = metaHeader.SetEpoch(epoch + 1) + if err != nil { + return nil, err + } + if mp.epochStartData == nil { + return nil, process.ErrNilEpochStartData + } + + err = metaHeader.SetEpochStartHandler(mp.epochStartData) + if err != nil { + return nil, err + } // TODO: the trigger would need to be changed upon commit of a block with the epoch start results return metaHeader, nil @@ -77,31 +88,43 @@ func (mp *metaProcessor) CreateBlockProposal( metaHdr.SoftwareVersion = []byte(mp.headerIntegrityVerifier.GetVersion(metaHdr.Epoch, metaHdr.Round)) - // var body data.BodyHandler - // err := mp.updateHeaderForEpochStartIfNeeded(metaHdr) - // if err != nil { - // return nil, nil, err - // } - // - // err = mp.blockChainHook.SetCurrentHeader(metaHdr) - // if err != nil { - // return nil, nil, err - // } - // - // body, err = mp.createBody(metaHdr, haveTime) - // if err != nil { - // return nil, nil, err - // } - // + var body data.BodyHandler + if metaHdr.IsStartOfEpochBlock() { + // no new transactions in start of epoch block + // to simplify bootstrapping + return metaHdr, &block.Body{}, nil + } + + mp.gasComputation.Reset() + mp.miniBlocksSelectionSession.ResetSelectionSession() + err := mp.createBlockBodyProposal(metaHdr, haveTime) + if err != nil { + return nil, nil, err + } + + mbsToMe := mp.miniBlocksSelectionSession.GetMiniBlocks() + numTxs := mp.miniBlocksSelectionSession.GetNumTxsAdded() + referencedShardHeaderHashes := mp.miniBlocksSelectionSession.GetReferencedHeaderHashes() + referencedShardHeaders := mp.miniBlocksSelectionSession.GetReferencedHeaders() + if len(mbsToMe) > 0 { + log.Debug("processed miniblocks and txs with destination in self shard", + "num miniblocks", len(mbsToMe), + "num txs", numTxs, + "num shard headers", len(referencedShardHeaderHashes), + ) + } + + defer func() { + go mp.checkAndRequestIfShardHeadersMissing() + }() + + mp.shardInfoCreateData.CreateShardInfoV3(metaHdr, referencedShardHeaders, referencedShardHeaderHashes) + // body, err = mp.applyBodyToHeader(metaHdr, body) // if err != nil { // return nil, nil, err // } - // - // mp.requestHandler.SetEpoch(metaHdr.GetEpoch()) - // return metaHdr, body, nil - - return nil, nil, nil + return metaHdr, body, nil } // VerifyBlockProposal will be implemented in a further PR @@ -144,3 +167,143 @@ func hasRewardMiniBlocks(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { } return false } + +func (mp *metaProcessor) createBlockBodyProposal( + metaHdr data.MetaHeaderHandler, + haveTime func() bool, +) error { + mp.blockSizeThrottler.ComputeCurrentMaxSize() + + log.Debug("started creating block body", + "epoch", metaHdr.GetEpoch(), + "round", metaHdr.GetRound(), + "nonce", metaHdr.GetNonce(), + ) + + return mp.createProposalMiniBlocks(haveTime) +} + +func (mp *metaProcessor) createProposalMiniBlocks(haveTime func() bool) error { + if !haveTime() { + log.Debug("metaProcessor.createProposalMiniBlocks", "error", process.ErrTimeIsOut) + return nil + } + + startTime := time.Now() + err := mp.selectIncomingMiniBlocksForProposal(haveTime) + if err != nil { + return err + } + elapsedTime := time.Since(startTime) + log.Debug("elapsed time to create mbs to me", "time", elapsedTime) + + return nil +} + +func (mp *metaProcessor) selectIncomingMiniBlocksForProposal( + haveTime func() bool, +) error { + sw := core.NewStopWatch() + sw.Start("ComputeLongestShardsChainsFromLastNotarized") + orderedHdrs, orderedHdrsHashes, _, err := mp.blockTracker.ComputeLongestShardsChainsFromLastNotarized() + sw.Stop("ComputeLongestShardsChainsFromLastNotarized") + log.Debug("measurements ComputeLongestShardsChainsFromLastNotarized", sw.GetMeasurements()...) + if err != nil { + return err + } + + log.Debug("shard headers ordered", + "num shard headers", len(orderedHdrs), + ) + + lastShardHdr, err := mp.getLastCrossNotarizedShardHdrs() + if err != nil { + return err + } + + err = mp.selectIncomingMiniBlocks(lastShardHdr, orderedHdrs, orderedHdrsHashes, haveTime) + if err != nil { + return err + } + + return nil +} + +func (mp *metaProcessor) selectIncomingMiniBlocks( + lastShardHdr map[uint32]ShardHeaderInfo, + orderedHdrs []data.HeaderHandler, + orderedHdrsHashes [][]byte, + haveTime func() bool, +) error { + hdrsAdded := uint32(0) + maxShardHeadersFromSameShard := core.MaxUint32( + process.MinShardHeadersFromSameShardInOneMetaBlock, + process.MaxShardHeadersAllowedInOneMetaBlock/mp.shardCoordinator.NumberOfShards(), + ) + maxShardHeadersAllowedInOneMetaBlock := maxShardHeadersFromSameShard * mp.shardCoordinator.NumberOfShards() + hdrsAddedForShard := make(map[uint32]uint32) + for i := 0; i < len(orderedHdrs); i++ { + if !haveTime() { + log.Debug("time is up after putting cross txs with destination to current shard", + "num txs", mp.miniBlocksSelectionSession.GetNumTxsAdded(), + ) + break + } + + if hdrsAdded >= maxShardHeadersAllowedInOneMetaBlock { + log.Debug("maximum shard headers allowed to be included in one meta block has been reached", + "shard headers added", hdrsAdded, + ) + break + } + + currShardHdr := orderedHdrs[i] + if currShardHdr.GetNonce() > lastShardHdr[currShardHdr.GetShardID()].Header.GetNonce()+1 { + log.Trace("skip searching", + "shard", currShardHdr.GetShardID(), + "last shard hdr nonce", lastShardHdr[currShardHdr.GetShardID()].Header.GetNonce(), + "curr shard hdr nonce", currShardHdr.GetNonce()) + continue + } + + if hdrsAddedForShard[currShardHdr.GetShardID()] >= maxShardHeadersFromSameShard { + log.Trace("maximum shard headers from same shard allowed to be included in one meta block has been reached", + "shard", currShardHdr.GetShardID(), + "shard headers added", hdrsAddedForShard[currShardHdr.GetShardID()], + ) + continue + } + + hasProofForHdr := mp.proofsPool.HasProof(currShardHdr.GetShardID(), orderedHdrsHashes[i]) + if !hasProofForHdr { + log.Trace("no proof for shard header", + "shard", currShardHdr.GetShardID(), + "hash", logger.DisplayByteSlice(orderedHdrsHashes[i]), + ) + continue + } + + if len(currShardHdr.GetMiniBlockHeadersWithDst(mp.shardCoordinator.SelfId())) == 0 { + mp.miniBlocksSelectionSession.AddReferencedHeader(orderedHdrs[i], orderedHdrsHashes[i]) + continue + } + + _, pendingMiniBlocks, errCreated := mp.createMbsCrossShardDstMe(orderedHdrsHashes[i], currShardHdr, nil, true) + if errCreated != nil { + return errCreated + } + + // pending miniBlocks were already reverted, but still returned to check if we need to stop adding more shard headers + if len(pendingMiniBlocks) > 0 { + log.Debug("shard header cannot be fully added", + "round", currShardHdr.GetRound(), + "nonce", currShardHdr.GetNonce(), + "hash", orderedHdrsHashes[i]) + break + } + + mp.miniBlocksSelectionSession.AddReferencedHeader(currShardHdr, orderedHdrsHashes[i]) + } + + return nil +} diff --git a/process/errors.go b/process/errors.go index 49445b37119..ff1afffee01 100644 --- a/process/errors.go +++ b/process/errors.go @@ -1406,3 +1406,9 @@ var ErrZeroLimit = errors.New("zero limit") // ErrInvalidBlockType signals that an invalid block type has been provided var ErrInvalidBlockType = errors.New("invalid block type") + +// ErrNilEpochStartData signals that nil epoch start data has been provided +var ErrNilEpochStartData = errors.New("nil epoch start data") + +// ErrInconsistentShardHeadersAndHashes signals that shard headers are inconsistent with their hashes +var ErrInconsistentShardHeadersAndHashes = errors.New("inconsistent shard headers and hashes") diff --git a/testscommon/gasComputationMock.go b/testscommon/gasComputationMock.go index de98d5346ac..a5fa33e5045 100644 --- a/testscommon/gasComputationMock.go +++ b/testscommon/gasComputationMock.go @@ -23,6 +23,7 @@ type GasComputationMock struct { ResetIncomingLimitCalled func() ResetOutgoingLimitCalled func() ResetCalled func() + RevertIncomingMiniBlocksCalled func(miniBlockHashes [][]byte) } // CheckIncomingMiniBlocks - @@ -55,6 +56,13 @@ func (mock *GasComputationMock) GetBandwidthForTransactions() uint64 { return 0 } +// RevertIncomingMiniBlocks - +func (mock *GasComputationMock) RevertIncomingMiniBlocks(miniBlockHashes [][]byte) { + if mock.RevertIncomingMiniBlocksCalled != nil { + mock.RevertIncomingMiniBlocksCalled(miniBlockHashes) + } +} + // TotalGasConsumed - func (mock *GasComputationMock) TotalGasConsumed() uint64 { if mock.TotalGasConsumedCalled != nil { From 44a64d9f395c72c3ab0f1c705d12f8621e7b385c Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 21 Oct 2025 18:57:49 +0300 Subject: [PATCH 08/51] fixes integration tests --- integrationTests/testFullNode.go | 21 +++++++++++++++++++ integrationTests/testProcessorNode.go | 13 +++++++++++- integrationTests/testSyncNode.go | 11 ++++++++++ .../vm/staking/metaBlockProcessorCreator.go | 10 +++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/integrationTests/testFullNode.go b/integrationTests/testFullNode.go index ebee60a7f51..00207f52960 100644 --- a/integrationTests/testFullNode.go +++ b/integrationTests/testFullNode.go @@ -1170,6 +1170,15 @@ func (tpn *TestFullNode) initBlockProcessor( epochStartSystemSCProcessor, _ := metachain.NewSystemSCProcessor(argsEpochSystemSC) tpn.EpochStartSystemSCProcessor = epochStartSystemSCProcessor + shardInfoCreator, errShardInfoCreate := block.NewShardInfoCreateData( + tpn.EnableEpochsHandler, + tpn.DataPool.Headers(), + tpn.DataPool.Proofs(), + &mock.PendingMiniBlocksHandlerStub{}, + argumentsBase.BlockTracker, + ) + log.LogIfError(errShardInfoCreate) + arguments := block.ArgMetaProcessor{ ArgBaseProcessor: argumentsBase, SCToProtocol: scToProtocolInstance, @@ -1180,6 +1189,7 @@ func (tpn *TestFullNode) initBlockProcessor( EpochValidatorInfoCreator: epochStartValidatorInfo, ValidatorStatisticsProcessor: tpn.ValidatorStatisticsProcessor, EpochSystemSCProcessor: epochStartSystemSCProcessor, + ShardInfoCreator: shardInfoCreator, } tpn.BlockProcessor, err = block.NewMetaProcessor(arguments) @@ -1356,6 +1366,16 @@ func (tpn *TestFullNode) initBlockProcessorWithSync( if tpn.ShardCoordinator.SelfId() == core.MetachainShardId { argumentsBase.ForkDetector = tpn.ForkDetector argumentsBase.TxCoordinator = &mock.TransactionCoordinatorMock{} + + shardInfoCreator, errShardInfoCreate := block.NewShardInfoCreateData( + coreComponents.EnableEpochsHandler(), + dataComponents.DataPool.Headers(), + dataComponents.DataPool.Proofs(), + &mock.PendingMiniBlocksHandlerStub{}, + argumentsBase.BlockTracker, + ) + log.LogIfError(errShardInfoCreate) + arguments := block.ArgMetaProcessor{ ArgBaseProcessor: argumentsBase, SCToProtocol: &mock.SCToProtocolStub{}, @@ -1370,6 +1390,7 @@ func (tpn *TestFullNode) initBlockProcessorWithSync( }, }, EpochSystemSCProcessor: &testscommon.EpochStartSystemSCStub{}, + ShardInfoCreator: shardInfoCreator, } tpn.BlockProcessor, err = block.NewMetaProcessor(arguments) diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index 5b6aa49ab49..78ae7dbfd90 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -31,11 +31,12 @@ import ( ed25519SingleSig "github.com/multiversx/mx-chain-crypto-go/signing/ed25519/singlesig" "github.com/multiversx/mx-chain-crypto-go/signing/mcl" mclsig "github.com/multiversx/mx-chain-crypto-go/signing/mcl/singlesig" - "github.com/multiversx/mx-chain-go/process/asyncExecution/queue" vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/multiversx/mx-chain-vm-common-go/parsers" wasmConfig "github.com/multiversx/mx-chain-vm-go/config" + "github.com/multiversx/mx-chain-go/process/asyncExecution/queue" + "github.com/multiversx/mx-chain-go/process/asyncExecution/executionTrack" "github.com/multiversx/mx-chain-go/process/estimator" "github.com/multiversx/mx-chain-go/process/missingData" @@ -2729,6 +2730,15 @@ func (tpn *TestProcessorNode) initBlockProcessor() { epochStartSystemSCProcessor, _ := metachain.NewSystemSCProcessor(argsEpochSystemSC) tpn.EpochStartSystemSCProcessor = epochStartSystemSCProcessor + shardInfoCreator, errShardInfoCreator := block.NewShardInfoCreateData( + tpn.EnableEpochsHandler, + tpn.DataPool.Headers(), + tpn.DataPool.Proofs(), + &mock.PendingMiniBlocksHandlerStub{}, + argumentsBase.BlockTracker, + ) + log.LogIfError(errShardInfoCreator) + arguments := block.ArgMetaProcessor{ ArgBaseProcessor: argumentsBase, SCToProtocol: scToProtocolInstance, @@ -2739,6 +2749,7 @@ func (tpn *TestProcessorNode) initBlockProcessor() { EpochValidatorInfoCreator: epochStartValidatorInfo, ValidatorStatisticsProcessor: tpn.ValidatorStatisticsProcessor, EpochSystemSCProcessor: epochStartSystemSCProcessor, + ShardInfoCreator: shardInfoCreator, } tpn.BlockProcessor, err = block.NewMetaProcessor(arguments) diff --git a/integrationTests/testSyncNode.go b/integrationTests/testSyncNode.go index 9a1db209eae..882f1fabd92 100644 --- a/integrationTests/testSyncNode.go +++ b/integrationTests/testSyncNode.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/asyncExecution/executionTrack" "github.com/multiversx/mx-chain-go/process/asyncExecution/queue" @@ -219,6 +220,15 @@ func (tpn *TestProcessorNode) initBlockProcessorWithSync() { ) argumentsBase.ForkDetector = tpn.ForkDetector argumentsBase.TxCoordinator = &mock.TransactionCoordinatorMock{} + shardInfoCreator, errShardInfoCreator := block.NewShardInfoCreateData( + tpn.EnableEpochsHandler, + tpn.DataPool.Headers(), + tpn.DataPool.Proofs(), + &mock.PendingMiniBlocksHandlerStub{}, + argumentsBase.BlockTracker, + ) + log.LogIfError(errShardInfoCreator) + arguments := block.ArgMetaProcessor{ ArgBaseProcessor: argumentsBase, SCToProtocol: &mock.SCToProtocolStub{}, @@ -233,6 +243,7 @@ func (tpn *TestProcessorNode) initBlockProcessorWithSync() { }, }, EpochSystemSCProcessor: &testscommon.EpochStartSystemSCStub{}, + ShardInfoCreator: shardInfoCreator, } tpn.BlockProcessor, err = block.NewMetaProcessor(arguments) diff --git a/integrationTests/vm/staking/metaBlockProcessorCreator.go b/integrationTests/vm/staking/metaBlockProcessorCreator.go index 42550548102..329d4278f67 100644 --- a/integrationTests/vm/staking/metaBlockProcessorCreator.go +++ b/integrationTests/vm/staking/metaBlockProcessorCreator.go @@ -6,6 +6,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/process/asyncExecution/executionTrack" "github.com/multiversx/mx-chain-go/process/estimator" @@ -127,6 +128,14 @@ func createMetaBlockProcessor( } missingDataResolver, _ := missingData.NewMissingDataResolver(missingDataArgs) + shardInfoCreator, _ := blproc.NewShardInfoCreateData( + coreComponents.EnableEpochsHandler(), + dataComponents.Datapool().Headers(), + dataComponents.Datapool().Proofs(), + &mock.PendingMiniBlocksHandlerStub{}, + blockTracker, + ) + args := blproc.ArgMetaProcessor{ ArgBaseProcessor: blproc.ArgBaseProcessor{ CoreComponents: coreComponents, @@ -180,6 +189,7 @@ func createMetaBlockProcessor( EpochValidatorInfoCreator: valInfoCreator, ValidatorStatisticsProcessor: validatorsInfoCreator, EpochSystemSCProcessor: systemSCProcessor, + ShardInfoCreator: shardInfoCreator, } metaProc, _ := blproc.NewMetaProcessor(args) From 6d1e26494a51dc265f29a069a61b6af3d63683f7 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 22 Oct 2025 11:55:35 +0300 Subject: [PATCH 09/51] fixes --- process/block/baseProcess.go | 9 ++++++--- process/block/shardblockProposal.go | 2 -- process/block/shardblockProposal_test.go | 3 ++- testscommon/headerHandlerStub.go | 9 +++++++++ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 1362ff80760..ba9c1104c6e 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -2745,9 +2745,12 @@ func (bp *baseProcessor) createMbsCrossShardDstMe( return false, pendingMiniBlocks, nil } - err := bp.miniBlocksSelectionSession.AddMiniBlocksAndHashes(currMiniBlocksAdded) - if err != nil { - return false, nil, err + if len(currMiniBlocksAdded) > 0 { + err := bp.miniBlocksSelectionSession.AddMiniBlocksAndHashes(currMiniBlocksAdded) + if err != nil { + return false, nil, err + } + bp.miniBlocksSelectionSession.AddReferencedHeader(currentBlock, currentBlockHash) } if !hdrFinished { diff --git a/process/block/shardblockProposal.go b/process/block/shardblockProposal.go index 1f4156cfb00..ca358e196b0 100644 --- a/process/block/shardblockProposal.go +++ b/process/block/shardblockProposal.go @@ -601,8 +601,6 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( if errCreated != nil { return nil, errCreated } - - sp.miniBlocksSelectionSession.AddReferencedHeader(currentMetaBlock, currentMetaBlockHash) if !shouldContinue { break } diff --git a/process/block/shardblockProposal_test.go b/process/block/shardblockProposal_test.go index 7506d635b3b..4170fefe76d 100644 --- a/process/block/shardblockProposal_test.go +++ b/process/block/shardblockProposal_test.go @@ -866,7 +866,8 @@ func TestShardProcessor_SelectIncomingMiniBlocks(t *testing.T) { orderedMetaBlocksHashes = append(orderedMetaBlocksHashes, []byte("hash4")) _, err = sp.SelectIncomingMiniBlocks(providedLastCrossNotarizedMetaHdr, orderedMetaBlocks, orderedMetaBlocksHashes, haveTimeTrue) require.NoError(t, err) - require.Equal(t, 2, cntAddReferencedMetaBlockCalled) // should be called twice, the third hdr returns shouldContinue false + // should be called three times, the third hdr returns shouldContinue false, but still added miniblocks, so meta block is referenced + require.Equal(t, 3, cntAddReferencedMetaBlockCalled) }) } diff --git a/testscommon/headerHandlerStub.go b/testscommon/headerHandlerStub.go index e612cb22f8d..1a9cad48639 100644 --- a/testscommon/headerHandlerStub.go +++ b/testscommon/headerHandlerStub.go @@ -67,6 +67,15 @@ type HeaderHandlerStub struct { SetMiniBlockHeaderHandlersCalled func(mbsHandlers []data.MiniBlockHeaderHandler) error SetTxCountCalled func(count uint32) error SetMetaBlockHashesCalled func(hashes [][]byte) error + SetEpochStartHandlerCalled func(epochStartHandler data.EpochStartHandler) error +} + +// SetEpochStartHandler - +func (hhs *HeaderHandlerStub) SetEpochStartHandler(epochStartHandler data.EpochStartHandler) error { + if hhs.SetEpochStartHandlerCalled != nil { + return hhs.SetEpochStartHandlerCalled(epochStartHandler) + } + return nil } // SetLastExecutionResultHandler - From d9ab0f955202fba1f793d403e8e5a94e72906238 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 22 Oct 2025 12:20:31 +0300 Subject: [PATCH 10/51] fixes and renaming --- process/block/shardblockProposal.go | 7 ++-- process/block/shardblockProposal_test.go | 14 ++++---- .../mbSelection/mbSelectionSessionStub.go | 32 +++++++++---------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/process/block/shardblockProposal.go b/process/block/shardblockProposal.go index ca358e196b0..7b405e0de73 100644 --- a/process/block/shardblockProposal.go +++ b/process/block/shardblockProposal.go @@ -553,6 +553,7 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( var pendingMiniBlocks []block.MiniblockAndHash var errCreated error var shouldContinue bool + lastMeta := lastCrossNotarizedMetaHdr for i := 0; i < len(orderedMetaBlocks); i++ { if !haveTime() { log.Debug("time is up after putting cross txs with destination to current shard", @@ -569,9 +570,9 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( } currentMetaBlock = orderedMetaBlocks[i] - if currentMetaBlock.GetNonce() > lastCrossNotarizedMetaHdr.GetNonce()+1 { + if currentMetaBlock.GetNonce() > lastMeta.GetNonce()+1 { log.Debug("skip searching", - "last meta hdr nonce", lastCrossNotarizedMetaHdr.GetNonce(), + "last meta hdr nonce", lastMeta.GetNonce(), "curr meta hdr nonce", currentMetaBlock.GetNonce()) break } @@ -593,6 +594,7 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( if len(currentMetaBlock.GetMiniBlockHeadersWithDst(sp.shardCoordinator.SelfId())) == 0 { sp.miniBlocksSelectionSession.AddReferencedHeader(orderedMetaBlocks[i], orderedMetaBlocksHashes[i]) + lastMeta = currentMetaBlock continue } @@ -604,6 +606,7 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( if !shouldContinue { break } + lastMeta = currentMetaBlock } return pendingMiniBlocks, nil diff --git a/process/block/shardblockProposal_test.go b/process/block/shardblockProposal_test.go index 4170fefe76d..338c4cabffe 100644 --- a/process/block/shardblockProposal_test.go +++ b/process/block/shardblockProposal_test.go @@ -628,7 +628,7 @@ func TestShardProcessor_SelectIncomingMiniBlocks(t *testing.T) { coreComponents, dataComponents, bootstrapComponents, statusComponents := createComponentHolderMocks() arguments := CreateMockArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ - GetReferencedMetaBlocksCalled: func() []data.HeaderHandler { + GetReferencedHeadersCalled: func() []data.HeaderHandler { require.Fail(t, "should have not been called") return nil }, @@ -659,7 +659,7 @@ func TestShardProcessor_SelectIncomingMiniBlocks(t *testing.T) { } arguments := CreateMockArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ - GetReferencedMetaBlocksCalled: func() []data.HeaderHandler { + GetReferencedHeadersCalled: func() []data.HeaderHandler { return make([]data.HeaderHandler, process.MaxMetaHeadersAllowedInOneShardBlock) }, } @@ -808,7 +808,7 @@ func TestShardProcessor_SelectIncomingMiniBlocks(t *testing.T) { arguments := CreateMockArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) cntAddReferencedMetaBlockCalled := 0 arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ - AddReferencedMetaBlockCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddReferencedMetaBlockCalled++ }, } @@ -847,7 +847,7 @@ func TestShardProcessor_SelectIncomingMiniBlocks(t *testing.T) { return make(map[string]uint32) // empty }, GetNonceCalled: func() uint64 { - return 2 // same nonce + return 3 }, }, &testscommon.HeaderHandlerStub{ @@ -858,7 +858,7 @@ func TestShardProcessor_SelectIncomingMiniBlocks(t *testing.T) { } }, GetNonceCalled: func() uint64 { - return 2 // same nonce + return 4 // same nonce }, }, } @@ -866,8 +866,8 @@ func TestShardProcessor_SelectIncomingMiniBlocks(t *testing.T) { orderedMetaBlocksHashes = append(orderedMetaBlocksHashes, []byte("hash4")) _, err = sp.SelectIncomingMiniBlocks(providedLastCrossNotarizedMetaHdr, orderedMetaBlocks, orderedMetaBlocksHashes, haveTimeTrue) require.NoError(t, err) - // should be called three times, the third hdr returns shouldContinue false, but still added miniblocks, so meta block is referenced - require.Equal(t, 3, cntAddReferencedMetaBlockCalled) + // should be called for the first 2 meta blocks, the third one does not add any mini blocks, although it has some for the shard, so it is skipped + require.Equal(t, 2, cntAddReferencedMetaBlockCalled) }) } diff --git a/testscommon/mbSelection/mbSelectionSessionStub.go b/testscommon/mbSelection/mbSelectionSessionStub.go index 8ba5741351d..fd3ac8f0d6a 100644 --- a/testscommon/mbSelection/mbSelectionSessionStub.go +++ b/testscommon/mbSelection/mbSelectionSessionStub.go @@ -11,10 +11,10 @@ type MiniBlockSelectionSessionStub struct { GetMiniBlockHeaderHandlersCalled func() []data.MiniBlockHeaderHandler GetMiniBlocksCalled func() block.MiniBlockSlice GetMiniBlockHashesCalled func() [][]byte - AddReferencedMetaBlockCalled func(metaBlock data.HeaderHandler, metaBlockHash []byte) - GetReferencedMetaBlockHashesCalled func() [][]byte - GetReferencedMetaBlocksCalled func() []data.HeaderHandler - GetLastMetaBlockCalled func() data.HeaderHandler + AddReferencedHeaderCalled func(metaBlock data.HeaderHandler, metaBlockHash []byte) + GetReferencedHeaderHashesCalled func() [][]byte + GetReferencedHeadersCalled func() []data.HeaderHandler + GetLastHeaderCalled func() data.HeaderHandler GetGasProvidedCalled func() uint64 GetNumTxsAddedCalled func() uint32 AddMiniBlocksAndHashesCalled func(miniBlocksAndHashes []block.MiniblockAndHash) error @@ -52,33 +52,33 @@ func (mbss *MiniBlockSelectionSessionStub) GetMiniBlockHashes() [][]byte { return nil } -// AddReferencedMetaBlock - +// AddReferencedHeader - func (mbss *MiniBlockSelectionSessionStub) AddReferencedHeader(metaBlock data.HeaderHandler, metaBlockHash []byte) { - if mbss.AddReferencedMetaBlockCalled != nil { - mbss.AddReferencedMetaBlockCalled(metaBlock, metaBlockHash) + if mbss.AddReferencedHeaderCalled != nil { + mbss.AddReferencedHeaderCalled(metaBlock, metaBlockHash) } } -// GetReferencedMetaBlockHashes - +// GetReferencedHeaderHashes - func (mbss *MiniBlockSelectionSessionStub) GetReferencedHeaderHashes() [][]byte { - if mbss.GetReferencedMetaBlockHashesCalled != nil { - return mbss.GetReferencedMetaBlockHashesCalled() + if mbss.GetReferencedHeaderHashesCalled != nil { + return mbss.GetReferencedHeaderHashesCalled() } return nil } -// GetReferencedMetaBlocks - +// GetReferencedHeaders - func (mbss *MiniBlockSelectionSessionStub) GetReferencedHeaders() []data.HeaderHandler { - if mbss.GetReferencedMetaBlocksCalled != nil { - return mbss.GetReferencedMetaBlocksCalled() + if mbss.GetReferencedHeadersCalled != nil { + return mbss.GetReferencedHeadersCalled() } return nil } -// GetLastMetaBlock - +// GetLastHeader - func (mbss *MiniBlockSelectionSessionStub) GetLastHeader() data.HeaderHandler { - if mbss.GetLastMetaBlockCalled != nil { - return mbss.GetLastMetaBlockCalled() + if mbss.GetLastHeaderCalled != nil { + return mbss.GetLastHeaderCalled() } return nil } From bf4f9f4e0d523549fba698bb3ea268cba447cf69 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 22 Oct 2025 13:08:20 +0300 Subject: [PATCH 11/51] finalize create meta block proposal --- process/block/metablockProposal.go | 58 +++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index efe805602b8..e2c3f87951d 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -88,7 +88,6 @@ func (mp *metaProcessor) CreateBlockProposal( metaHdr.SoftwareVersion = []byte(mp.headerIntegrityVerifier.GetVersion(metaHdr.Epoch, metaHdr.Round)) - var body data.BodyHandler if metaHdr.IsStartOfEpochBlock() { // no new transactions in start of epoch block // to simplify bootstrapping @@ -103,13 +102,18 @@ func (mp *metaProcessor) CreateBlockProposal( } mbsToMe := mp.miniBlocksSelectionSession.GetMiniBlocks() + miniBlocksHeadersToMe := mp.miniBlocksSelectionSession.GetMiniBlockHeaderHandlers() numTxs := mp.miniBlocksSelectionSession.GetNumTxsAdded() referencedShardHeaderHashes := mp.miniBlocksSelectionSession.GetReferencedHeaderHashes() referencedShardHeaders := mp.miniBlocksSelectionSession.GetReferencedHeaders() + body := &block.Body{ + MiniBlocks: mbsToMe, + } + if len(mbsToMe) > 0 { - log.Debug("processed miniblocks and txs with destination in self shard", + log.Debug("created miniblocks with txs with destination in self shard", "num miniblocks", len(mbsToMe), - "num txs", numTxs, + "num txs proposed", numTxs, "num shard headers", len(referencedShardHeaderHashes), ) } @@ -118,15 +122,53 @@ func (mp *metaProcessor) CreateBlockProposal( go mp.checkAndRequestIfShardHeadersMissing() }() - mp.shardInfoCreateData.CreateShardInfoV3(metaHdr, referencedShardHeaders, referencedShardHeaderHashes) + // TODO: referenced shard headers should be also notarized, not only the headers corresponding to the execution results + // this will be needed for metachain to keep track of the already processed headers. + shardDataHandler, err := mp.shardInfoCreateData.CreateShardInfoV3(metaHdr, referencedShardHeaders, referencedShardHeaderHashes) + if err != nil { + return nil, nil, err + } + + err = metaHdr.SetShardInfoHandlers(shardDataHandler) + if err != nil { + return nil, nil, err + } + + err = metaHdr.SetMiniBlockHeaderHandlers(miniBlocksHeadersToMe) + if err != nil { + return nil, nil, err + } + + totalProcessedTxs := getTxCount(shardDataHandler) + getTxCountExecutionResults(metaHdr) + // TODO: consider if tx count per metablock header is still needed + // as we still have it in the execution results + err = metaHdr.SetTxCount(totalProcessedTxs) + if err != nil { + return nil, nil, err + } + + marshalizedBody, err := mp.marshalizer.Marshal(body) + if err != nil { + return nil, nil, err + } + mp.blockSizeThrottler.Add(metaHdr.GetRound(), uint32(len(marshalizedBody))) - // body, err = mp.applyBodyToHeader(metaHdr, body) - // if err != nil { - // return nil, nil, err - // } return metaHdr, body, nil } +func getTxCountExecutionResults(metaHeader data.MetaHeaderHandler) uint32 { + totalTxs := uint64(0) + execResults := metaHeader.GetExecutionResultsHandlers() + for _, execResult := range execResults { + execResultsMeta, ok := execResult.(data.MetaExecutionResultHandler) + if !ok { + continue + } + totalTxs += execResultsMeta.GetExecutedTxCount() + } + return uint32(totalTxs) +} + // VerifyBlockProposal will be implemented in a further PR func (mp *metaProcessor) VerifyBlockProposal( _ data.HeaderHandler, From dac8325204ff9753b83bce80cde348275a17c65f Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 22 Oct 2025 14:05:04 +0300 Subject: [PATCH 12/51] add todo --- process/block/metablockProposal.go | 1 + 1 file changed, 1 insertion(+) diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index e2c3f87951d..5050d262527 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -60,6 +60,7 @@ func (mp *metaProcessor) CreateNewHeaderProposal(round uint64, nonce uint64) (da return nil, process.ErrNilEpochStartData } + // TODO: clean up the epoch start data upon commit err = metaHeader.SetEpochStartHandler(mp.epochStartData) if err != nil { return nil, err From 02f2345dc894e3eae338886ecb3641d568f8633e Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 22 Oct 2025 16:52:38 +0300 Subject: [PATCH 13/51] add unit tests for metachain create new header proposal --- process/block/export_test.go | 5 + process/block/metablockProposal.go | 9 +- process/block/metablockProposal_test.go | 477 ++++++++++++++++++++++++ testscommon/headerHandlerStub.go | 16 +- 4 files changed, 500 insertions(+), 7 deletions(-) diff --git a/process/block/export_test.go b/process/block/export_test.go index 0a259808562..f33c3b12743 100644 --- a/process/block/export_test.go +++ b/process/block/export_test.go @@ -804,3 +804,8 @@ func (sp *shardProcessor) GetCrossShardIncomingMiniBlocksFromBody(body *block.Bo func GetHaveTimeForProposal(startTime time.Time, maxDuration time.Duration) func() time.Duration { return getHaveTimeForProposal(startTime, maxDuration) } + +// SetEpochStartData - +func (mp *metaProcessor) SetEpochStartData(epochStartData *block.EpochStart) { + mp.epochStartData = epochStartData +} diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 5050d262527..2fa6cf61ad1 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -15,6 +15,7 @@ import ( // CreateNewHeaderProposal creates a new header func (mp *metaProcessor) CreateNewHeaderProposal(round uint64, nonce uint64) (data.HeaderHandler, error) { + // TODO: the trigger would need to be changed upon commit of a block with the epoch start results epoch := mp.epochStartTrigger.Epoch() header := mp.versionedHeaderFactory.Create(epoch, round) @@ -65,7 +66,6 @@ func (mp *metaProcessor) CreateNewHeaderProposal(round uint64, nonce uint64) (da if err != nil { return nil, err } - // TODO: the trigger would need to be changed upon commit of a block with the epoch start results return metaHeader, nil } @@ -194,15 +194,18 @@ func (mp *metaProcessor) hasStartOfEpochExecutionResults(metaHeader data.MetaHea if err != nil { return false, err } - if hasRewardMiniBlocks(mbHeaders) { + if hasRewardOrPeerMiniBlocksFromSelf(mbHeaders) { return true, nil } } return false, nil } -func hasRewardMiniBlocks(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { +func hasRewardOrPeerMiniBlocksFromSelf(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { for _, mbHeader := range miniBlockHeaders { + if mbHeader.GetSenderShardID() != common.MetachainShardId { + continue + } if mbHeader.GetTypeInt32() == int32(block.RewardsBlock) || mbHeader.GetTypeInt32() == int32(block.PeerBlock) { return true diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index f3c38aa00fd..466280117cf 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -3,12 +3,489 @@ package block_test import ( "testing" + "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/process" blproc "github.com/multiversx/mx-chain-go/process/block" + "github.com/multiversx/mx-chain-go/process/mock" + "github.com/multiversx/mx-chain-go/testscommon" + "github.com/multiversx/mx-chain-go/testscommon/executionTrack" ) +func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { + t.Parallel() + + defaultBootstrapComponents := &mock.BootstrapComponentsMock{ + Coordinator: mock.NewOneShardCoordinatorMock(), + HdrIntegrityVerifier: &mock.HeaderIntegrityVerifierStub{}, + VersionedHdrFactory: &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &block.MetaBlock{} + }, + }, + } + + validMetaHeaderV3 := testscommon.HeaderHandlerStub{ + IsHeaderV3Called: func() bool { + return true + }, + } + + prevValidMetaBlockV3 := testscommon.HeaderHandlerStub{ + IsHeaderV3Called: func() bool { + return true + }, + GetLastExecutionResultHandlerCalled: func() data.LastExecutionResultHandler { + return &block.MetaExecutionResultInfo{} + }, + } + validMetaExecutionResultsWithEpochChange := []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{ + MiniBlockHeaders: []block.MiniBlockHeader{ + { + Hash: []byte("mb hash"), + SenderShardID: core.MetachainShardId, + Type: block.RewardsBlock, // this miniBlock marks the epoch start + }, + }, + }, + } + validMetaExecutionResultsWithoutEpochChange := []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{ + MiniBlockHeaders: []block.MiniBlockHeader{ + { + Hash: []byte("mb hash"), + ReceiverShardID: core.MetachainShardId, + SenderShardID: 0, + Type: block.TxBlock, + }, + }, + }, + } + + t.Run("versioned header factory creates an invalid meta header, should error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.EpochStartTrigger = &testscommon.EpochStartTriggerStub{ + EpochCalled: func() uint32 { + return 1 + }, + } + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &block.Header{} + }, + } + + arguments.BootstrapComponents = &bc + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, header) + require.Equal(t, process.ErrWrongTypeAssertion, err) + }) + t.Run("versioned header factory creates a metablock but with version < v3, should error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.EpochStartTrigger = &testscommon.EpochStartTriggerStub{ + EpochCalled: func() uint32 { + return 1 + }, + } + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &block.MetaBlock{} + }, + } + + arguments.BootstrapComponents = &bc + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, header) + require.Equal(t, process.ErrInvalidHeader, err) + }) + t.Run("correct meta header version, set round error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &testscommon.HeaderHandlerStub{ + IsHeaderV3Called: func() bool { + return true + }, + SetRoundCalled: func(_ uint64) error { + return expectedErr + }, + } + }, + } + + arguments.BootstrapComponents = &bc + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, header) + require.Equal(t, expectedErr, err) + }) + t.Run("correct meta header version, set nonce error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + + bc := *defaultBootstrapComponents + versionedHeader := validMetaHeaderV3 + versionedHeader.SetNonceCalled = func(_ uint64) error { + return expectedErr + } + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &versionedHeader + }, + } + + arguments.BootstrapComponents = &bc + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, header) + require.Equal(t, expectedErr, err) + }) + t.Run("correct meta header version, add execution result error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ExecutionResultsTracker = &executionTrack.ExecutionResultsTrackerStub{ + GetPendingExecutionResultsCalled: func() ([]data.BaseExecutionResultHandler, error) { + return nil, expectedErr + }, + } + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &validMetaHeaderV3 + }, + } + + arguments.BootstrapComponents = &bc + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, header) + require.Equal(t, expectedErr, err) + }) + t.Run("error checking epoch start data in execution results, should error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ExecutionResultsTracker = &executionTrack.ExecutionResultsTrackerStub{ + GetPendingExecutionResultsCalled: func() ([]data.BaseExecutionResultHandler, error) { + return nil, nil + }, + } + + metaBlockWithInvalidExecutionResult := validMetaHeaderV3 + metaBlockWithInvalidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.ExecutionResult{}, // invalid for meta block + } + } + + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &metaBlockWithInvalidExecutionResult + }, + } + + arguments.BootstrapComponents = &bc + dataComponentsModified := *dataComponents + dataComponentsModified.BlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &prevValidMetaBlockV3 + }, + GetCurrentBlockHeaderHashCalled: func() []byte { + return []byte("prev header hash") + }, + } + arguments.DataComponents = &dataComponentsModified + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, header) + require.Equal(t, process.ErrWrongTypeAssertion, err) + }) + t.Run("with epoch start data in execution results, but missing epoch start data in meta block processor", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ExecutionResultsTracker = &executionTrack.ExecutionResultsTrackerStub{ + GetPendingExecutionResultsCalled: func() ([]data.BaseExecutionResultHandler, error) { + return nil, nil + }, + } + + metaBlockWithValidExecutionResult := validMetaHeaderV3 + metaBlockWithValidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{ + MiniBlockHeaders: []block.MiniBlockHeader{ + { + Hash: []byte("mb hash"), + SenderShardID: core.MetachainShardId, + Type: block.RewardsBlock, // this miniBlock marks the epoch start + }, + }, + }, + } + } + + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &metaBlockWithValidExecutionResult + }, + } + + arguments.BootstrapComponents = &bc + dataComponentsModified := *dataComponents + dataComponentsModified.BlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &prevValidMetaBlockV3 + }, + GetCurrentBlockHeaderHashCalled: func() []byte { + return []byte("prev header hash") + }, + } + arguments.DataComponents = &dataComponentsModified + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Equal(t, process.ErrNilEpochStartData, err) + require.Nil(t, header) + }) + t.Run("with epoch start data in execution results and in meta block processor, error on set epoch", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ExecutionResultsTracker = &executionTrack.ExecutionResultsTrackerStub{ + GetPendingExecutionResultsCalled: func() ([]data.BaseExecutionResultHandler, error) { + return nil, nil + }, + } + + metaBlockWithValidExecutionResult := validMetaHeaderV3 + metaBlockWithValidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { + return validMetaExecutionResultsWithEpochChange + } + metaBlockWithValidExecutionResult.SetEpochCalled = func(epoch uint32) error { + require.Equal(t, uint32(1), epoch) + return expectedErr + } + + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &metaBlockWithValidExecutionResult + }, + } + + arguments.BootstrapComponents = &bc + dataComponentsModified := *dataComponents + dataComponentsModified.BlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &prevValidMetaBlockV3 + }, + GetCurrentBlockHeaderHashCalled: func() []byte { + return []byte("prev header hash") + }, + } + arguments.DataComponents = &dataComponentsModified + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + mp.SetEpochStartData(&block.EpochStart{ + LastFinalizedHeaders: make([]block.EpochStartShardData, 3), + Economics: block.Economics{}, + }) + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Equal(t, expectedErr, err) + require.Nil(t, header) + }) + t.Run("with epoch start data in execution results and in meta block processor, error on set epoch start data", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ExecutionResultsTracker = &executionTrack.ExecutionResultsTrackerStub{ + GetPendingExecutionResultsCalled: func() ([]data.BaseExecutionResultHandler, error) { + return nil, nil + }, + } + + metaBlockWithValidExecutionResult := validMetaHeaderV3 + metaBlockWithValidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { + return validMetaExecutionResultsWithEpochChange + } + metaBlockWithValidExecutionResult.SetEpochStartHandlerCalled = func(_ data.EpochStartHandler) error { + return expectedErr + } + + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &metaBlockWithValidExecutionResult + }, + } + + arguments.BootstrapComponents = &bc + dataComponentsModified := *dataComponents + dataComponentsModified.BlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &prevValidMetaBlockV3 + }, + GetCurrentBlockHeaderHashCalled: func() []byte { + return []byte("prev header hash") + }, + } + arguments.DataComponents = &dataComponentsModified + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + mp.SetEpochStartData(&block.EpochStart{ + LastFinalizedHeaders: make([]block.EpochStartShardData, 3), + Economics: block.Economics{}, + }) + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Equal(t, expectedErr, err) + require.Nil(t, header) + }) + t.Run("without epoch start data in execution results, should pass and not change epoch", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ExecutionResultsTracker = &executionTrack.ExecutionResultsTrackerStub{ + GetPendingExecutionResultsCalled: func() ([]data.BaseExecutionResultHandler, error) { + return nil, nil + }, + } + + metaBlockWithValidExecutionResult := validMetaHeaderV3 + metaBlockWithValidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { + return validMetaExecutionResultsWithoutEpochChange + } + metaBlockWithValidExecutionResult.SetEpochCalled = func(epoch uint32) error { + require.Fail(t, "should not have been called") + return nil + } + + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &metaBlockWithValidExecutionResult + }, + } + + arguments.BootstrapComponents = &bc + dataComponentsModified := *dataComponents + dataComponentsModified.BlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &prevValidMetaBlockV3 + }, + GetCurrentBlockHeaderHashCalled: func() []byte { + return []byte("prev header hash") + }, + } + arguments.DataComponents = &dataComponentsModified + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, err) + require.NotNil(t, header) + }) + t.Run("with epoch start data in execution results and in meta block processor, should pass and change epoch", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ExecutionResultsTracker = &executionTrack.ExecutionResultsTrackerStub{ + GetPendingExecutionResultsCalled: func() ([]data.BaseExecutionResultHandler, error) { + return nil, nil + }, + } + + metaBlockWithValidExecutionResult := validMetaHeaderV3 + metaBlockWithValidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { + return validMetaExecutionResultsWithEpochChange + } + metaBlockWithValidExecutionResult.SetEpochCalled = func(epoch uint32) error { + require.Equal(t, uint32(1), epoch) + return nil + } + + bc := *defaultBootstrapComponents + bc.VersionedHdrFactory = &testscommon.VersionedHeaderFactoryStub{ + CreateCalled: func(epoch uint32, _ uint64) data.HeaderHandler { + return &metaBlockWithValidExecutionResult + }, + } + + arguments.BootstrapComponents = &bc + dataComponentsModified := *dataComponents + dataComponentsModified.BlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &prevValidMetaBlockV3 + }, + GetCurrentBlockHeaderHashCalled: func() []byte { + return []byte("prev header hash") + }, + } + arguments.DataComponents = &dataComponentsModified + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + mp.SetEpochStartData(&block.EpochStart{ + LastFinalizedHeaders: make([]block.EpochStartShardData, 3), + Economics: block.Economics{}, + }) + header, err := mp.CreateNewHeaderProposal(1, 1) + require.Nil(t, err) + require.NotNil(t, header) + }) +} + func TestMetaProcessor_VerifyBlockProposal(t *testing.T) { t.Parallel() diff --git a/testscommon/headerHandlerStub.go b/testscommon/headerHandlerStub.go index 1a9cad48639..5bb25c92ae3 100644 --- a/testscommon/headerHandlerStub.go +++ b/testscommon/headerHandlerStub.go @@ -68,6 +68,8 @@ type HeaderHandlerStub struct { SetTxCountCalled func(count uint32) error SetMetaBlockHashesCalled func(hashes [][]byte) error SetEpochStartHandlerCalled func(epochStartHandler data.EpochStartHandler) error + SetRoundCalled func(round uint64) error + SetNonceCalled func(nonce uint64) error } // SetEpochStartHandler - @@ -241,8 +243,11 @@ func (hhs *HeaderHandlerStub) GetReserved() []byte { } // SetNonce - -func (hhs *HeaderHandlerStub) SetNonce(_ uint64) error { - panic("implement me") +func (hhs *HeaderHandlerStub) SetNonce(nonce uint64) error { + if hhs.SetNonceCalled != nil { + return hhs.SetNonceCalled(nonce) + } + return nil } // SetEpoch - @@ -254,8 +259,11 @@ func (hhs *HeaderHandlerStub) SetEpoch(epoch uint32) error { } // SetRound - -func (hhs *HeaderHandlerStub) SetRound(_ uint64) error { - panic("implement me") +func (hhs *HeaderHandlerStub) SetRound(round uint64) error { + if hhs.SetRoundCalled != nil { + return hhs.SetRoundCalled(round) + } + return nil } // SetTimeStamp - From f85d11c9819fa00c53b012029d58ebdeae18eb15 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 22 Oct 2025 18:37:19 +0300 Subject: [PATCH 14/51] more unit tests and fixes --- process/block/metablock.go | 4 +- process/block/metablockProposal.go | 49 +++++--- process/block/metablockProposal_test.go | 114 ++++++++++++++++++ process/block/shardblockProposal_test.go | 6 +- process/errors.go | 3 + process/interface.go | 1 + process/mock/blockTrackerMock.go | 5 + testscommon/headerHandlerStub.go | 8 +- .../processMocks/shardInfoCreatorMock.go | 40 ++++++ 9 files changed, 205 insertions(+), 25 deletions(-) create mode 100644 testscommon/processMocks/shardInfoCreatorMock.go diff --git a/process/block/metablock.go b/process/block/metablock.go index 54ea01b81f8..11e13c2680b 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -92,7 +92,9 @@ func NewMetaProcessor(arguments ArgMetaProcessor) (*metaProcessor, error) { if check.IfNil(arguments.ReceiptsRepository) { return nil, process.ErrNilReceiptsRepository } - + if check.IfNil(arguments.ShardInfoCreator) { + return nil, process.ErrNilShardInfoCreator + } mp := metaProcessor{ baseProcessor: base, headersCounter: NewHeaderCounter(), diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 2fa6cf61ad1..8f1bece9a41 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -89,7 +89,7 @@ func (mp *metaProcessor) CreateBlockProposal( metaHdr.SoftwareVersion = []byte(mp.headerIntegrityVerifier.GetVersion(metaHdr.Epoch, metaHdr.Round)) - if metaHdr.IsStartOfEpochBlock() { + if metaHdr.IsStartOfEpochBlock() || metaHdr.GetEpochChangeProposed() { // no new transactions in start of epoch block // to simplify bootstrapping return metaHdr, &block.Body{}, nil @@ -303,38 +303,44 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( break } - currShardHdr := orderedHdrs[i] - if currShardHdr.GetNonce() > lastShardHdr[currShardHdr.GetShardID()].Header.GetNonce()+1 { + currHdr := orderedHdrs[i] + currHdrHash := orderedHdrsHashes[i] + if currHdr.GetNonce() > lastShardHdr[currHdr.GetShardID()].Header.GetNonce()+1 { log.Trace("skip searching", - "shard", currShardHdr.GetShardID(), - "last shard hdr nonce", lastShardHdr[currShardHdr.GetShardID()].Header.GetNonce(), - "curr shard hdr nonce", currShardHdr.GetNonce()) + "shard", currHdr.GetShardID(), + "last shard hdr nonce", lastShardHdr[currHdr.GetShardID()].Header.GetNonce(), + "curr shard hdr nonce", currHdr.GetNonce()) continue } - if hdrsAddedForShard[currShardHdr.GetShardID()] >= maxShardHeadersFromSameShard { + if hdrsAddedForShard[currHdr.GetShardID()] >= maxShardHeadersFromSameShard { log.Trace("maximum shard headers from same shard allowed to be included in one meta block has been reached", - "shard", currShardHdr.GetShardID(), - "shard headers added", hdrsAddedForShard[currShardHdr.GetShardID()], + "shard", currHdr.GetShardID(), + "shard headers added", hdrsAddedForShard[currHdr.GetShardID()], ) continue } - hasProofForHdr := mp.proofsPool.HasProof(currShardHdr.GetShardID(), orderedHdrsHashes[i]) + hasProofForHdr := mp.proofsPool.HasProof(currHdr.GetShardID(), currHdrHash) if !hasProofForHdr { log.Trace("no proof for shard header", - "shard", currShardHdr.GetShardID(), - "hash", logger.DisplayByteSlice(orderedHdrsHashes[i]), + "shard", currHdr.GetShardID(), + "hash", logger.DisplayByteSlice(currHdrHash), ) continue } - if len(currShardHdr.GetMiniBlockHeadersWithDst(mp.shardCoordinator.SelfId())) == 0 { - mp.miniBlocksSelectionSession.AddReferencedHeader(orderedHdrs[i], orderedHdrsHashes[i]) + if len(currHdr.GetMiniBlockHeadersWithDst(mp.shardCoordinator.SelfId())) == 0 { + mp.miniBlocksSelectionSession.AddReferencedHeader(currHdr, currHdrHash) + lastShardHdr[currHdr.GetShardID()] = ShardHeaderInfo{ + Header: currHdr, + Hash: currHdrHash, + UsedInBlock: true, + } continue } - _, pendingMiniBlocks, errCreated := mp.createMbsCrossShardDstMe(orderedHdrsHashes[i], currShardHdr, nil, true) + _, pendingMiniBlocks, errCreated := mp.createMbsCrossShardDstMe(currHdrHash, currHdr, nil, true) if errCreated != nil { return errCreated } @@ -342,13 +348,18 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( // pending miniBlocks were already reverted, but still returned to check if we need to stop adding more shard headers if len(pendingMiniBlocks) > 0 { log.Debug("shard header cannot be fully added", - "round", currShardHdr.GetRound(), - "nonce", currShardHdr.GetNonce(), - "hash", orderedHdrsHashes[i]) + "round", currHdr.GetRound(), + "nonce", currHdr.GetNonce(), + "hash", currHdrHash) break } - mp.miniBlocksSelectionSession.AddReferencedHeader(currShardHdr, orderedHdrsHashes[i]) + mp.miniBlocksSelectionSession.AddReferencedHeader(currHdr, orderedHdrsHashes[i]) + lastShardHdr[currHdr.GetShardID()] = ShardHeaderInfo{ + Header: currHdr, + Hash: currHdrHash, + UsedInBlock: true, + } } return nil diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index 466280117cf..5861de0cf25 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -13,6 +13,8 @@ import ( "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/executionTrack" + "github.com/multiversx/mx-chain-go/testscommon/mbSelection" + "github.com/multiversx/mx-chain-go/testscommon/processMocks" ) func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { @@ -486,6 +488,118 @@ func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { }) } +func TestMetaProcessor_CreateBlockProposal(t *testing.T) { + t.Parallel() + + t.Run("nil header", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + checkCreateBlockProposalResult(t, mp, nil, haveTimeTrue, process.ErrNilBlockHeader) + }) + t.Run("not header v3", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + notV3Header := &block.MetaBlock{} + checkCreateBlockProposalResult(t, mp, notV3Header, haveTimeTrue, process.ErrInvalidHeader) + }) + t.Run("shard header v3", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + shardHeaderV3 := &block.HeaderV3{} + checkCreateBlockProposalResult(t, mp, shardHeaderV3, haveTimeTrue, process.ErrWrongTypeAssertion) + }) + t.Run("createBlockBodyProposal error (ComputeLongestShardsChainsFromLastNotarized error)", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.BlockTracker = &mock.BlockTrackerMock{ + ComputeLongestShardsChainsFromLastNotarizedCalled: func() ([]data.HeaderHandler, [][]byte, map[uint32][]data.HeaderHandler, error) { + return nil, nil, nil, expectedErr + }, + } + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + checkCreateBlockProposalResult(t, mp, validMetaHeaderV3, haveTimeTrue, expectedErr) + }) + t.Run("createShardInfoV3 error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ShardInfoCreator = &processMocks.ShardInfoCreatorMock{ + CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) { + return nil, expectedErr + }, + } + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + checkCreateBlockProposalResult(t, mp, validMetaHeaderV3, haveTimeTrue, expectedErr) + }) + t.Run("set shard info error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + GetMiniBlocksCalled: func() block.MiniBlockSlice { + return make([]*block.MiniBlock, 5) // coverage + }, + } + var invalidShardData data.ShardDataHandler + arguments.ShardInfoCreator = &processMocks.ShardInfoCreatorMock{ + CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) { + return []data.ShardDataHandler{invalidShardData}, nil + }, + } + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + checkCreateBlockProposalResult(t, mp, validMetaHeaderV3, haveTimeTrue, data.ErrInvalidTypeAssertion) + }) + t.Run("set mini block header handlers error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + var invalidMiniBlockHeader data.MiniBlockHeaderHandler + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + GetMiniBlockHeaderHandlersCalled: func() []data.MiniBlockHeaderHandler { + return []data.MiniBlockHeaderHandler{invalidMiniBlockHeader} + }, + } + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + checkCreateBlockProposalResult(t, mp, validMetaHeaderV3, haveTimeTrue, data.ErrInvalidTypeAssertion) + }) +} + func TestMetaProcessor_VerifyBlockProposal(t *testing.T) { t.Parallel() diff --git a/process/block/shardblockProposal_test.go b/process/block/shardblockProposal_test.go index 338c4cabffe..168830b24db 100644 --- a/process/block/shardblockProposal_test.go +++ b/process/block/shardblockProposal_test.go @@ -56,7 +56,7 @@ func haveTimeFalse() bool { return false } -type shardProcessorTest interface { +type processorTest interface { CreateBlockProposal( initialHdr data.HeaderHandler, haveTime func() bool, @@ -1406,12 +1406,12 @@ func TestShardProcessor_CheckMetaHeadersValidityAndFinalityProposal(t *testing.T func checkCreateBlockProposalResult( t *testing.T, - sp shardProcessorTest, + processor processorTest, header data.HeaderHandler, haveTime func() bool, expectedError error, ) { - hdr, body, err := sp.CreateBlockProposal(header, haveTime) + hdr, body, err := processor.CreateBlockProposal(header, haveTime) require.Equal(t, expectedError, err) require.Nil(t, hdr) require.Nil(t, body) diff --git a/process/errors.go b/process/errors.go index ff1afffee01..42f6068ee37 100644 --- a/process/errors.go +++ b/process/errors.go @@ -1412,3 +1412,6 @@ var ErrNilEpochStartData = errors.New("nil epoch start data") // ErrInconsistentShardHeadersAndHashes signals that shard headers are inconsistent with their hashes var ErrInconsistentShardHeadersAndHashes = errors.New("inconsistent shard headers and hashes") + +// ErrNilShardInfoCreator signals that a nil shard info creator has been provided +var ErrNilShardInfoCreator = errors.New("nil shard info creator") diff --git a/process/interface.go b/process/interface.go index 430d09a486e..65ba5efbc4b 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1582,4 +1582,5 @@ type InclusionEstimator interface { type ShardInfoCreator interface { CreateShardInfoV3(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) CreateShardInfoFromLegacyMeta(metaHeader data.MetaHeaderHandler, shardHeaders []data.ShardHeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) + IsInterfaceNil() bool } diff --git a/process/mock/blockTrackerMock.go b/process/mock/blockTrackerMock.go index 5c6d425c363..5fcf2d9e135 100644 --- a/process/mock/blockTrackerMock.go +++ b/process/mock/blockTrackerMock.go @@ -9,6 +9,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/track" "github.com/multiversx/mx-chain-go/sharding" @@ -244,6 +245,10 @@ func (btm *BlockTrackerMock) ComputeLongestMetaChainFromLastNotarized() ([]data. // ComputeLongestShardsChainsFromLastNotarized - func (btm *BlockTrackerMock) ComputeLongestShardsChainsFromLastNotarized() ([]data.HeaderHandler, [][]byte, map[uint32][]data.HeaderHandler, error) { + if btm.ComputeLongestShardsChainsFromLastNotarizedCalled != nil { + return btm.ComputeLongestShardsChainsFromLastNotarizedCalled() + } + hdrsMap := make(map[uint32][]data.HeaderHandler) hdrsHashesMap := make(map[uint32][][]byte) diff --git a/testscommon/headerHandlerStub.go b/testscommon/headerHandlerStub.go index 5bb25c92ae3..e230d925b17 100644 --- a/testscommon/headerHandlerStub.go +++ b/testscommon/headerHandlerStub.go @@ -70,6 +70,7 @@ type HeaderHandlerStub struct { SetEpochStartHandlerCalled func(epochStartHandler data.EpochStartHandler) error SetRoundCalled func(round uint64) error SetNonceCalled func(nonce uint64) error + SetShardInfoHandlersCalled func(shardInfo []data.ShardDataHandler) error } // SetEpochStartHandler - @@ -459,8 +460,11 @@ func (hhs *HeaderHandlerStub) SetDevFeesInEpoch(_ *big.Int) error { } // SetShardInfoHandlers - -func (hhs *HeaderHandlerStub) SetShardInfoHandlers(_ []data.ShardDataHandler) error { - panic("implement me") +func (hhs *HeaderHandlerStub) SetShardInfoHandlers(shardInfo []data.ShardDataHandler) error { + if hhs.SetShardInfoHandlersCalled != nil { + return hhs.SetShardInfoHandlersCalled(shardInfo) + } + return nil } // SetAccumulatedFeesInEpoch - diff --git a/testscommon/processMocks/shardInfoCreatorMock.go b/testscommon/processMocks/shardInfoCreatorMock.go new file mode 100644 index 00000000000..439424abe50 --- /dev/null +++ b/testscommon/processMocks/shardInfoCreatorMock.go @@ -0,0 +1,40 @@ +package processMocks + +import ( + "github.com/multiversx/mx-chain-core-go/data" +) + +// ShardInfoCreatorMock is a mock implementation of ShardInfoCreator interface +type ShardInfoCreatorMock struct { + CreateShardInfoV3Called func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) + CreateShardInfoFromLegacyMetaCalled func(metaHeader data.MetaHeaderHandler, shardHeaders []data.ShardHeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) +} + +// CreateShardInfoV3 - +func (scm *ShardInfoCreatorMock) CreateShardInfoV3( + metaHeader data.MetaHeaderHandler, + shardHeaders []data.HeaderHandler, + shardHeaderHashes [][]byte, +) ([]data.ShardDataHandler, error) { + if scm.CreateShardInfoV3Called != nil { + return scm.CreateShardInfoV3Called(metaHeader, shardHeaders, shardHeaderHashes) + } + return nil, nil +} + +// CreateShardInfoFromLegacyMeta - +func (scm *ShardInfoCreatorMock) CreateShardInfoFromLegacyMeta( + metaHeader data.MetaHeaderHandler, + shardHeaders []data.ShardHeaderHandler, + shardHeaderHashes [][]byte, +) ([]data.ShardDataHandler, error) { + if scm.CreateShardInfoFromLegacyMetaCalled != nil { + return scm.CreateShardInfoFromLegacyMetaCalled(metaHeader, shardHeaders, shardHeaderHashes) + } + return nil, nil +} + +// IsInterfaceNil - +func (scm *ShardInfoCreatorMock) IsInterfaceNil() bool { + return scm == nil +} From a3c97ac39c330ab1e00b0cc6732eb5e32662e51b Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Thu, 23 Oct 2025 16:26:02 +0300 Subject: [PATCH 15/51] unit tests and fixes --- process/block/export_test.go | 15 ++ process/block/metablockProposal.go | 24 +- process/block/metablockProposal_test.go | 315 ++++++++++++++++++++++++ 3 files changed, 348 insertions(+), 6 deletions(-) diff --git a/process/block/export_test.go b/process/block/export_test.go index f33c3b12743..af12565fa0f 100644 --- a/process/block/export_test.go +++ b/process/block/export_test.go @@ -809,3 +809,18 @@ func GetHaveTimeForProposal(startTime time.Time, maxDuration time.Duration) func func (mp *metaProcessor) SetEpochStartData(epochStartData *block.EpochStart) { mp.epochStartData = epochStartData } + +// GetTxCountExecutionResults - +func GetTxCountExecutionResults(metaHeader data.MetaHeaderHandler) (uint32, error) { + return getTxCountExecutionResults(metaHeader) +} + +// HasStartOfEpochExecutionResults - +func (mp *metaProcessor) HasStartOfEpochExecutionResults(metaHeader data.MetaHeaderHandler) (bool, error) { + return mp.hasStartOfEpochExecutionResults(metaHeader) +} + +// HasRewardOrPeerMiniBlocksFromMeta - +func HasRewardOrPeerMiniBlocksFromMeta(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { + return hasRewardOrPeerMiniBlocksFromMeta(miniBlockHeaders) +} diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 8f1bece9a41..52f548e4d0b 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -140,7 +140,12 @@ func (mp *metaProcessor) CreateBlockProposal( return nil, nil, err } - totalProcessedTxs := getTxCount(shardDataHandler) + getTxCountExecutionResults(metaHdr) + txsInExecutionResults, err := getTxCountExecutionResults(metaHdr) + if err != nil { + return nil, nil, err + } + + totalProcessedTxs := getTxCount(shardDataHandler) + txsInExecutionResults // TODO: consider if tx count per metablock header is still needed // as we still have it in the execution results err = metaHdr.SetTxCount(totalProcessedTxs) @@ -157,17 +162,21 @@ func (mp *metaProcessor) CreateBlockProposal( return metaHdr, body, nil } -func getTxCountExecutionResults(metaHeader data.MetaHeaderHandler) uint32 { +func getTxCountExecutionResults(metaHeader data.MetaHeaderHandler) (uint32, error) { + if check.IfNil(metaHeader) { + return 0, nil + } + totalTxs := uint64(0) execResults := metaHeader.GetExecutionResultsHandlers() for _, execResult := range execResults { execResultsMeta, ok := execResult.(data.MetaExecutionResultHandler) if !ok { - continue + return 0, process.ErrWrongTypeAssertion } totalTxs += execResultsMeta.GetExecutedTxCount() } - return uint32(totalTxs) + return uint32(totalTxs), nil } // VerifyBlockProposal will be implemented in a further PR @@ -188,20 +197,23 @@ func (mp *metaProcessor) ProcessBlockProposal( } func (mp *metaProcessor) hasStartOfEpochExecutionResults(metaHeader data.MetaHeaderHandler) (bool, error) { + if check.IfNil(metaHeader) { + return false, process.ErrNilHeaderHandler + } execResults := metaHeader.GetExecutionResultsHandlers() for _, execResult := range execResults { mbHeaders, err := mp.extractMiniBlocksHeaderHandlersFromExecResult(execResult, common.MetachainShardId) if err != nil { return false, err } - if hasRewardOrPeerMiniBlocksFromSelf(mbHeaders) { + if hasRewardOrPeerMiniBlocksFromMeta(mbHeaders) { return true, nil } } return false, nil } -func hasRewardOrPeerMiniBlocksFromSelf(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { +func hasRewardOrPeerMiniBlocksFromMeta(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { for _, mbHeader := range miniBlockHeaders { if mbHeader.GetSenderShardID() != common.MetachainShardId { continue diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index 5861de0cf25..08f79c98667 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -598,6 +598,105 @@ func TestMetaProcessor_CreateBlockProposal(t *testing.T) { validMetaHeaderV3 := &block.MetaBlockV3{} checkCreateBlockProposalResult(t, mp, validMetaHeaderV3, haveTimeTrue, data.ErrInvalidTypeAssertion) }) + t.Run("marshall error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + GetMiniBlockHeaderHandlersCalled: func() []data.MiniBlockHeaderHandler { return nil }, + } + cc := coreComponents + cc.IntMarsh = &testscommon.MarshallerStub{ + MarshalCalled: func(obj interface{}) ([]byte, error) { + return nil, expectedErr + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + checkCreateBlockProposalResult(t, mp, validMetaHeaderV3, haveTimeTrue, expectedErr) + }) + t.Run("successful creation, non start of epoch block", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + GetMiniBlockHeaderHandlersCalled: func() []data.MiniBlockHeaderHandler { return nil }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + header, body, err := mp.CreateBlockProposal(validMetaHeaderV3, haveTimeTrue) + require.Nil(t, err) + require.NotNil(t, header) + require.NotNil(t, body) + }) + t.Run("successful creation, start of epoch block with empy body", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + GetMiniBlockHeaderHandlersCalled: func() []data.MiniBlockHeaderHandler { return nil }, + } + arguments.GasComputation = &testscommon.GasComputationMock{ + ResetCalled: func() { + require.Fail(t, "should not be called") + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + // add epoch start data to the meta processor so that IsEpochStartBlock returns true + validMetaHeaderV3 := &block.MetaBlockV3{ + EpochStart: block.EpochStart{ + LastFinalizedHeaders: make([]block.EpochStartShardData, 3), + }, + } + header, body, err := mp.CreateBlockProposal(validMetaHeaderV3, haveTimeTrue) + require.Nil(t, err) + require.NotNil(t, header) + require.NotNil(t, body) + b := body.(*block.Body) + // start of epoch block should have no mini blocks headers and no mini blocks in the body + require.Len(t, header.GetMiniBlockHeaderHandlers(), 0) + require.Len(t, b.MiniBlocks, 0) + }) + t.Run("successful creation, epoch change proposal block with empy body", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + GetMiniBlockHeaderHandlersCalled: func() []data.MiniBlockHeaderHandler { return nil }, + } + arguments.GasComputation = &testscommon.GasComputationMock{ + ResetCalled: func() { + require.Fail(t, "should not be called") + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + // add epoch start data to the meta processor so that IsEpochStartBlock returns true + validMetaHeaderV3 := &block.MetaBlockV3{ + EpochStart: block.EpochStart{ + LastFinalizedHeaders: make([]block.EpochStartShardData, 3), + }, + } + header, body, err := mp.CreateBlockProposal(validMetaHeaderV3, haveTimeTrue) + require.Nil(t, err) + require.NotNil(t, header) + require.NotNil(t, body) + b := body.(*block.Body) + // epoch change proposal should have no mini blocks headers and no mini blocks in the body + require.Len(t, header.GetMiniBlockHeaderHandlers(), 0) + require.Len(t, b.MiniBlocks, 0) + }) } func TestMetaProcessor_VerifyBlockProposal(t *testing.T) { @@ -617,3 +716,219 @@ func TestMetaProcessor_VerifyBlockProposal(t *testing.T) { err = mp.VerifyBlockProposal(header, body, haveTime) require.NoError(t, err) } + +func Test_getTxCountExecutionResults(t *testing.T) { + t.Parallel() + + t.Run("nil meta block", func(t *testing.T) { + t.Parallel() + + txCount, err := blproc.GetTxCountExecutionResults(nil) + require.Nil(t, err) + require.Equal(t, uint32(0), txCount) + }) + t.Run("no execution results notarized", func(t *testing.T) { + t.Parallel() + + metaBlock := &block.MetaBlockV3{} + txCount, err := blproc.GetTxCountExecutionResults(metaBlock) + require.Nil(t, err) + require.Equal(t, uint32(0), txCount) + }) + t.Run("empty execution results notarized", func(t *testing.T) { + t.Parallel() + + metaBlock := &block.MetaBlockV3{ + ExecutionResults: []*block.MetaExecutionResult{{}, {}}, + } + txCount, err := blproc.GetTxCountExecutionResults(metaBlock) + require.Nil(t, err) + require.Equal(t, uint32(0), txCount) + }) + t.Run("invalid execution result in notarized list", func(t *testing.T) { + t.Parallel() + + var metaExecutionResult *block.BaseExecutionResult + metaBlock := &testscommon.HeaderHandlerStub{ + GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + metaExecutionResult, + } + }, + } + + txCount, err := blproc.GetTxCountExecutionResults(metaBlock) + require.Equal(t, process.ErrWrongTypeAssertion, err) + require.Equal(t, uint32(0), txCount) + }) + t.Run("execution results notarized", func(t *testing.T) { + t.Parallel() + + metaBlock := &block.MetaBlockV3{ + ExecutionResults: []*block.MetaExecutionResult{ + { + ExecutedTxCount: 5, + }, + { + ExecutedTxCount: 10, + }, + }, + } + txCount, err := blproc.GetTxCountExecutionResults(metaBlock) + require.Nil(t, err) + require.Equal(t, uint32(15), txCount) + }) +} + +func TestMetaProcessor_hasStartOfEpochExecutionResults(t *testing.T) { + t.Parallel() + + mbHeaderWithEpochStartData := block.MiniBlockHeader{ + Hash: []byte("mb hash"), + SenderShardID: core.MetachainShardId, + Type: block.RewardsBlock, + } + t.Run("nil meta block", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(nil) + require.Equal(t, process.ErrNilHeaderHandler, err) + require.False(t, hasEpochStartData) + }) + t.Run("no executionResults", func(t *testing.T) { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(validMetaHeaderV3) + require.Nil(t, err) + require.False(t, hasEpochStartData) + }) + t.Run("executionResults with invalid data", func(t *testing.T) { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &testscommon.HeaderHandlerStub{ + GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.ExecutionResult{}, + } + }, + } + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(validMetaHeaderV3) + require.Equal(t, process.ErrWrongTypeAssertion, err) + require.False(t, hasEpochStartData) + }) + t.Run("executionResults without epoch start data", func(t *testing.T) { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + mbHeader := mbHeaderWithEpochStartData + mbHeader.Type = block.TxBlock + validMetaHeaderV3 := &testscommon.HeaderHandlerStub{ + GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{MiniBlockHeaders: []block.MiniBlockHeader{mbHeader}}} + }, + } + + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(validMetaHeaderV3) + require.Nil(t, err) + require.False(t, hasEpochStartData) + }) + t.Run("executionResults with reward miniBlocks epoch start data not from meta", func(t *testing.T) { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + mbHeader := mbHeaderWithEpochStartData + mbHeader.SenderShardID = 0 + validMetaHeaderV3 := &testscommon.HeaderHandlerStub{ + GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{MiniBlockHeaders: []block.MiniBlockHeader{mbHeader}}} + }, + } + + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(validMetaHeaderV3) + require.Nil(t, err) + require.False(t, hasEpochStartData) + }) + t.Run("executionResults with peer miniBlocks epoch start data not from meta", func(t *testing.T) { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + mbHeader := mbHeaderWithEpochStartData + mbHeader.SenderShardID = 0 + mbHeader.Type = block.PeerBlock + validMetaHeaderV3 := &testscommon.HeaderHandlerStub{ + GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{MiniBlockHeaders: []block.MiniBlockHeader{mbHeader}}} + }, + } + + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(validMetaHeaderV3) + require.Nil(t, err) + require.False(t, hasEpochStartData) + }) + t.Run("executionResults with reward miniBlocks epoch start data from meta", func(t *testing.T) { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + mbHeader := mbHeaderWithEpochStartData + mbHeader.Type = block.RewardsBlock + validMetaHeaderV3 := &testscommon.HeaderHandlerStub{ + GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{MiniBlockHeaders: []block.MiniBlockHeader{mbHeader}}} + }, + } + + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(validMetaHeaderV3) + require.Nil(t, err) + require.True(t, hasEpochStartData) + }) + t.Run("executionResults with peer miniBlocks epoch start data from meta", func(t *testing.T) { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + mbHeader := mbHeaderWithEpochStartData + mbHeader.Type = block.PeerBlock + validMetaHeaderV3 := &testscommon.HeaderHandlerStub{ + GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { + return []data.BaseExecutionResultHandler{ + &block.MetaExecutionResult{MiniBlockHeaders: []block.MiniBlockHeader{mbHeader}}} + }, + } + + hasEpochStartData, err := mp.HasStartOfEpochExecutionResults(validMetaHeaderV3) + require.Nil(t, err) + require.True(t, hasEpochStartData) + }) +} + +func Test_hasRewardOrPeerMiniBlocksFromSelf(t *testing.T) { + t.Parallel() + + t.Run("nil miniBlocks", func(t *testing.T) { + // t.Parallel() + // miniBlockHeaders := []data.MiniBlockHeaderHandler{nil} + // has, err := blproc.HasRewardOrPeerMiniBlocksFromMeta(miniBlockHeaders) + }) +} From d98b17a23a89aacc021c403883ff5091d3826389 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Thu, 23 Oct 2025 16:33:43 +0300 Subject: [PATCH 16/51] unit tests --- process/block/metablockProposal_test.go | 56 +++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index 08f79c98667..2638cdf5bf6 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -8,6 +8,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data/block" "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" blproc "github.com/multiversx/mx-chain-go/process/block" "github.com/multiversx/mx-chain-go/process/mock" @@ -927,8 +928,57 @@ func Test_hasRewardOrPeerMiniBlocksFromSelf(t *testing.T) { t.Parallel() t.Run("nil miniBlocks", func(t *testing.T) { - // t.Parallel() - // miniBlockHeaders := []data.MiniBlockHeaderHandler{nil} - // has, err := blproc.HasRewardOrPeerMiniBlocksFromMeta(miniBlockHeaders) + t.Parallel() + response := blproc.HasRewardOrPeerMiniBlocksFromMeta(nil) + require.False(t, response) + }) + t.Run("no miniBlocks", func(t *testing.T) { + t.Parallel() + response := blproc.HasRewardOrPeerMiniBlocksFromMeta([]data.MiniBlockHeaderHandler{}) + require.False(t, response) + }) + t.Run("with reward miniBlocks from different shard", func(t *testing.T) { + t.Parallel() + miniBlocks := []data.MiniBlockHeaderHandler{ + &block.MiniBlockHeader{ + SenderShardID: 1, + Type: block.RewardsBlock, + }, + } + response := blproc.HasRewardOrPeerMiniBlocksFromMeta(miniBlocks) + require.False(t, response) + }) + t.Run("only tx miniBlocks", func(t *testing.T) { + t.Parallel() + miniBlocks := []data.MiniBlockHeaderHandler{ + &block.MiniBlockHeader{ + SenderShardID: common.MetachainShardId, // although not possible in combination with txblock + Type: block.TxBlock, + }, + } + response := blproc.HasRewardOrPeerMiniBlocksFromMeta(miniBlocks) + require.False(t, response) + }) + t.Run("with reward miniBlocks from meta shard", func(t *testing.T) { + t.Parallel() + miniBlocks := []data.MiniBlockHeaderHandler{ + &block.MiniBlockHeader{ + SenderShardID: common.MetachainShardId, + Type: block.RewardsBlock, + }, + } + response := blproc.HasRewardOrPeerMiniBlocksFromMeta(miniBlocks) + require.True(t, response) + }) + t.Run("with peer miniBlocks from meta shard", func(t *testing.T) { + t.Parallel() + miniBlocks := []data.MiniBlockHeaderHandler{ + &block.MiniBlockHeader{ + SenderShardID: common.MetachainShardId, + Type: block.PeerBlock, + }, + } + response := blproc.HasRewardOrPeerMiniBlocksFromMeta(miniBlocks) + require.True(t, response) }) } From aa6194dbc326bfbccf4d84749a33fe0ff444fbd8 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Thu, 23 Oct 2025 18:43:38 +0300 Subject: [PATCH 17/51] unit tests and fixes --- process/block/export_test.go | 23 ++++ process/block/metablockProposal.go | 17 ++- process/block/metablockProposal_test.go | 174 ++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 6 deletions(-) diff --git a/process/block/export_test.go b/process/block/export_test.go index af12565fa0f..99638ce06c8 100644 --- a/process/block/export_test.go +++ b/process/block/export_test.go @@ -824,3 +824,26 @@ func (mp *metaProcessor) HasStartOfEpochExecutionResults(metaHeader data.MetaHea func HasRewardOrPeerMiniBlocksFromMeta(miniBlockHeaders []data.MiniBlockHeaderHandler) bool { return hasRewardOrPeerMiniBlocksFromMeta(miniBlockHeaders) } + +// CreateProposalMiniBlocks - +func (mp *metaProcessor) CreateProposalMiniBlocks(haveTime func() bool) error { + return mp.createProposalMiniBlocks(haveTime) +} + +// SelectIncomingMiniBlocksForProposal - +func (mp *metaProcessor) SelectIncomingMiniBlocksForProposal( + haveTime func() bool, +) error { + return mp.selectIncomingMiniBlocksForProposal(haveTime) +} + +// SelectIncomingMiniBlocks - +func (mp *metaProcessor) SelectIncomingMiniBlocks( + lastShardHdr map[uint32]ShardHeaderInfo, + orderedHdrs []data.HeaderHandler, + orderedHdrsHashes [][]byte, + maxNumHeadersFromSameShard uint32, + haveTime func() bool, +) error { + return mp.selectIncomingMiniBlocks(lastShardHdr, orderedHdrs, orderedHdrsHashes, maxNumHeadersFromSameShard, haveTime) +} diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 52f548e4d0b..3c9f84c5b63 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -279,7 +279,11 @@ func (mp *metaProcessor) selectIncomingMiniBlocksForProposal( return err } - err = mp.selectIncomingMiniBlocks(lastShardHdr, orderedHdrs, orderedHdrsHashes, haveTime) + maxShardHeadersFromSameShard := core.MaxUint32( + process.MinShardHeadersFromSameShardInOneMetaBlock, + process.MaxShardHeadersAllowedInOneMetaBlock/mp.shardCoordinator.NumberOfShards(), + ) + err = mp.selectIncomingMiniBlocks(lastShardHdr, orderedHdrs, orderedHdrsHashes, maxShardHeadersFromSameShard, haveTime) if err != nil { return err } @@ -291,13 +295,10 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( lastShardHdr map[uint32]ShardHeaderInfo, orderedHdrs []data.HeaderHandler, orderedHdrsHashes [][]byte, + maxShardHeadersFromSameShard uint32, haveTime func() bool, ) error { hdrsAdded := uint32(0) - maxShardHeadersFromSameShard := core.MaxUint32( - process.MinShardHeadersFromSameShardInOneMetaBlock, - process.MaxShardHeadersAllowedInOneMetaBlock/mp.shardCoordinator.NumberOfShards(), - ) maxShardHeadersAllowedInOneMetaBlock := maxShardHeadersFromSameShard * mp.shardCoordinator.NumberOfShards() hdrsAddedForShard := make(map[uint32]uint32) for i := 0; i < len(orderedHdrs); i++ { @@ -349,6 +350,8 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( Hash: currHdrHash, UsedInBlock: true, } + hdrsAddedForShard[currHdr.GetShardID()]++ + hdrsAdded++ continue } @@ -366,12 +369,14 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( break } - mp.miniBlocksSelectionSession.AddReferencedHeader(currHdr, orderedHdrsHashes[i]) + mp.miniBlocksSelectionSession.AddReferencedHeader(currHdr, currHdrHash) lastShardHdr[currHdr.GetShardID()] = ShardHeaderInfo{ Header: currHdr, Hash: currHdrHash, UsedInBlock: true, } + hdrsAddedForShard[currHdr.GetShardID()]++ + hdrsAdded++ } return nil diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index 2638cdf5bf6..c964434adef 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -982,3 +982,177 @@ func Test_hasRewardOrPeerMiniBlocksFromSelf(t *testing.T) { require.True(t, response) }) } + +func TestMetaProcessor_createProposalMiniBlocks(t *testing.T) { + t.Parallel() + miniblockSelectionSessionNoAdd := &mbSelection.MiniBlockSelectionSessionStub{ + AddMiniBlocksAndHashesCalled: func(miniBlocksAndHashes []block.MiniblockAndHash) error { + require.Fail(t, "miniBlocksAndHashes should not be called") + return nil + }, + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { + require.Fail(t, "AddReferencedHeader should not be called") + }, + CreateAndAddMiniBlockFromTransactionsCalled: func(txHashes [][]byte) error { + require.Fail(t, "CreateAndAddMiniBlockFromTransactions should not be called") + return nil + }, + } + t.Run("no time", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = miniblockSelectionSessionNoAdd + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + err = mp.CreateProposalMiniBlocks(haveTimeFalse) + require.Nil(t, err) + }) + t.Run("with time and error returned by selectIncomingMiniBlocksForProposal", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.BlockTracker = &mock.BlockTrackerMock{ + ComputeLongestShardsChainsFromLastNotarizedCalled: func() ([]data.HeaderHandler, [][]byte, map[uint32][]data.HeaderHandler, error) { + return nil, nil, nil, expectedErr + }, + } + arguments.MiniBlocksSelectionSession = miniblockSelectionSessionNoAdd + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + err = mp.CreateProposalMiniBlocks(haveTimeTrue) + require.Equal(t, expectedErr, err) + }) + t.Run("with time and no error, no mini blocks/shard headers", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = miniblockSelectionSessionNoAdd + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + err = mp.CreateProposalMiniBlocks(haveTimeTrue) + require.Nil(t, err) + }) +} + +func TestMetaProcessor_selectIncomingMiniBlocksForProposal(t *testing.T) { + t.Parallel() + + t.Run("error from ComputeLongestShardsChainsFromLastNotarized", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.BlockTracker = &mock.BlockTrackerMock{ + ComputeLongestShardsChainsFromLastNotarizedCalled: func() ([]data.HeaderHandler, [][]byte, map[uint32][]data.HeaderHandler, error) { + return nil, nil, nil, expectedErr + }, + } + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + err = mp.SelectIncomingMiniBlocksForProposal(haveTimeTrue) + require.Equal(t, expectedErr, err) + }) + t.Run("error from getLastCrossNotarizedShardHdrs", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.BlockTracker = &mock.BlockTrackerMock{ + ComputeLongestShardsChainsFromLastNotarizedCalled: func() ([]data.HeaderHandler, [][]byte, map[uint32][]data.HeaderHandler, error) { + return []data.HeaderHandler{}, [][]byte{}, nil, nil + }, + GetLastCrossNotarizedHeaderCalled: func(shardID uint32) (data.HeaderHandler, []byte, error) { + return nil, nil, expectedErr + }, + } + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + err = mp.SelectIncomingMiniBlocksForProposal(haveTimeTrue) + require.Equal(t, expectedErr, err) + }) + t.Run("selection ok", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + err = mp.SelectIncomingMiniBlocksForProposal(haveTimeTrue) + require.Nil(t, err) + }) +} + +func TestMetaProcessor_selectIncomingMiniBlocks(t *testing.T) { + t.Parallel() + + t.Run("no ordered headers", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddMiniBlocksAndHashesCalled: func(miniBlocksAndHashes []block.MiniblockAndHash) error { + require.Fail(t, "should not be called") + return nil + }, + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { + require.Fail(t, "should not be called") + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + orederdHeaders := []data.HeaderHandler{} + orderedHeaderHashes := [][]byte{} + + maxNumHeadersFromSameShard := uint32(2) + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, orederdHeaders, orderedHeaderHashes, maxNumHeadersFromSameShard, haveTimeTrue) + require.Nil(t, err) + }) +} + +func createLastShardHeadersNotGenesis() map[uint32]blproc.ShardHeaderInfo { + shard0 := uint32(0) + shard1 := uint32(1) + shard2 := uint32(2) + + return map[uint32]blproc.ShardHeaderInfo{ + shard0: { + Header: &block.Header{ + ShardID: shard0, + Nonce: 10, + Round: 10, + }, + Hash: []byte("hash1"), + }, + shard1: { + Header: &block.Header{ + ShardID: shard1, + Nonce: 10, + Round: 10, + }, + Hash: []byte("hash2"), + }, + shard2: { + Header: &block.Header{ + ShardID: shard2, + Nonce: 10, + Round: 10, + }, + Hash: []byte("hash3"), + }, + } +} From 37cee1f057c1643b7d750647ef7472845cb78d46 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Fri, 24 Oct 2025 11:05:34 +0300 Subject: [PATCH 18/51] MX-17245 Adding unit tests for shardinfo --- process/block/shardinfo_test.go | 130 ++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 process/block/shardinfo_test.go diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go new file mode 100644 index 00000000000..67b931ad2cb --- /dev/null +++ b/process/block/shardinfo_test.go @@ -0,0 +1,130 @@ +package block + +import ( + "testing" + + "github.com/multiversx/mx-chain-go/process" + "github.com/multiversx/mx-chain-go/process/mock" + "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" + "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" + "github.com/multiversx/mx-chain-go/testscommon/pool" + "github.com/stretchr/testify/assert" +) + +func TestShardInfo_NewShardInfoCreateData(t *testing.T) { + t.Parallel() + + t.Run("nil enableEpochsHandler", func(t *testing.T) { + t.Parallel() + + headersPool := &pool.HeadersPoolStub{} + proofsPool := &dataRetriever.ProofsPoolMock{} + pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} + blockTracker := &mock.BlockTrackerMock{} + + sicd, err := NewShardInfoCreateData( + nil, + headersPool, + proofsPool, + pendingMiniBlocksHandler, + blockTracker, + ) + assert.Nil(t, sicd) + assert.Equal(t, process.ErrNilEnableEpochsHandler, err) + }) + + t.Run("nil headersPool", func(t *testing.T) { + t.Parallel() + + proofsPool := &dataRetriever.ProofsPoolMock{} + pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} + blockTracker := &mock.BlockTrackerMock{} + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + + sicd, err := NewShardInfoCreateData( + enableEpochsHandler, + nil, + proofsPool, + pendingMiniBlocksHandler, + blockTracker, + ) + assert.Nil(t, sicd) + assert.Equal(t, process.ErrNilHeadersDataPool, err) + }) + + t.Run("nil proofsPool", func(t *testing.T) { + t.Parallel() + + headersPool := &pool.HeadersPoolStub{} + pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} + blockTracker := &mock.BlockTrackerMock{} + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + + sicd, err := NewShardInfoCreateData( + enableEpochsHandler, + headersPool, + nil, + pendingMiniBlocksHandler, + blockTracker, + ) + assert.Nil(t, sicd) + assert.Equal(t, process.ErrNilProofsPool, err) + }) + + t.Run("nil pendingMiniBlocksHandler", func(t *testing.T) { + t.Parallel() + + headersPool := &pool.HeadersPoolStub{} + proofsPool := &dataRetriever.ProofsPoolMock{} + blockTracker := &mock.BlockTrackerMock{} + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + + sicd, err := NewShardInfoCreateData( + enableEpochsHandler, + headersPool, + proofsPool, + nil, + blockTracker, + ) + assert.Nil(t, sicd) + assert.Equal(t, process.ErrNilPendingMiniBlocksHandler, err) + }) + + t.Run("nil blockTracker", func(t *testing.T) { + t.Parallel() + + headersPool := &pool.HeadersPoolStub{} + proofsPool := &dataRetriever.ProofsPoolMock{} + pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + + sicd, err := NewShardInfoCreateData( + enableEpochsHandler, + headersPool, + proofsPool, + pendingMiniBlocksHandler, + nil, + ) + assert.Nil(t, sicd) + assert.Equal(t, process.ErrNilBlockTracker, err) + }) + t.Run("should work", func(t *testing.T) { + t.Parallel() + + headersPool := &pool.HeadersPoolStub{} + proofsPool := &dataRetriever.ProofsPoolMock{} + pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} + blockTracker := &mock.BlockTrackerMock{} + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + + sicd, err := NewShardInfoCreateData( + enableEpochsHandler, + headersPool, + proofsPool, + pendingMiniBlocksHandler, + blockTracker, + ) + assert.NotNil(t, sicd) + assert.Nil(t, err) + }) +} From 24f64a5a7c2d977a9a9495b570862c3c71edc0f9 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Sat, 25 Oct 2025 04:37:57 +0300 Subject: [PATCH 19/51] MX-17245 coverage for createShardMiniblockHeader --- process/block/shardinfo_test.go | 248 +++++++++++++++++++++++++------- 1 file changed, 194 insertions(+), 54 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 67b931ad2cb..17dd4a940cb 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -1,14 +1,20 @@ package block import ( + "fmt" "testing" + "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/pool" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestShardInfo_NewShardInfoCreateData(t *testing.T) { @@ -17,114 +23,248 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { t.Run("nil enableEpochsHandler", func(t *testing.T) { t.Parallel() - headersPool := &pool.HeadersPoolStub{} - proofsPool := &dataRetriever.ProofsPoolMock{} - pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} - blockTracker := &mock.BlockTrackerMock{} - + args := createDefaultShardInfoCreateDataArgs() sicd, err := NewShardInfoCreateData( nil, - headersPool, - proofsPool, - pendingMiniBlocksHandler, - blockTracker, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, ) assert.Nil(t, sicd) + assert.True(t, sicd.IsInterfaceNil()) assert.Equal(t, process.ErrNilEnableEpochsHandler, err) }) t.Run("nil headersPool", func(t *testing.T) { t.Parallel() - - proofsPool := &dataRetriever.ProofsPoolMock{} - pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} - blockTracker := &mock.BlockTrackerMock{} - enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() - + args := createDefaultShardInfoCreateDataArgs() sicd, err := NewShardInfoCreateData( - enableEpochsHandler, + args.enableEpochsHandler, nil, - proofsPool, - pendingMiniBlocksHandler, - blockTracker, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, ) assert.Nil(t, sicd) + assert.True(t, sicd.IsInterfaceNil()) assert.Equal(t, process.ErrNilHeadersDataPool, err) }) t.Run("nil proofsPool", func(t *testing.T) { t.Parallel() - headersPool := &pool.HeadersPoolStub{} - pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} - blockTracker := &mock.BlockTrackerMock{} - enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + args := createDefaultShardInfoCreateDataArgs() sicd, err := NewShardInfoCreateData( - enableEpochsHandler, - headersPool, + args.enableEpochsHandler, + args.headersPool, nil, - pendingMiniBlocksHandler, - blockTracker, + args.pendingMiniBlocksHandler, + args.blockTracker, ) assert.Nil(t, sicd) + assert.True(t, sicd.IsInterfaceNil()) assert.Equal(t, process.ErrNilProofsPool, err) }) t.Run("nil pendingMiniBlocksHandler", func(t *testing.T) { t.Parallel() - headersPool := &pool.HeadersPoolStub{} - proofsPool := &dataRetriever.ProofsPoolMock{} - blockTracker := &mock.BlockTrackerMock{} - enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + args := createDefaultShardInfoCreateDataArgs() sicd, err := NewShardInfoCreateData( - enableEpochsHandler, - headersPool, - proofsPool, + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, nil, - blockTracker, + args.blockTracker, ) assert.Nil(t, sicd) + assert.True(t, sicd.IsInterfaceNil()) assert.Equal(t, process.ErrNilPendingMiniBlocksHandler, err) }) t.Run("nil blockTracker", func(t *testing.T) { t.Parallel() - headersPool := &pool.HeadersPoolStub{} - proofsPool := &dataRetriever.ProofsPoolMock{} - pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} - enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() - + args := createDefaultShardInfoCreateDataArgs() sicd, err := NewShardInfoCreateData( - enableEpochsHandler, - headersPool, - proofsPool, - pendingMiniBlocksHandler, + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, nil, ) assert.Nil(t, sicd) + assert.True(t, sicd.IsInterfaceNil()) assert.Equal(t, process.ErrNilBlockTracker, err) }) t.Run("should work", func(t *testing.T) { t.Parallel() - headersPool := &pool.HeadersPoolStub{} - proofsPool := &dataRetriever.ProofsPoolMock{} - pendingMiniBlocksHandler := &mock.PendingMiniBlocksHandlerStub{} - blockTracker := &mock.BlockTrackerMock{} - enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + args := createDefaultShardInfoCreateDataArgs() sicd, err := NewShardInfoCreateData( - enableEpochsHandler, - headersPool, - proofsPool, - pendingMiniBlocksHandler, - blockTracker, + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, ) assert.NotNil(t, sicd) + assert.False(t, sicd.IsInterfaceNil()) assert.Nil(t, err) }) } + +func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { + t.Parallel() + + headerHandler := getShardHeaderForShard1() + t.Run("ScheduledMiniBlocksFlag disabled", func(t *testing.T) { + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + + miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) + require.NotNil(t, miniblockHeaders) + require.Equal(t, 3, len(miniblockHeaders)) + }) + t.Run("ScheduledMiniBlocksFlag enabled, all miniblocks final", func(t *testing.T) { + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { + return flag == common.ScheduledMiniBlocksFlag + } + + miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) + require.NotNil(t, miniblockHeaders) + require.Equal(t, 3, len(miniblockHeaders)) + }) + t.Run("ScheduledMiniBlocksFlag enabled, not all miniblocks final", func(t *testing.T) { + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { + return flag == common.ScheduledMiniBlocksFlag + } + _ = headerHandler.GetMiniBlockHeaderHandlers()[1].SetConstructionState(int32(block.Proposed)) + require.False(t, headerHandler.GetMiniBlockHeaderHandlers()[1].IsFinal()) + + miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) + require.NotNil(t, miniblockHeaders) + require.Equal(t, 2, len(miniblockHeaders)) + }) + t.Run("ScheduledMiniBlocksFlag enabled, no final miniblocks", func(t *testing.T) { + enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() + enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { + return flag == common.ScheduledMiniBlocksFlag + } + for i := 0; i < len(headerHandler.GetMiniBlockHeaderHandlers()); i++ { + fmt.Printf("MiniBlockHeader %d: %v\n", i, headerHandler.GetMiniBlockHeaderHandlers()[i]) + _ = headerHandler.GetMiniBlockHeaderHandlers()[i].SetConstructionState(int32(block.Proposed)) + require.False(t, headerHandler.GetMiniBlockHeaderHandlers()[i].IsFinal()) + } + + miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) + require.NotNil(t, miniblockHeaders) + require.Equal(t, 0, len(miniblockHeaders)) + }) +} + +func TestShardInfoCreateData_createShardMiniBlockHeaderFromExecutionResultHandler(t *testing.T) { + t.Parallel() + + execResultHandler := getExecutionResultForShard1() + shardMiniBlockHeaders := createShardMiniBlockHeaderFromExecutionResultHandler(execResultHandler) + require.NotNil(t, shardMiniBlockHeaders) + require.Equal(t, 3, len(shardMiniBlockHeaders)) + for i := 0; i < len(shardMiniBlockHeaders); i++ { + assert.Equal(t, execResultHandler.MiniBlockHeaders[i].Hash, shardMiniBlockHeaders[i].Hash) + assert.Equal(t, execResultHandler.MiniBlockHeaders[i].Type, shardMiniBlockHeaders[i].Type) + assert.Equal(t, execResultHandler.MiniBlockHeaders[i].TxCount, shardMiniBlockHeaders[i].TxCount) + assert.Equal(t, execResultHandler.MiniBlockHeaders[i].SenderShardID, shardMiniBlockHeaders[i].SenderShardID) + assert.Equal(t, execResultHandler.MiniBlockHeaders[i].ReceiverShardID, shardMiniBlockHeaders[i].ReceiverShardID) + } +} + +type shardInfoCreateDataTestArgs struct { + headersPool *pool.HeadersPoolStub + proofsPool *dataRetriever.ProofsPoolMock + pendingMiniBlocksHandler *mock.PendingMiniBlocksHandlerStub + blockTracker *mock.BlockTrackerMock + enableEpochsHandler *enableEpochsHandlerMock.EnableEpochsHandlerStub +} + +func createDefaultShardInfoCreateDataArgs() *shardInfoCreateDataTestArgs { + return &shardInfoCreateDataTestArgs{ + headersPool: &pool.HeadersPoolStub{}, + proofsPool: &dataRetriever.ProofsPoolMock{}, + pendingMiniBlocksHandler: &mock.PendingMiniBlocksHandlerStub{}, + blockTracker: &mock.BlockTrackerMock{}, + enableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), + } +} + +func getMiniBlockHeadersForShard1() []block.MiniBlockHeader { + mbHash1 := []byte("mb hash 1") + mbHash2 := []byte("mb hash 2") + mbHash3 := []byte("mb hash 3") + + miniBlockHeader1 := block.MiniBlockHeader{ + Hash: mbHash1, + Type: block.TxBlock, + TxCount: 10, + SenderShardID: 1, + ReceiverShardID: 2, + } + miniBlockHeader2 := block.MiniBlockHeader{ + Hash: mbHash2, + Type: block.InvalidBlock, + TxCount: 1, + SenderShardID: 1, + ReceiverShardID: 2, + } + miniBlockHeader3 := block.MiniBlockHeader{ + Hash: mbHash3, + Type: block.SmartContractResultBlock, + TxCount: 5, + SenderShardID: 1, + ReceiverShardID: 0, + } + + miniBlockHeaders := make([]block.MiniBlockHeader, 0) + miniBlockHeaders = append(miniBlockHeaders, miniBlockHeader1) + miniBlockHeaders = append(miniBlockHeaders, miniBlockHeader2) + miniBlockHeaders = append(miniBlockHeaders, miniBlockHeader3) + return miniBlockHeaders +} + +func getShardHeaderForShard1() data.HeaderHandler { + prevHash := []byte("prevHash") + prevRandSeed := []byte("prevRandSeed") + currRandSeed := []byte("currRandSeed") + return &block.HeaderV2{ + Header: &block.Header{ + Round: 10, + Nonce: 45, + ShardID: 0, + PrevRandSeed: prevRandSeed, + RandSeed: currRandSeed, + PrevHash: prevHash, + MiniBlockHeaders: getMiniBlockHeadersForShard1(), + }, + } +} + +func getExecutionResultForShard1() *block.ExecutionResult { + + return &block.ExecutionResult{ + ExecutedTxCount: 100, + MiniBlockHeaders: getMiniBlockHeadersForShard1(), + BaseExecutionResult: &block.BaseExecutionResult{ + HeaderHash: []byte("header hash"), + HeaderNonce: 12345, + HeaderEpoch: 7, + HeaderRound: 15, + RootHash: []byte("root hash"), + GasUsed: 5000, + }, + } +} From 8d0661705147fcd98d24705e93f6c19b28af085b Mon Sep 17 00:00:00 2001 From: Daniel Radu Date: Mon, 27 Oct 2025 12:29:45 +0200 Subject: [PATCH 20/51] added maps to avoid duplicates --- process/block/mbsSelectionSession.go | 57 +++++++++++++++-------- process/block/mbsSelectionSession_test.go | 55 ++++++++++++++++++++++ 2 files changed, 92 insertions(+), 20 deletions(-) diff --git a/process/block/mbsSelectionSession.go b/process/block/mbsSelectionSession.go index 2101c7c949a..4ff0f62d5b9 100644 --- a/process/block/mbsSelectionSession.go +++ b/process/block/mbsSelectionSession.go @@ -20,15 +20,17 @@ type miniBlocksSelectionConfig struct { } type miniBlocksSelectionResult struct { - miniBlockHeaderHandlers []data.MiniBlockHeaderHandler - miniBlocks block.MiniBlockSlice - miniBlockHashes [][]byte - referencedHeaderHashes [][]byte - referencedHeader []data.HeaderHandler - lastHeader data.HeaderHandler - gasProvided uint64 - numTxsAdded uint32 - mut sync.RWMutex + miniBlockHeaderHandlers []data.MiniBlockHeaderHandler + miniBlocks block.MiniBlockSlice + miniBlockHashes [][]byte + miniBlockHashesUnique map[string]struct{} + referenceHeaderHashesUnique map[string]struct{} + referencedHeaderHashes [][]byte + referencedHeader []data.HeaderHandler + lastHeader data.HeaderHandler + gasProvided uint64 + numTxsAdded uint32 + mut sync.RWMutex } type miniBlocksSelectionSession struct { @@ -54,14 +56,16 @@ func NewMiniBlocksSelectionSession(shardID uint32, marshaller marshal.Marshalize hasher: hasher, }, miniBlocksSelectionResult: &miniBlocksSelectionResult{ - miniBlockHeaderHandlers: make([]data.MiniBlockHeaderHandler, 0, defaultCapacity), - miniBlocks: make(block.MiniBlockSlice, 0, defaultCapacity), - miniBlockHashes: make([][]byte, 0, defaultCapacity), - referencedHeaderHashes: make([][]byte, 0, defaultCapacity), - referencedHeader: make([]data.HeaderHandler, 0, defaultCapacity), - lastHeader: nil, - gasProvided: 0, - numTxsAdded: 0, + miniBlockHeaderHandlers: make([]data.MiniBlockHeaderHandler, 0, defaultCapacity), + miniBlocks: make(block.MiniBlockSlice, 0, defaultCapacity), + miniBlockHashes: make([][]byte, 0, defaultCapacity), + miniBlockHashesUnique: make(map[string]struct{}), + referenceHeaderHashesUnique: make(map[string]struct{}), + referencedHeaderHashes: make([][]byte, 0, defaultCapacity), + referencedHeader: make([]data.HeaderHandler, 0, defaultCapacity), + lastHeader: nil, + gasProvided: 0, + numTxsAdded: 0, }, }, nil } @@ -74,6 +78,8 @@ func (s *miniBlocksSelectionSession) ResetSelectionSession() { s.miniBlockHeaderHandlers = make([]data.MiniBlockHeaderHandler, 0, defaultCapacity) s.miniBlocks = make(block.MiniBlockSlice, 0, defaultCapacity) s.miniBlockHashes = make([][]byte, 0, defaultCapacity) + s.miniBlockHashesUnique = make(map[string]struct{}) + s.referenceHeaderHashesUnique = make(map[string]struct{}) s.referencedHeaderHashes = make([][]byte, 0, defaultCapacity) s.referencedHeader = make([]data.HeaderHandler, 0, defaultCapacity) s.lastHeader = nil @@ -135,9 +141,13 @@ func (s *miniBlocksSelectionSession) AddReferencedHeader(header data.HeaderHandl return } - s.referencedHeader = append(s.referencedHeader, header) - s.referencedHeaderHashes = append(s.referencedHeaderHashes, headerHash) - s.lastHeader = header + _, ok := s.referenceHeaderHashesUnique[string(headerHash)] + if !ok { + s.referenceHeaderHashesUnique[string(headerHash)] = struct{}{} + s.referencedHeader = append(s.referencedHeader, header) + s.referencedHeaderHashes = append(s.referencedHeaderHashes, headerHash) + s.lastHeader = header + } } // GetReferencedHeaderHashes returns the hashes of the referenced headers @@ -203,6 +213,13 @@ func (s *miniBlocksSelectionSession) AddMiniBlocksAndHashes(miniBlocksAndHashes numTxsAdded := 0 for _, miniBlockInfo := range miniBlocksAndHashes { + _, ok := s.miniBlockHashesUnique[string(miniBlockInfo.Hash)] + if ok { + continue + } + + s.miniBlockHashesUnique[string(miniBlockInfo.Hash)] = struct{}{} + txCount := len(miniBlockInfo.Miniblock.GetTxHashes()) mbHeader := &block.MiniBlockHeader{ diff --git a/process/block/mbsSelectionSession_test.go b/process/block/mbsSelectionSession_test.go index 3d453812432..858a0007a53 100644 --- a/process/block/mbsSelectionSession_test.go +++ b/process/block/mbsSelectionSession_test.go @@ -47,6 +47,16 @@ func TestMiniBlockSelectionSession_ResetSelectionSession(t *testing.T) { t.Parallel() session := createDummyFilledSession() + + require.NotEmpty(t, session.GetMiniBlocks()) + require.NotEmpty(t, session.GetMiniBlockHeaderHandlers()) + require.NotEmpty(t, session.GetMiniBlockHashes()) + require.NotEmpty(t, session.GetReferencedHeaderHashes()) + require.NotEmpty(t, session.GetReferencedHeaders()) + require.NotEmpty(t, session.referenceHeaderHashesUnique) + require.NotEmpty(t, session.miniBlockHashesUnique) + require.NotNil(t, session.GetLastHeader()) + session.ResetSelectionSession() require.Empty(t, session.GetMiniBlocks()) @@ -54,6 +64,8 @@ func TestMiniBlockSelectionSession_ResetSelectionSession(t *testing.T) { require.Empty(t, session.GetMiniBlockHashes()) require.Empty(t, session.GetReferencedHeaderHashes()) require.Empty(t, session.GetReferencedHeaders()) + require.Empty(t, session.referenceHeaderHashesUnique) + require.Empty(t, session.miniBlockHashesUnique) require.Nil(t, session.GetLastHeader()) require.Equal(t, uint64(0), session.GetGasProvided()) require.Equal(t, uint32(0), session.GetNumTxsAdded()) @@ -89,6 +101,29 @@ func TestMiniBlockSelectionSession_AddMiniBlocksAndHashes(t *testing.T) { require.Empty(t, session.GetMiniBlocks()) require.Empty(t, session.GetMiniBlockHashes()) }) + + t.Run("should not add same mini block twice", func(t *testing.T) { + t.Parallel() + + session, _ := NewMiniBlocksSelectionSession(1, marshaller, hasher) + err := session.AddMiniBlocksAndHashes([]block.MiniblockAndHash{ + {&block.MiniBlock{}, []byte("hash1")}, + {&block.MiniBlock{}, []byte("hash2")}, + {&block.MiniBlock{}, []byte("hash3")}, + }) + + require.NoError(t, err) + require.Equal(t, 3, len(session.GetMiniBlocks())) + require.Equal(t, 3, len(session.GetMiniBlockHashes())) + + err = session.AddMiniBlocksAndHashes([]block.MiniblockAndHash{ + {&block.MiniBlock{}, []byte("hash1")}, + }) + + require.NoError(t, err) + require.Equal(t, 3, len(session.GetMiniBlocks())) + }) + t.Run("should add mini blocks and hashes successfully", func(t *testing.T) { t.Parallel() @@ -236,6 +271,24 @@ func TestMiniBlocksSelectionSession_AddReferencedMetaBlock(t *testing.T) { require.Empty(t, session.GetReferencedHeaders()) require.Empty(t, session.GetReferencedHeaderHashes()) }) + t.Run("should not add same reference header twice", func(t *testing.T) { + session, _ := NewMiniBlocksSelectionSession(1, marshaller, hasher) + metaBlock := &block.MetaBlock{Epoch: 1, Round: 1} + metaBlockHash := []byte("metaHash") + session.AddReferencedHeader(metaBlock, metaBlockHash) + + require.Len(t, session.GetReferencedHeaders(), 1) + require.Len(t, session.GetReferencedHeaderHashes(), 1) + require.Equal(t, metaBlock, session.GetReferencedHeaders()[0]) + require.Equal(t, metaBlockHash, session.GetReferencedHeaderHashes()[0]) + + session.AddReferencedHeader(metaBlock, metaBlockHash) + + require.Len(t, session.GetReferencedHeaders(), 1) + require.Len(t, session.GetReferencedHeaderHashes(), 1) + require.Equal(t, metaBlock, session.GetReferencedHeaders()[0]) + require.Equal(t, metaBlockHash, session.GetReferencedHeaderHashes()[0]) + }) } func TestMiniBlocksSelectionSession_IsInterfaceNil(t *testing.T) { @@ -276,6 +329,8 @@ func createDummyFilledSession() *miniBlocksSelectionSession { // Add dummy mini blocks and hashes session.miniBlocks = append(session.miniBlocks, miniBlock) session.miniBlockHashes = append(session.miniBlockHashes, miniBlockHash) + session.miniBlockHashesUnique[string(miniBlockHash)] = struct{}{} + session.referenceHeaderHashesUnique[string(metaBlockHash)] = struct{}{} session.miniBlockHeaderHandlers = append(session.miniBlockHeaderHandlers, miniBlockHeader) session.referencedHeaderHashes = append(session.referencedHeaderHashes, metaBlockHash) session.referencedHeader = append(session.referencedHeader, metaBlock) From 640c2b58f8fa9f4e184c1a5b699026299859e60c Mon Sep 17 00:00:00 2001 From: Daniel Radu Date: Mon, 27 Oct 2025 12:44:32 +0200 Subject: [PATCH 21/51] removed gasProvided --- process/block/interface.go | 1 - process/block/mbsSelectionSession.go | 11 ----------- process/block/mbsSelectionSession_test.go | 3 --- 3 files changed, 15 deletions(-) diff --git a/process/block/interface.go b/process/block/interface.go index c9189edf1a8..a53c4f56700 100644 --- a/process/block/interface.go +++ b/process/block/interface.go @@ -64,7 +64,6 @@ type MiniBlocksSelectionSession interface { GetReferencedHeaderHashes() [][]byte GetReferencedHeaders() []data.HeaderHandler GetLastHeader() data.HeaderHandler - GetGasProvided() uint64 GetNumTxsAdded() uint32 AddMiniBlocksAndHashes(miniBlocksAndHashes []block.MiniblockAndHash) error CreateAndAddMiniBlockFromTransactions(txHashes [][]byte) error diff --git a/process/block/mbsSelectionSession.go b/process/block/mbsSelectionSession.go index 4ff0f62d5b9..e5c03490753 100644 --- a/process/block/mbsSelectionSession.go +++ b/process/block/mbsSelectionSession.go @@ -28,7 +28,6 @@ type miniBlocksSelectionResult struct { referencedHeaderHashes [][]byte referencedHeader []data.HeaderHandler lastHeader data.HeaderHandler - gasProvided uint64 numTxsAdded uint32 mut sync.RWMutex } @@ -64,7 +63,6 @@ func NewMiniBlocksSelectionSession(shardID uint32, marshaller marshal.Marshalize referencedHeaderHashes: make([][]byte, 0, defaultCapacity), referencedHeader: make([]data.HeaderHandler, 0, defaultCapacity), lastHeader: nil, - gasProvided: 0, numTxsAdded: 0, }, }, nil @@ -83,7 +81,6 @@ func (s *miniBlocksSelectionSession) ResetSelectionSession() { s.referencedHeaderHashes = make([][]byte, 0, defaultCapacity) s.referencedHeader = make([]data.HeaderHandler, 0, defaultCapacity) s.lastHeader = nil - s.gasProvided = 0 s.numTxsAdded = 0 } @@ -188,14 +185,6 @@ func (s *miniBlocksSelectionSession) GetLastHeader() data.HeaderHandler { return s.lastHeader } -// GetGasProvided returns the gas provided for the mini blocks -func (s *miniBlocksSelectionSession) GetGasProvided() uint64 { - s.mut.RLock() - defer s.mut.RUnlock() - - return s.gasProvided -} - // GetNumTxsAdded returns the number of transactions added to the mini blocks func (s *miniBlocksSelectionSession) GetNumTxsAdded() uint32 { s.mut.RLock() diff --git a/process/block/mbsSelectionSession_test.go b/process/block/mbsSelectionSession_test.go index 858a0007a53..1df7c75c665 100644 --- a/process/block/mbsSelectionSession_test.go +++ b/process/block/mbsSelectionSession_test.go @@ -67,7 +67,6 @@ func TestMiniBlockSelectionSession_ResetSelectionSession(t *testing.T) { require.Empty(t, session.referenceHeaderHashesUnique) require.Empty(t, session.miniBlockHashesUnique) require.Nil(t, session.GetLastHeader()) - require.Equal(t, uint64(0), session.GetGasProvided()) require.Equal(t, uint32(0), session.GetNumTxsAdded()) } @@ -82,7 +81,6 @@ func TestMiniBlockSelectionSession_Getters(t *testing.T) { require.Len(t, session.GetReferencedHeaderHashes(), 1) require.Len(t, session.GetReferencedHeaders(), 1) require.NotNil(t, session.GetLastHeader()) - require.Equal(t, uint64(100), session.GetGasProvided()) require.Equal(t, uint32(2), session.GetNumTxsAdded()) } @@ -335,7 +333,6 @@ func createDummyFilledSession() *miniBlocksSelectionSession { session.referencedHeaderHashes = append(session.referencedHeaderHashes, metaBlockHash) session.referencedHeader = append(session.referencedHeader, metaBlock) session.lastHeader = metaBlock - session.gasProvided = 100 session.numTxsAdded = 2 return session From e8a514fcd893aeb03d021f1428ad6c2cbbb543da Mon Sep 17 00:00:00 2001 From: Daniel Radu Date: Mon, 27 Oct 2025 13:04:48 +0200 Subject: [PATCH 22/51] fix --- process/block/mbsSelectionSession.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/process/block/mbsSelectionSession.go b/process/block/mbsSelectionSession.go index e5c03490753..213079fde8d 100644 --- a/process/block/mbsSelectionSession.go +++ b/process/block/mbsSelectionSession.go @@ -201,6 +201,9 @@ func (s *miniBlocksSelectionSession) AddMiniBlocksAndHashes(miniBlocksAndHashes miniBlockHashes := make([][]byte, 0, len(miniBlocksAndHashes)) numTxsAdded := 0 + s.mut.Lock() + defer s.mut.Unlock() + for _, miniBlockInfo := range miniBlocksAndHashes { _, ok := s.miniBlockHashesUnique[string(miniBlockInfo.Hash)] if ok { @@ -229,8 +232,6 @@ func (s *miniBlocksSelectionSession) AddMiniBlocksAndHashes(miniBlocksAndHashes numTxsAdded += txCount } - s.mut.Lock() - defer s.mut.Unlock() s.miniBlocks = append(s.miniBlocks, miniBlocks...) s.miniBlockHeaderHandlers = append(s.miniBlockHeaderHandlers, miniBlockHeaderHandlers...) s.miniBlockHashes = append(s.miniBlockHashes, miniBlockHashes...) From c4efd84897e14a5a0525f0adc1afbd81e3564931 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Mon, 27 Oct 2025 15:37:13 +0200 Subject: [PATCH 23/51] MX-17245 Added unit tests --- process/block/shardinfo_test.go | 185 +++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 2 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 17dd4a940cb..4784c42647a 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -118,11 +118,135 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { }) } +func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { + t.Parallel() + + t.Run("should fail with nil execution result", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromExecutionResult(nil) + require.NotNil(t, err) + require.Nil(t, shardData) + require.ErrorIs(t, err, process.ErrNilExecutionResultHandler) + }) + + t.Run("should fail with wrong type of execution result", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + var execResult data.BaseExecutionResultHandler = &block.BaseExecutionResult{} + shardData, err := sic.createShardDataFromExecutionResult(execResult) + require.NotNil(t, err) + require.Nil(t, shardData) + require.ErrorIs(t, err, process.ErrWrongTypeAssertion) + }) + + t.Run("should fail when GetHeaderByHash errors", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + return nil, fmt.Errorf("GetHeaderByHash error") + } + + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + execResult := getExecutionResultForShard1() + shardData, err := sic.createShardDataFromExecutionResult(execResult) + require.NotNil(t, err) + require.Nil(t, shardData) + require.Equal(t, fmt.Errorf("GetHeaderByHash error"), err) + }) + + t.Run("should fail when updateShardDataWithCrossShardInfo fails", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + return getShardHeaderForShard1(), nil + } + + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + execResult := getExecutionResultForShard1() + shardData, err := sic.createShardDataFromExecutionResult(execResult) + require.NotNil(t, err) + require.Nil(t, shardData) + require.Equal(t, fmt.Errorf("notarized headers slice is nil"), err) + }) + + t.Run("should work", func(t *testing.T) { + t.Parallel() + expectedNonce := uint64(1) + header := getShardHeaderForShard1() + args := createDefaultShardInfoCreateDataArgs() + args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + return header, nil + } + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + execResult := getExecutionResultForShard1() + shardData, err := sic.createShardDataFromExecutionResult(execResult) + require.Nil(t, err) + require.NotNil(t, shardData) + assert.Equal(t, uint32(2), shardData.GetNumPendingMiniBlocks()) + assert.Equal(t, uint32(execResult.GetExecutedTxCount()), shardData.GetTxCount()) + assert.Equal(t, uint32(1), shardData.GetShardID()) + assert.Equal(t, shardData.GetAccumulatedFees(), execResult.GetAccumulatedFees()) + assert.Equal(t, execResult.GetHeaderHash(), shardData.GetHeaderHash()) + assert.Equal(t, execResult.GetHeaderRound(), shardData.GetRound()) + assert.Equal(t, header.GetPrevHash(), shardData.GetPrevHash()) + assert.Equal(t, execResult.GetHeaderNonce(), shardData.GetNonce()) + assert.Equal(t, header.GetPrevRandSeed(), shardData.GetPrevRandSeed()) + assert.Equal(t, header.GetPubKeysBitmap(), shardData.GetPubKeysBitmap()) + assert.Equal(t, shardData.GetAccumulatedFees(), execResult.GetAccumulatedFees()) + assert.Equal(t, shardData.GetDeveloperFees(), execResult.GetDeveloperFees()) + }) +} + func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { t.Parallel() - headerHandler := getShardHeaderForShard1() t.Run("ScheduledMiniBlocksFlag disabled", func(t *testing.T) { + t.Parallel() + headerHandler := getShardHeaderForShard1() enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) @@ -130,6 +254,8 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { require.Equal(t, 3, len(miniblockHeaders)) }) t.Run("ScheduledMiniBlocksFlag enabled, all miniblocks final", func(t *testing.T) { + t.Parallel() + headerHandler := getShardHeaderForShard1() enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { return flag == common.ScheduledMiniBlocksFlag @@ -140,6 +266,8 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { require.Equal(t, 3, len(miniblockHeaders)) }) t.Run("ScheduledMiniBlocksFlag enabled, not all miniblocks final", func(t *testing.T) { + t.Parallel() + headerHandler := getShardHeaderForShard1() enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { return flag == common.ScheduledMiniBlocksFlag @@ -152,6 +280,8 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { require.Equal(t, 2, len(miniblockHeaders)) }) t.Run("ScheduledMiniBlocksFlag enabled, no final miniblocks", func(t *testing.T) { + t.Parallel() + headerHandler := getShardHeaderForShard1() enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { return flag == common.ScheduledMiniBlocksFlag @@ -184,6 +314,57 @@ func TestShardInfoCreateData_createShardMiniBlockHeaderFromExecutionResultHandle } } +// TODO modify when the function is updated +func TestShardInfoCreateData_updateShardDataWithCrossShardInfo(t *testing.T) { + t.Parallel() + header := block.Header{ShardID: 1} + shardData := &block.ShardData{} + + t.Run("should fail with GetLastSelfNotarizedHeader error", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return nil, nil, fmt.Errorf("GetLastSelfNotarizedHeader error") + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + err = sic.updateShardDataWithCrossShardInfo(shardData, &header) + assert.Error(t, err) + }) + + t.Run("should work with no data", func(t *testing.T) { + t.Parallel() + expectedNonce := uint64(12345) + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + err = sic.updateShardDataWithCrossShardInfo(shardData, &header) + assert.NotNil(t, shardData) + require.Nil(t, err) + assert.Equal(t, uint32(2), shardData.NumPendingMiniBlocks) + assert.Equal(t, uint64(expectedNonce), shardData.LastIncludedMetaNonce) + }) + +} + type shardInfoCreateDataTestArgs struct { headersPool *pool.HeadersPoolStub proofsPool *dataRetriever.ProofsPoolMock @@ -244,7 +425,7 @@ func getShardHeaderForShard1() data.HeaderHandler { Header: &block.Header{ Round: 10, Nonce: 45, - ShardID: 0, + ShardID: 1, PrevRandSeed: prevRandSeed, RandSeed: currRandSeed, PrevHash: prevHash, From cd0277c858787dedf961028c98c4c41b27e40fd0 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 27 Oct 2025 16:06:55 +0200 Subject: [PATCH 24/51] refactor & fixes --- process/block/baseProcess.go | 43 +++++++++++++---------------- process/block/metablockProposal.go | 30 +++++++++++++++----- process/block/shardblockProposal.go | 32 +++++++++++++-------- process/common.go | 6 ++++ 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index ba9c1104c6e..9ca9c7071b1 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -49,6 +49,13 @@ import ( var log = logger.GetOrCreate("process/block") +// CrossShardIncomingMbsCreationResult represents the result of creating cross-shard mini blocks +type CrossShardIncomingMbsCreationResult struct { + HeaderFinished bool + PendingMiniBlocks []block.MiniblockAndHash + AddedMiniBlocks []block.MiniblockAndHash +} + type hashAndHdr struct { hdr data.HeaderHandler hash []byte @@ -1129,7 +1136,6 @@ func (bp *baseProcessor) cleanupPools(headerHandler data.HeaderHandler) { } else { bp.cleanupPoolsForCrossShard(core.MetachainShardId, noncesToPrevFinal) } - } func (bp *baseProcessor) cleanupPoolsForCrossShard( @@ -2725,32 +2731,13 @@ func (bp *baseProcessor) createMbsCrossShardDstMe( currentBlockHash []byte, currentBlock data.HeaderHandler, miniBlockProcessingInfo map[string]*processedMb.ProcessedMiniBlockInfo, - allOrNothing bool, -) (bool, []block.MiniblockAndHash, error) { +) (*CrossShardIncomingMbsCreationResult, error) { currMiniBlocksAdded, pendingMiniBlocks, currNumTxsAdded, hdrFinished, errCreate := bp.txCoordinator.CreateMbsCrossShardDstMe( currentBlock, miniBlockProcessingInfo, ) if errCreate != nil { - return false, nil, errCreate - } - - if allOrNothing && len(pendingMiniBlocks) > 0 { - log.Debug("block cannot be fully processed", - "round", currentBlock.GetRound(), - "nonce", currentBlock.GetNonce(), - "hash", currentBlockHash) - bp.revertGasForCrossShardDstMeMiniBlocks(currMiniBlocksAdded, pendingMiniBlocks) - - return false, pendingMiniBlocks, nil - } - - if len(currMiniBlocksAdded) > 0 { - err := bp.miniBlocksSelectionSession.AddMiniBlocksAndHashes(currMiniBlocksAdded) - if err != nil { - return false, nil, err - } - bp.miniBlocksSelectionSession.AddReferencedHeader(currentBlock, currentBlockHash) + return nil, errCreate } if !hdrFinished { @@ -2761,10 +2748,18 @@ func (bp *baseProcessor) createMbsCrossShardDstMe( "num mbs added", len(currMiniBlocksAdded), "num txs added", currNumTxsAdded) - return false, pendingMiniBlocks, nil + return &CrossShardIncomingMbsCreationResult{ + HeaderFinished: false, + PendingMiniBlocks: pendingMiniBlocks, + AddedMiniBlocks: currMiniBlocksAdded, + }, nil } - return true, pendingMiniBlocks, nil + return &CrossShardIncomingMbsCreationResult{ + HeaderFinished: true, + PendingMiniBlocks: pendingMiniBlocks, + AddedMiniBlocks: currMiniBlocksAdded, + }, nil } func (bp *baseProcessor) revertGasForCrossShardDstMeMiniBlocks(added, pending []block.MiniblockAndHash) { diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 3c9f84c5b63..89fd6441746 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -301,9 +301,15 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( hdrsAdded := uint32(0) maxShardHeadersAllowedInOneMetaBlock := maxShardHeadersFromSameShard * mp.shardCoordinator.NumberOfShards() hdrsAddedForShard := make(map[uint32]uint32) + var err error + + if len(orderedHdrs) != len(orderedHdrsHashes) { + return process.ErrInconsistentShardHeadersAndHashes + } + for i := 0; i < len(orderedHdrs); i++ { if !haveTime() { - log.Debug("time is up after putting cross txs with destination to current shard", + log.Debug("time is up after putting cross txs with destination to metachain", "num txs", mp.miniBlocksSelectionSession.GetNumTxsAdded(), ) break @@ -318,10 +324,14 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( currHdr := orderedHdrs[i] currHdrHash := orderedHdrsHashes[i] - if currHdr.GetNonce() > lastShardHdr[currHdr.GetShardID()].Header.GetNonce()+1 { + lastShardHeaderInfo, ok := lastShardHdr[currHdr.GetShardID()] + if !ok { + return process.ErrMissingHeader + } + if currHdr.GetNonce() != lastShardHeaderInfo.Header.GetNonce()+1 { log.Trace("skip searching", "shard", currHdr.GetShardID(), - "last shard hdr nonce", lastShardHdr[currHdr.GetShardID()].Header.GetNonce(), + "last shard hdr nonce", lastShardHeaderInfo.Header.GetNonce(), "curr shard hdr nonce", currHdr.GetNonce()) continue } @@ -355,13 +365,12 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( continue } - _, pendingMiniBlocks, errCreated := mp.createMbsCrossShardDstMe(currHdrHash, currHdr, nil, true) + createIncomingMbsResult, errCreated := mp.createMbsCrossShardDstMe(currHdrHash, currHdr, nil) if errCreated != nil { return errCreated } - - // pending miniBlocks were already reverted, but still returned to check if we need to stop adding more shard headers - if len(pendingMiniBlocks) > 0 { + if !createIncomingMbsResult.HeaderFinished { + mp.revertGasForCrossShardDstMeMiniBlocks(createIncomingMbsResult.AddedMiniBlocks, createIncomingMbsResult.PendingMiniBlocks) log.Debug("shard header cannot be fully added", "round", currHdr.GetRound(), "nonce", currHdr.GetNonce(), @@ -369,6 +378,13 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( break } + if len(createIncomingMbsResult.AddedMiniBlocks) > 0 { + err = mp.miniBlocksSelectionSession.AddMiniBlocksAndHashes(createIncomingMbsResult.AddedMiniBlocks) + if err != nil { + return err + } + } + mp.miniBlocksSelectionSession.AddReferencedHeader(currHdr, currHdrHash) lastShardHdr[currHdr.GetShardID()] = ShardHeaderInfo{ Header: currHdr, diff --git a/process/block/shardblockProposal.go b/process/block/shardblockProposal.go index 7b405e0de73..8bd1fc877ae 100644 --- a/process/block/shardblockProposal.go +++ b/process/block/shardblockProposal.go @@ -552,7 +552,7 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( var currentMetaBlockHash []byte var pendingMiniBlocks []block.MiniblockAndHash var errCreated error - var shouldContinue bool + var createIncomingMbsResult *CrossShardIncomingMbsCreationResult lastMeta := lastCrossNotarizedMetaHdr for i := 0; i < len(orderedMetaBlocks); i++ { if !haveTime() { @@ -570,22 +570,22 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( } currentMetaBlock = orderedMetaBlocks[i] - if currentMetaBlock.GetNonce() > lastMeta.GetNonce()+1 { + currentMetaBlockHash = orderedMetaBlocksHashes[i] + if currentMetaBlock.GetNonce() != lastMeta.GetNonce()+1 { log.Debug("skip searching", "last meta hdr nonce", lastMeta.GetNonce(), "curr meta hdr nonce", currentMetaBlock.GetNonce()) - break + continue } - hasProofForHdr := sp.proofsPool.HasProof(core.MetachainShardId, orderedMetaBlocksHashes[i]) + hasProofForHdr := sp.proofsPool.HasProof(core.MetachainShardId, currentMetaBlockHash) if !hasProofForHdr { log.Trace("no proof for meta header", - "hash", logger.DisplayByteSlice(orderedMetaBlocksHashes[i]), + "hash", logger.DisplayByteSlice(currentMetaBlockHash), ) - break + continue } - currentMetaBlockHash = orderedMetaBlocksHashes[i] metaBlock, ok := currentMetaBlock.(data.MetaHeaderHandler) if !ok { log.Warn("selectIncomingMiniBlocks: wrong type assertion for meta block") @@ -593,20 +593,30 @@ func (sp *shardProcessor) selectIncomingMiniBlocks( } if len(currentMetaBlock.GetMiniBlockHeadersWithDst(sp.shardCoordinator.SelfId())) == 0 { - sp.miniBlocksSelectionSession.AddReferencedHeader(orderedMetaBlocks[i], orderedMetaBlocksHashes[i]) + sp.miniBlocksSelectionSession.AddReferencedHeader(currentMetaBlock, currentMetaBlockHash) lastMeta = currentMetaBlock continue } currProcessedMiniBlocksInfo := sp.processedMiniBlocksTracker.GetProcessedMiniBlocksInfo(currentMetaBlockHash) - shouldContinue, pendingMiniBlocks, errCreated = sp.createMbsCrossShardDstMe(currentMetaBlockHash, metaBlock, currProcessedMiniBlocksInfo, false) + createIncomingMbsResult, errCreated = sp.createMbsCrossShardDstMe(currentMetaBlockHash, metaBlock, currProcessedMiniBlocksInfo) if errCreated != nil { return nil, errCreated } - if !shouldContinue { + + pendingMiniBlocks = append(pendingMiniBlocks, createIncomingMbsResult.PendingMiniBlocks...) + if len(createIncomingMbsResult.AddedMiniBlocks) > 0 { + errAdd := sp.miniBlocksSelectionSession.AddMiniBlocksAndHashes(createIncomingMbsResult.AddedMiniBlocks) + if errAdd != nil { + return nil, errAdd + } + sp.miniBlocksSelectionSession.AddReferencedHeader(currentMetaBlock, currentMetaBlockHash) + lastMeta = currentMetaBlock + } + + if !createIncomingMbsResult.HeaderFinished { break } - lastMeta = currentMetaBlock } return pendingMiniBlocks, nil diff --git a/process/common.go b/process/common.go index 4572a534af2..f7f7a27e8f7 100644 --- a/process/common.go +++ b/process/common.go @@ -1230,9 +1230,15 @@ func CreateDataForInclusionEstimation( var notarizedInRound uint64 switch lastExecutionResult := handler.(type) { case *block.ExecutionResultInfo: + if check.IfNil(lastExecutionResult.GetExecutionResult()) { + return nil, ErrNilBaseExecutionResult + } notarizedInRound = lastExecutionResult.GetNotarizedInRound() proposedInRound = lastExecutionResult.GetExecutionResult().HeaderRound case *block.MetaExecutionResultInfo: + if check.IfNil(lastExecutionResult.GetExecutionResult()) { + return nil, ErrNilBaseExecutionResult + } notarizedInRound = lastExecutionResult.GetNotarizedInRound() proposedInRound = lastExecutionResult.GetExecutionResult().GetHeaderRound() default: From 89e0745131461adc65d2984923005069c1624c6b Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 27 Oct 2025 16:07:35 +0200 Subject: [PATCH 25/51] add new unit tests & fix after refactor --- consensus/broadcast/delayedBroadcast_test.go | 2 - .../vm/wasm/wasmvm/wasmVM_test.go | 1 - .../transactionsFeeProcessor_test.go | 8 +- process/block/metablockProposal_test.go | 393 +++++++++++++++++- process/block/shardblockProposal_test.go | 15 +- 5 files changed, 405 insertions(+), 14 deletions(-) diff --git a/consensus/broadcast/delayedBroadcast_test.go b/consensus/broadcast/delayedBroadcast_test.go index 961bc0efcc9..a161b27ac42 100644 --- a/consensus/broadcast/delayedBroadcast_test.go +++ b/consensus/broadcast/delayedBroadcast_test.go @@ -333,7 +333,6 @@ func TestDelayedBlockBroadcaster_HeaderReceivedWithoutSignaturesForShardShouldNo require.Nil(t, err) originalLogPattern := logger.GetLogLevelPattern() - err = logger.SetLogLevel("*:TRACE") require.Nil(t, err) defer func() { @@ -602,7 +601,6 @@ func TestDelayedBlockBroadcaster_SetHeaderForValidatorWithoutSignaturesShouldNot require.Nil(t, err) originalLogPattern := logger.GetLogLevelPattern() - err = logger.SetLogLevel("*:TRACE") require.Nil(t, err) defer func() { diff --git a/integrationTests/vm/wasm/wasmvm/wasmVM_test.go b/integrationTests/vm/wasm/wasmvm/wasmVM_test.go index c0416a4a4e7..b8b826a20b0 100644 --- a/integrationTests/vm/wasm/wasmvm/wasmVM_test.go +++ b/integrationTests/vm/wasm/wasmvm/wasmVM_test.go @@ -973,7 +973,6 @@ func TestCommunityContract_CrossShard_TxProcessor(t *testing.T) { parentCode := codePath + "/parent_old.wasm" logger.ToggleLoggerName(true) - // logger.SetLogLevel("*:TRACE") // Deploy Funder SC in shard 0 funderOwnerAccount, _ := testContextFunderSC.Accounts.LoadAccount(funderOwner) diff --git a/outport/process/transactionsfee/transactionsFeeProcessor_test.go b/outport/process/transactionsfee/transactionsFeeProcessor_test.go index d4801d88208..5f77eaf2290 100644 --- a/outport/process/transactionsfee/transactionsFeeProcessor_test.go +++ b/outport/process/transactionsfee/transactionsFeeProcessor_test.go @@ -10,6 +10,8 @@ import ( outportcore "github.com/multiversx/mx-chain-core-go/data/outport" "github.com/multiversx/mx-chain-core-go/data/smartContractResult" "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/outport/mock" "github.com/multiversx/mx-chain-go/process" @@ -19,8 +21,6 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/epochNotifier" "github.com/multiversx/mx-chain-go/testscommon/genericMocks" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" - logger "github.com/multiversx/mx-chain-logger-go" - "github.com/stretchr/testify/require" ) var pubKeyConverter, _ = pubkeyConverter.NewBech32PubkeyConverter(32, "erd") @@ -416,8 +416,6 @@ func silentDecodeAddress(address string) []byte { func TestPutFeeAndGasUsedScrWithRefundNoTx(t *testing.T) { t.Parallel() - _ = logger.SetLogLevel("*:TRACE") - txHash := []byte("relayedTx") scrWithRefund := []byte("scrWithRefund") @@ -446,6 +444,8 @@ func TestPutFeeAndGasUsedScrWithRefundNoTx(t *testing.T) { wasCalled := false txsFeeProc, err := NewTransactionsFeeProcessor(arg) + require.Nil(t, err) + txsFeeProc.log = &testscommon.LoggerStub{ TraceCalled: func(message string, args ...interface{}) { wasCalled = true diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index c964434adef..fd15549e696 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -9,10 +9,13 @@ import ( "github.com/stretchr/testify/require" "github.com/multiversx/mx-chain-go/common" + retriever "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/process" blproc "github.com/multiversx/mx-chain-go/process/block" + "github.com/multiversx/mx-chain-go/process/block/processedMb" "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/testscommon" + dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/executionTrack" "github.com/multiversx/mx-chain-go/testscommon/mbSelection" "github.com/multiversx/mx-chain-go/testscommon/processMocks" @@ -42,11 +45,14 @@ func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { return true }, GetLastExecutionResultHandlerCalled: func() data.LastExecutionResultHandler { - return &block.MetaExecutionResultInfo{} + return &block.MetaExecutionResultInfo{ + ExecutionResult: &block.BaseMetaExecutionResult{}, + } }, } validMetaExecutionResultsWithEpochChange := []data.BaseExecutionResultHandler{ &block.MetaExecutionResult{ + ExecutionResult: &block.BaseMetaExecutionResult{}, MiniBlockHeaders: []block.MiniBlockHeader{ { Hash: []byte("mb hash"), @@ -58,6 +64,7 @@ func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { } validMetaExecutionResultsWithoutEpochChange := []data.BaseExecutionResultHandler{ &block.MetaExecutionResult{ + ExecutionResult: &block.BaseMetaExecutionResult{}, MiniBlockHeaders: []block.MiniBlockHeader{ { Hash: []byte("mb hash"), @@ -216,7 +223,9 @@ func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { metaBlockWithInvalidExecutionResult := validMetaHeaderV3 metaBlockWithInvalidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { return []data.BaseExecutionResultHandler{ - &block.ExecutionResult{}, // invalid for meta block + &block.ExecutionResult{ + BaseExecutionResult: &block.BaseExecutionResult{}, + }, // invalid for meta block } } @@ -260,6 +269,7 @@ func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { metaBlockWithValidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { return []data.BaseExecutionResultHandler{ &block.MetaExecutionResult{ + ExecutionResult: &block.BaseMetaExecutionResult{}, MiniBlockHeaders: []block.MiniBlockHeader{ { Hash: []byte("mb hash"), @@ -1115,12 +1125,385 @@ func TestMetaProcessor_selectIncomingMiniBlocks(t *testing.T) { require.Nil(t, err) lastShardHeaders := createLastShardHeadersNotGenesis() - orederdHeaders := []data.HeaderHandler{} - orderedHeaderHashes := [][]byte{} + var orderedHeaders []data.HeaderHandler + var orderedHeaderHashes [][]byte maxNumHeadersFromSameShard := uint32(2) - err = mp.SelectIncomingMiniBlocks(lastShardHeaders, orederdHeaders, orderedHeaderHashes, maxNumHeadersFromSameShard, haveTimeTrue) + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, orderedHeaders, orderedHeaderHashes, maxNumHeadersFromSameShard, haveTimeTrue) + require.Nil(t, err) + }) + + t.Run("time is up before processing any header", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + // ensure proofs exist but haveTime will stop immediately + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + addRefCnt := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { + addRefCnt++ + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h := &testscommon.HeaderHandlerStub{ + GetShardIDCalled: func() uint32 { return 0 }, + GetNonceCalled: func() uint64 { return 11 }, + GetMiniBlockHeadersWithDstCalled: func(destId uint32) map[string]uint32 { return map[string]uint32{"x": 1} }, + } + orderedHeaders := []data.HeaderHandler{h} + orderedHeaderHashes := [][]byte{[]byte("h1")} + + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, orderedHeaders, orderedHeaderHashes, 2, haveTimeFalse) + require.Nil(t, err) + require.Equal(t, 0, addRefCnt) + }) + + t.Run("maximum shard headers allowed in one meta block reached (max=0)", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + called := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { called++ }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h := &testscommon.HeaderHandlerStub{ + GetShardIDCalled: func() uint32 { return 0 }, + GetNonceCalled: func() uint64 { return 11 }, + GetMiniBlockHeadersWithDstCalled: func(destId uint32) map[string]uint32 { return map[string]uint32{"x": 1} }, + } + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{[]byte("h1")}, 0, haveTimeTrue) + require.Nil(t, err) + require.Equal(t, 0, called) + }) + + t.Run("skip header due to nonce gap", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + cntAddRef := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + // last nonce for shard 0 is 10 -> header has 12 so gap > 1 triggers continue + h := &testscommon.HeaderHandlerStub{ + GetShardIDCalled: func() uint32 { return 0 }, + GetNonceCalled: func() uint64 { return 12 }, + GetMiniBlockHeadersWithDstCalled: func(destId uint32) map[string]uint32 { return map[string]uint32{"x": 1} }, + } + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{[]byte("h1")}, 2, haveTimeTrue) + require.Nil(t, err) + require.Equal(t, 0, cntAddRef) + }) + + t.Run("skip header due to per-shard limit", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + cntAddRef := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h1 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + h2 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 12 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h1, h2}, [][]byte{[]byte("h1"), []byte("h2")}, 1, haveTimeTrue) + require.Nil(t, err) + // only first header should be referenced + require.Equal(t, 1, cntAddRef) + // last shard header nonce for shard 0 should remain 11 due to per-shard limit preventing second update + require.Equal(t, uint64(11), lastShardHeaders[0].Header.GetNonce()) + }) + + t.Run("skip header due to missing proof", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return false }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + cntAddRef := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{[]byte("h1")}, 2, haveTimeTrue) + require.Nil(t, err) + require.Equal(t, 0, cntAddRef) + }) + + t.Run("no cross mini blocks with dst me -> add referenced header only", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + cntAddRef := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{[]byte("h1")}, 2, haveTimeTrue) + require.Nil(t, err) + require.Equal(t, 1, cntAddRef) + // last shard header updated and marked used + require.True(t, lastShardHeaders[0].UsedInBlock) + require.Equal(t, []byte("h1"), lastShardHeaders[0].Hash) + }) + + t.Run("createMbsCrossShardDstMe returns error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.TxCoordinator = &testscommon.TransactionCoordinatorMock{ + CreateMbsCrossShardDstMeCalled: func(header data.HeaderHandler, processedMiniBlocksInfo map[string]*processedMb.ProcessedMiniBlockInfo) ([]block.MiniblockAndHash, []block.MiniblockAndHash, uint32, bool, error) { + return nil, nil, 0, false, expectedErr + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h := &testscommon.HeaderHandlerStub{ + GetShardIDCalled: func() uint32 { return 0 }, + GetNonceCalled: func() uint64 { return 11 }, + GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{"mb": 1} }, + } + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{[]byte("h1")}, 2, haveTimeTrue) + require.Equal(t, expectedErr, err) + }) + + t.Run("pending mini blocks returned -> break without adding header", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + cntAddRef := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }} + arguments.TxCoordinator = &testscommon.TransactionCoordinatorMock{ + CreateMbsCrossShardDstMeCalled: func(header data.HeaderHandler, processedMiniBlocksInfo map[string]*processedMb.ProcessedMiniBlockInfo) ([]block.MiniblockAndHash, []block.MiniblockAndHash, uint32, bool, error) { + return nil, []block.MiniblockAndHash{{}}, 0, false, nil + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h1 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{"mb": 1} }} + h2 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 12 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{"mb": 1} }} + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h1, h2}, [][]byte{[]byte("h1"), []byte("h2")}, 2, haveTimeTrue) + require.Nil(t, err) + require.Equal(t, 0, cntAddRef) + // ensure second header was not processed due to break after first + require.Equal(t, uint64(10), lastShardHeaders[0].Header.GetNonce()) + }) + + t.Run("success: miniblocks added and header referenced", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(shardID uint32, headerHash []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + cntAddRef := 0 + cntAddMbs := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + AddMiniBlocksAndHashesCalled: func(miniBlocksAndHashes []block.MiniblockAndHash) error { cntAddMbs++; return nil }, + } + arguments.TxCoordinator = &testscommon.TransactionCoordinatorMock{ + CreateMbsCrossShardDstMeCalled: func(header data.HeaderHandler, processedMiniBlocksInfo map[string]*processedMb.ProcessedMiniBlockInfo) ([]block.MiniblockAndHash, []block.MiniblockAndHash, uint32, bool, error) { + return []block.MiniblockAndHash{{}}, nil, 3, true, nil + }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{"mb": 1} }} + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{[]byte("h1")}, 2, haveTimeTrue) + require.Nil(t, err) + require.Equal(t, 1, cntAddMbs) + require.Equal(t, 1, cntAddRef) + // last shard header updated and marked used + require.True(t, lastShardHeaders[0].UsedInBlock) + require.Equal(t, []byte("h1"), lastShardHeaders[0].Hash) + }) +} + +func TestMetaProcessor_selectIncomingMiniBlocks_GapsAndDuplicates(t *testing.T) { + t.Parallel() + + // helper to build a MetaProcessor with proofs pool behavior + type metaSel interface { + SelectIncomingMiniBlocks(lastShardHdr map[uint32]blproc.ShardHeaderInfo, orderedHdrs []data.HeaderHandler, orderedHdrsHashes [][]byte, maxNumHeadersFromSameShard uint32, haveTime func() bool) error + } + buildMp := func(hasProofFn func(shardID uint32, headerHash []byte) bool) metaSel { + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: hasProofFn} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + return mp + } + + t.Run("inconsistent ordered headers and hashes lengths -> error", func(t *testing.T) { + t.Parallel() + + mp := buildMp(func(uint32, []byte) bool { return true }) + lastShardHeaders := createLastShardHeadersNotGenesis() + h := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + err := mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{}, 2, haveTimeTrue) + require.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) + }) + + t.Run("missing last shard header for ordered header -> error", func(t *testing.T) { + t.Parallel() + + mp := buildMp(func(uint32, []byte) bool { return true }) + lastShardHeaders := createLastShardHeadersNotGenesis() + // header from shard 99, not present in lastShardHeaders map + h := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 99 }, GetNonceCalled: func() uint64 { return 1 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + err := mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h}, [][]byte{[]byte("h1")}, 2, haveTimeTrue) + require.Equal(t, process.ErrMissingHeader, err) + }) + + t.Run("duplicate nonce: first has proof accepted, second skipped", func(t *testing.T) { + t.Parallel() + + cntAddRef := 0 + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(uint32, []byte) bool { return true }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h1 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + h2 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h1, h2}, [][]byte{[]byte("h1"), []byte("h2")}, 2, haveTimeTrue) + require.Nil(t, err) + require.Equal(t, 1, cntAddRef) + // last shard header updated to first hash and used + require.True(t, lastShardHeaders[0].UsedInBlock) + require.Equal(t, []byte("h1"), lastShardHeaders[0].Hash) + }) + + t.Run("duplicate nonce: first missing proof skipped, second with proof accepted", func(t *testing.T) { + t.Parallel() + + cntAddRef := 0 + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + pools := dataComponents.DataPool + if ph, ok := pools.(*dataRetrieverMock.PoolsHolderStub); ok { + ph.ProofsCalled = func() retriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{HasProofCalled: func(_ uint32, hash []byte) bool { return string(hash) == "h2" }} + } + } + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + } + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + lastShardHeaders := createLastShardHeadersNotGenesis() + h1 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + h2 := &testscommon.HeaderHandlerStub{GetShardIDCalled: func() uint32 { return 0 }, GetNonceCalled: func() uint64 { return 11 }, GetMiniBlockHeadersWithDstCalled: func(uint32) map[string]uint32 { return map[string]uint32{} }} + err = mp.SelectIncomingMiniBlocks(lastShardHeaders, []data.HeaderHandler{h1, h2}, [][]byte{[]byte("h1"), []byte("h2")}, 2, haveTimeTrue) require.Nil(t, err) + require.Equal(t, 1, cntAddRef) + // last shard header updated to second hash and used + require.True(t, lastShardHeaders[0].UsedInBlock) + require.Equal(t, []byte("h2"), lastShardHeaders[0].Hash) }) } diff --git a/process/block/shardblockProposal_test.go b/process/block/shardblockProposal_test.go index 168830b24db..17b13e06722 100644 --- a/process/block/shardblockProposal_test.go +++ b/process/block/shardblockProposal_test.go @@ -221,6 +221,7 @@ func TestShardProcessor_CreateBlockProposal(t *testing.T) { arguments.BlockTracker = &mock.BlockTrackerMock{ ComputeLongestMetaChainFromLastNotarizedCalled: func() ([]data.HeaderHandler, [][]byte, error) { return []data.HeaderHandler{&block.MetaBlockV3{ + Nonce: 1, ShardInfo: []block.ShardData{ { ShardID: 1, @@ -535,8 +536,10 @@ func TestShardProcessor_CreateBlockProposal(t *testing.T) { arguments.BlockTracker = &mock.BlockTrackerMock{ ComputeLongestMetaChainFromLastNotarizedCalled: func() ([]data.HeaderHandler, [][]byte, error) { return []data.HeaderHandler{&block.MetaBlockV3{ + Nonce: 1, ShardInfo: []block.ShardData{ { + Nonce: 0, ShardID: 1, ShardMiniBlockHeaders: []block.MiniBlockHeader{ { @@ -547,6 +550,7 @@ func TestShardProcessor_CreateBlockProposal(t *testing.T) { }, // for extra coverage, should be skipped as it is empty { + Nonce: 1, ShardID: 1, ShardMiniBlockHeaders: []block.MiniBlockHeader{}, }, @@ -554,12 +558,15 @@ func TestShardProcessor_CreateBlockProposal(t *testing.T) { MiniBlockHeaders: []block.MiniBlockHeader{ {}, }, - }}, + }, &block.MetaBlockV3{Nonce: 2}, + }, [][]byte{[]byte("hash_ok"), []byte("hash_empty")}, nil }, GetLastCrossNotarizedHeaderCalled: func(shardID uint32) (data.HeaderHandler, []byte, error) { - return &block.MetaBlockV3{}, []byte("hash"), nil // dummy + return &block.MetaBlockV3{ + Nonce: 0, + }, []byte("hash"), nil // dummy }, } providedMb := &block.MiniBlock{ @@ -2429,6 +2436,10 @@ func TestShardProcessor_OnProposedBlock(t *testing.T) { } } arguments := CreateMockArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + cntAddRef := 0 + arguments.MiniBlocksSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{ + AddReferencedHeaderCalled: func(metaBlock data.HeaderHandler, metaBlockHash []byte) { cntAddRef++ }, + } sp, err := blproc.NewShardProcessor(arguments) require.Nil(t, err) From bb8ba06cdc3c212cdf78add76ec2751c47906d7e Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 27 Oct 2025 16:22:40 +0200 Subject: [PATCH 26/51] fixes --- consensus/broadcast/delayedBroadcast_test.go | 2 ++ process/block/shardInfo.go | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/consensus/broadcast/delayedBroadcast_test.go b/consensus/broadcast/delayedBroadcast_test.go index a161b27ac42..961bc0efcc9 100644 --- a/consensus/broadcast/delayedBroadcast_test.go +++ b/consensus/broadcast/delayedBroadcast_test.go @@ -333,6 +333,7 @@ func TestDelayedBlockBroadcaster_HeaderReceivedWithoutSignaturesForShardShouldNo require.Nil(t, err) originalLogPattern := logger.GetLogLevelPattern() + err = logger.SetLogLevel("*:TRACE") require.Nil(t, err) defer func() { @@ -601,6 +602,7 @@ func TestDelayedBlockBroadcaster_SetHeaderForValidatorWithoutSignaturesShouldNot require.Nil(t, err) originalLogPattern := logger.GetLogLevelPattern() + err = logger.SetLogLevel("*:TRACE") require.Nil(t, err) defer func() { diff --git a/process/block/shardInfo.go b/process/block/shardInfo.go index 9e5cacfb110..c4fff54954d 100644 --- a/process/block/shardInfo.go +++ b/process/block/shardInfo.go @@ -61,6 +61,9 @@ func (sic *ShardInfoCreateData) CreateShardInfoV3( shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte, ) ([]data.ShardDataHandler, error) { + if check.IfNil(metaHeader) { + return nil, process.ErrNilHeaderHandler + } if !metaHeader.IsHeaderV3() { return nil, process.ErrInvalidHeader } @@ -87,6 +90,9 @@ func (sic *ShardInfoCreateData) CreateShardInfoFromLegacyMeta( shardHeaders []data.ShardHeaderHandler, shardHeaderHashes [][]byte, ) ([]data.ShardDataHandler, error) { + if check.IfNil(metaHeader) { + return nil, process.ErrNilHeaderHandler + } if metaHeader.IsHeaderV3() { return nil, process.ErrInvalidHeader } @@ -184,7 +190,6 @@ func (sic *ShardInfoCreateData) createShardDataFromExecutionResult( return nil, process.ErrWrongTypeAssertion } - execResultHandler.GetMiniBlockHeadersHandlers() header, err := sic.headersPool.GetHeaderByHash(execResultHandler.GetHeaderHash()) if err != nil { return nil, err @@ -235,7 +240,7 @@ func createShardMiniBlockHeaderFromExecutionResultHandler( execResultHandler data.ExecutionResultHandler, ) []block.MiniBlockHeader { mbHeaderHandlers := execResultHandler.GetMiniBlockHeadersHandlers() - shardMiniBlockHeaders := make([]block.MiniBlockHeader, 0) + shardMiniBlockHeaders := make([]block.MiniBlockHeader, 0, len(mbHeaderHandlers)) for i := 0; i < len(mbHeaderHandlers); i++ { shardMiniBlockHeader := miniBlockHeaderFromMiniBlockHeaderHandler(mbHeaderHandlers[i]) shardMiniBlockHeaders = append(shardMiniBlockHeaders, shardMiniBlockHeader) From 914f6289e43c4254fe444d99a0c12561f4c1ee27 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 27 Oct 2025 16:40:10 +0200 Subject: [PATCH 27/51] fix ineffectual assignment --- process/block/baseProcess_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/process/block/baseProcess_test.go b/process/block/baseProcess_test.go index 5c1da3f3105..42cdb41f34f 100644 --- a/process/block/baseProcess_test.go +++ b/process/block/baseProcess_test.go @@ -64,7 +64,6 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/mainFactoryMocks" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" "github.com/multiversx/mx-chain-go/testscommon/outport" - "github.com/multiversx/mx-chain-go/testscommon/preprocMocks" "github.com/multiversx/mx-chain-go/testscommon/shardingMocks" stateMock "github.com/multiversx/mx-chain-go/testscommon/state" statusHandlerMock "github.com/multiversx/mx-chain-go/testscommon/statusHandler" @@ -132,7 +131,6 @@ func createArgBaseProcessor( var execResultsVerifier blproc.ExecutionResultsVerifier var missingDataResolver blproc.MissingDataResolver if check.IfNil(dataComponents) || check.IfNil(dataComponents.Datapool()) || check.IfNil(coreComponents) || check.IfNil(bootstrapComponents) { - blockDataRequester = &preprocMocks.BlockDataRequesterStub{} inclusionEstimator = &processMocks.InclusionEstimatorMock{} mbSelectionSession = &mbSelection.MiniBlockSelectionSessionStub{} execResultsVerifier = &processMocks.ExecutionResultsVerifierMock{} From f8cd2629577ed6677c5e745b76d6a4502014287a Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 27 Oct 2025 16:41:43 +0200 Subject: [PATCH 28/51] remove redundant types --- process/block/baseProcess_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/process/block/baseProcess_test.go b/process/block/baseProcess_test.go index 42cdb41f34f..c9b779dedda 100644 --- a/process/block/baseProcess_test.go +++ b/process/block/baseProcess_test.go @@ -3743,14 +3743,14 @@ func TestBaseProcessor_GetFinalMiniBlocksFromExecutionResult(t *testing.T) { bp, _ := blproc.NewShardProcessor(arguments) executionResults := []*block.ExecutionResult{ - &block.ExecutionResult{ + { MiniBlockHeaders: []block.MiniBlockHeader{ - block.MiniBlockHeader{ + { Hash: []byte("mbHash1"), ReceiverShardID: 1, SenderShardID: 0, }, - block.MiniBlockHeader{ + { Hash: []byte("mbHash2"), ReceiverShardID: 1, SenderShardID: 0, @@ -3788,9 +3788,9 @@ func TestBaseProcessor_GetFinalMiniBlocksFromExecutionResult(t *testing.T) { bp, _ := blproc.NewShardProcessor(arguments) executionResults := []*block.ExecutionResult{ - &block.ExecutionResult{ + { MiniBlockHeaders: []block.MiniBlockHeader{ - block.MiniBlockHeader{ + { Hash: []byte("mbHash1"), ReceiverShardID: 1, SenderShardID: 0, @@ -3840,9 +3840,9 @@ func TestBaseProcessor_GetFinalMiniBlocksFromExecutionResult(t *testing.T) { bp, _ := blproc.NewShardProcessor(arguments) executionResults := []*block.ExecutionResult{ - &block.ExecutionResult{ + { MiniBlockHeaders: []block.MiniBlockHeader{ - block.MiniBlockHeader{ + { Hash: []byte("mbHash1"), ReceiverShardID: 1, SenderShardID: 0, From a79b5f958aa65f2234c4961c8a23c63ca023a1b1 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Mon, 27 Oct 2025 21:19:33 +0200 Subject: [PATCH 29/51] MX-17245 Added coverage for create shard data legacy & v3 --- process/block/shardinfo_test.go | 213 +++++++++++++++++++++++++++++++- 1 file changed, 210 insertions(+), 3 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 4784c42647a..9d0c3a759e2 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -118,6 +118,195 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { }) } +func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { + t.Parallel() + +} + +func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { + t.Parallel() + + t.Run("should fail with updateShardDataWithCrossShardInfo error", func(t *testing.T) { + t.Parallel() + header := getShardHeaderForShard1() + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return nil, nil, fmt.Errorf("GetLastSelfNotarizedHeader error") + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return false + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) + require.NotNil(t, err) + require.Nil(t, shardData) + }) + + t.Run("should work with enable epoch flag disabled", func(t *testing.T) { + t.Parallel() + header := getShardHeaderForShard1() + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: header.GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return false + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) + require.Nil(t, err) + require.NotNil(t, shardData) + require.Equal(t, 1, len(shardData)) + require.Equal(t, header.GetNonce(), shardData[0].GetNonce()) + require.Equal(t, uint32(0), shardData[0].(*block.ShardData).GetEpoch()) + }) + t.Run("should work with enable epoch flag enabled", func(t *testing.T) { + t.Parallel() + header := getShardHeaderForShard1() + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: header.GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) + require.Nil(t, err) + require.NotNil(t, shardData) + require.Equal(t, 1, len(shardData)) + require.Equal(t, header.GetNonce(), shardData[0].GetNonce()) + require.Equal(t, header.GetEpoch(), shardData[0].(*block.ShardData).GetEpoch()) + }) +} +func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { + t.Parallel() + + t.Run("should fail with nil header", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromV3Header(nil) + require.NotNil(t, err) + require.Nil(t, shardData) + require.ErrorIs(t, err, process.ErrNilHeaderHandler) + }) + t.Run("should return early if no execution results", func(t *testing.T) { + t.Parallel() + header := &block.HeaderV3{ + Nonce: 0, + } + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromV3Header(header) + require.Nil(t, err) + require.NotNil(t, shardData) + require.Equal(t, 0, len(shardData)) + }) + t.Run("should fail with createShardDataFromExecutionResult error", func(t *testing.T) { + t.Parallel() + expectedNonce := uint64(12345) + header := getHeaderV3ForShard1() + args := createDefaultShardInfoCreateDataArgs() + // GetHeaderByHash error will fail createShardDataFromExecutionResult + args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + return nil, fmt.Errorf("GetHeaderByHash error") + } + + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromV3Header(header) + require.NotNil(t, err) + require.Nil(t, shardData) + require.Equal(t, fmt.Errorf("GetHeaderByHash error"), err) + }) + + t.Run("should work", func(t *testing.T) { + t.Parallel() + expectedNonce := uint64(12345) + header := getHeaderV3ForShard1() + args := createDefaultShardInfoCreateDataArgs() + args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + return header, nil + } + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardDataFromV3Header(header) + require.Nil(t, err) + require.NotNil(t, shardData) + require.Equal(t, 1, len(shardData)) + require.Equal(t, expectedNonce, shardData[0].GetNonce()) + }) +} + func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { t.Parallel() @@ -229,15 +418,16 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { assert.Equal(t, uint32(2), shardData.GetNumPendingMiniBlocks()) assert.Equal(t, uint32(execResult.GetExecutedTxCount()), shardData.GetTxCount()) assert.Equal(t, uint32(1), shardData.GetShardID()) - assert.Equal(t, shardData.GetAccumulatedFees(), execResult.GetAccumulatedFees()) + assert.Equal(t, execResult.GetAccumulatedFees(), shardData.GetAccumulatedFees()) assert.Equal(t, execResult.GetHeaderHash(), shardData.GetHeaderHash()) assert.Equal(t, execResult.GetHeaderRound(), shardData.GetRound()) assert.Equal(t, header.GetPrevHash(), shardData.GetPrevHash()) assert.Equal(t, execResult.GetHeaderNonce(), shardData.GetNonce()) assert.Equal(t, header.GetPrevRandSeed(), shardData.GetPrevRandSeed()) assert.Equal(t, header.GetPubKeysBitmap(), shardData.GetPubKeysBitmap()) - assert.Equal(t, shardData.GetAccumulatedFees(), execResult.GetAccumulatedFees()) - assert.Equal(t, shardData.GetDeveloperFees(), execResult.GetDeveloperFees()) + assert.Equal(t, execResult.GetAccumulatedFees(), shardData.GetAccumulatedFees()) + assert.Equal(t, execResult.GetDeveloperFees(), shardData.GetDeveloperFees()) + require.Equal(t, header.GetEpoch(), shardData.(*block.ShardData).GetEpoch()) }) } @@ -434,6 +624,23 @@ func getShardHeaderForShard1() data.HeaderHandler { } } +func getHeaderV3ForShard1() data.HeaderHandler { + prevHash := []byte("prevHash") + prevRandSeed := []byte("prevRandSeed") + currRandSeed := []byte("currRandSeed") + return &block.HeaderV3{ + Epoch: 7, + Round: 10, + Nonce: 45, + ShardID: 1, + PrevRandSeed: prevRandSeed, + RandSeed: currRandSeed, + PrevHash: prevHash, + MiniBlockHeaders: getMiniBlockHeadersForShard1(), + ExecutionResults: []*block.ExecutionResult{getExecutionResultForShard1()}, + } +} + func getExecutionResultForShard1() *block.ExecutionResult { return &block.ExecutionResult{ From 56aa5111a744083d6d0fe9745f631b000916de05 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Mon, 27 Oct 2025 23:24:05 +0200 Subject: [PATCH 30/51] MX-17245 Added cunit test for CreateShardInfoFromLegacyMeta, CreateShardInfoFromHeader --- process/block/shardinfo_test.go | 392 +++++++++++++++++++++++++++++--- 1 file changed, 366 insertions(+), 26 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 9d0c3a759e2..4418546f279 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -10,7 +10,7 @@ import ( "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/mock" - "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" + dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/pool" "github.com/stretchr/testify/assert" @@ -118,9 +118,349 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { }) } +func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { + t.Parallel() + + pool := dataRetrieverMock.NewPoolsHolderMock() + // we will have a 3 hdrs in pool + hdrHash1 := []byte("hdr hash 1") + hdrHash2 := []byte("hdr hash 2") + hdrHash3 := []byte("hdr hash 3") + + mbHash1 := []byte("mb hash 1") + mbHash2 := []byte("mb hash 2") + mbHash3 := []byte("mb hash 3") + + miniBlockHeader1 := block.MiniBlockHeader{Hash: mbHash1} + miniBlockHeader2 := block.MiniBlockHeader{Hash: mbHash2} + miniBlockHeader3 := block.MiniBlockHeader{Hash: mbHash3} + + miniBlockHeaders1 := make([]block.MiniBlockHeader, 0) + miniBlockHeaders1 = append(miniBlockHeaders1, miniBlockHeader1) + miniBlockHeaders1 = append(miniBlockHeaders1, miniBlockHeader2) + miniBlockHeaders1 = append(miniBlockHeaders1, miniBlockHeader3) + + miniBlockHeaders2 := make([]block.MiniBlockHeader, 0) + miniBlockHeaders2 = append(miniBlockHeaders2, miniBlockHeader1) + miniBlockHeaders2 = append(miniBlockHeaders2, miniBlockHeader2) + + miniBlockHeaders3 := make([]block.MiniBlockHeader, 0) + miniBlockHeaders3 = append(miniBlockHeaders3, miniBlockHeader1) + + header1 := &block.Header{ + Round: 1, + Nonce: 45, + ShardID: 0, + MiniBlockHeaders: miniBlockHeaders1} + header2 := &block.Header{ + Round: 2, + Nonce: 45, + ShardID: 1, + MiniBlockHeaders: miniBlockHeaders2} + header3 := &block.Header{ + Round: 3, + Nonce: 45, + ShardID: 2, + MiniBlockHeaders: miniBlockHeaders3} + // put the existing headers inside datapool + pool.Headers().AddHeader(hdrHash1, header1) + pool.Headers().AddHeader(hdrHash2, header2) + pool.Headers().AddHeader(hdrHash3, header3) + + headerHashes := make([][]byte, 0) + headers := make([]data.ShardHeaderHandler, 0) + headers = append(headers, []data.ShardHeaderHandler{header1, header2, header3}...) + headerHashes = append(headerHashes, [][]byte{hdrHash1, hdrHash2, hdrHash3}...) + round := uint64(10) + metaHdr := &block.MetaBlock{Round: round} + + t.Run("should fail with V3 meta header", func(t *testing.T) { + t.Parallel() + + args := createDefaultShardInfoCreateDataArgs() + metaHdrV3 := &block.MetaBlockV3{Round: round} + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdrV3, headers, headerHashes) + require.NotNil(t, err) + require.Nil(t, shardInfo) + assert.Equal(t, process.ErrInvalidHeader, err) + }) + t.Run("should fail with inconsistent headers and hashes", func(t *testing.T) { + t.Parallel() + + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdr, headers, headerHashes[:1]) + require.NotNil(t, err) + require.Nil(t, shardInfo) + assert.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) + }) + t.Run("should fail when createShardDataFromLegacyHeader errors", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return nil, nil, fmt.Errorf("GetLastSelfNotarizedHeader error") + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return true + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdr, headers, headerHashes) + require.NotNil(t, err) + require.Nil(t, shardInfo) + }) + t.Run("should work", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: headers[shardID].GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return true + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdr, headers, headerHashes) + require.Nil(t, err) + require.NotNil(t, shardInfo) + require.Equal(t, 3, len(shardInfo)) + }) +} + func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { t.Parallel() + t.Run("should fail with nil header", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + + shardData, err := sic.createShardInfoFromHeader(nil, nil) + require.NotNil(t, err) + require.Nil(t, shardData) + require.ErrorIs(t, err, process.ErrNilHeaderHandler) + }) + t.Run("should fail with invalid hash", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardData, err := sic.createShardInfoFromHeader(&block.Header{}, []byte{}) + require.NotNil(t, err) + require.Nil(t, shardData) + require.ErrorIs(t, err, process.ErrInvalidHash) + }) + + t.Run("should fail with missing shard header proof", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return false + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + + shardData, err := sic.createShardInfoFromHeader(&block.Header{Nonce: 1}, []byte("hash")) + require.NotNil(t, err) + require.Nil(t, shardData) + require.ErrorIs(t, err, process.ErrMissingHeaderProof) + }) + t.Run("should work with Legacy", func(t *testing.T) { + t.Parallel() + header := getShardHeaderForShard1() + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: header.GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return true + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + + shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + require.Nil(t, err) + require.NotNil(t, shardData) + }) + t.Run("should work with Legacy no proof for epoch < 1", func(t *testing.T) { + t.Parallel() + header := getShardHeaderForShard1() + header.(*block.HeaderV2).SetNonce(0) + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: header.GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return false + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + + shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + require.Nil(t, err) + require.NotNil(t, shardData) + }) + t.Run("should work with V3", func(t *testing.T) { + t.Parallel() + header := getHeaderV3ForShard1() + expectedNonce := uint64(12345) + args := createDefaultShardInfoCreateDataArgs() + args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + return header, nil + } + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil + } + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: header.GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return true + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + + shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + require.Nil(t, err) + require.NotNil(t, shardData) + }) + t.Run("should work with V3 no proof for nonce < 1", func(t *testing.T) { + t.Parallel() + header := getHeaderV3ForShard1() + expectedNonce := uint64(0) + header.(*block.HeaderV3).SetNonce(expectedNonce) + args := createDefaultShardInfoCreateDataArgs() + args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + return header, nil + } + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil + } + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: header.GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return false + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + + shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + require.Nil(t, err) + require.NotNil(t, shardData) + }) } func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { @@ -147,9 +487,9 @@ func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardData, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) + shardDataList, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) require.NotNil(t, err) - require.Nil(t, shardData) + require.Nil(t, shardDataList) }) t.Run("should work with enable epoch flag disabled", func(t *testing.T) { @@ -173,12 +513,12 @@ func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardData, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) + shardDataList, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) require.Nil(t, err) - require.NotNil(t, shardData) - require.Equal(t, 1, len(shardData)) - require.Equal(t, header.GetNonce(), shardData[0].GetNonce()) - require.Equal(t, uint32(0), shardData[0].(*block.ShardData).GetEpoch()) + require.NotNil(t, shardDataList) + require.Equal(t, 1, len(shardDataList)) + require.Equal(t, header.GetNonce(), shardDataList[0].GetNonce()) + require.Equal(t, uint32(0), shardDataList[0].(*block.ShardData).GetEpoch()) }) t.Run("should work with enable epoch flag enabled", func(t *testing.T) { t.Parallel() @@ -201,12 +541,12 @@ func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardData, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) + shardDataList, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) require.Nil(t, err) - require.NotNil(t, shardData) - require.Equal(t, 1, len(shardData)) - require.Equal(t, header.GetNonce(), shardData[0].GetNonce()) - require.Equal(t, header.GetEpoch(), shardData[0].(*block.ShardData).GetEpoch()) + require.NotNil(t, shardDataList) + require.Equal(t, 1, len(shardDataList)) + require.Equal(t, header.GetNonce(), shardDataList[0].GetNonce()) + require.Equal(t, header.GetEpoch(), shardDataList[0].(*block.ShardData).GetEpoch()) }) } func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { @@ -223,9 +563,9 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardData, err := sic.createShardDataFromV3Header(nil) + shardDataList, err := sic.createShardDataFromV3Header(nil) require.NotNil(t, err) - require.Nil(t, shardData) + require.Nil(t, shardDataList) require.ErrorIs(t, err, process.ErrNilHeaderHandler) }) t.Run("should return early if no execution results", func(t *testing.T) { @@ -242,10 +582,10 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardData, err := sic.createShardDataFromV3Header(header) + shardDataList, err := sic.createShardDataFromV3Header(header) require.Nil(t, err) - require.NotNil(t, shardData) - require.Equal(t, 0, len(shardData)) + require.NotNil(t, shardDataList) + require.Equal(t, 0, len(shardDataList)) }) t.Run("should fail with createShardDataFromExecutionResult error", func(t *testing.T) { t.Parallel() @@ -271,9 +611,9 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardData, err := sic.createShardDataFromV3Header(header) + shardDataList, err := sic.createShardDataFromV3Header(header) require.NotNil(t, err) - require.Nil(t, shardData) + require.Nil(t, shardDataList) require.Equal(t, fmt.Errorf("GetHeaderByHash error"), err) }) @@ -299,11 +639,11 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardData, err := sic.createShardDataFromV3Header(header) + shardDataList, err := sic.createShardDataFromV3Header(header) require.Nil(t, err) - require.NotNil(t, shardData) - require.Equal(t, 1, len(shardData)) - require.Equal(t, expectedNonce, shardData[0].GetNonce()) + require.NotNil(t, shardDataList) + require.Equal(t, 1, len(shardDataList)) + require.Equal(t, expectedNonce, shardDataList[0].GetNonce()) }) } @@ -557,7 +897,7 @@ func TestShardInfoCreateData_updateShardDataWithCrossShardInfo(t *testing.T) { type shardInfoCreateDataTestArgs struct { headersPool *pool.HeadersPoolStub - proofsPool *dataRetriever.ProofsPoolMock + proofsPool *dataRetrieverMock.ProofsPoolMock pendingMiniBlocksHandler *mock.PendingMiniBlocksHandlerStub blockTracker *mock.BlockTrackerMock enableEpochsHandler *enableEpochsHandlerMock.EnableEpochsHandlerStub @@ -566,7 +906,7 @@ type shardInfoCreateDataTestArgs struct { func createDefaultShardInfoCreateDataArgs() *shardInfoCreateDataTestArgs { return &shardInfoCreateDataTestArgs{ headersPool: &pool.HeadersPoolStub{}, - proofsPool: &dataRetriever.ProofsPoolMock{}, + proofsPool: &dataRetrieverMock.ProofsPoolMock{}, pendingMiniBlocksHandler: &mock.PendingMiniBlocksHandlerStub{}, blockTracker: &mock.BlockTrackerMock{}, enableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), From 8a6574739aeda120f8de95c15a5faa79e4986086 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Tue, 28 Oct 2025 12:33:49 +0200 Subject: [PATCH 31/51] MX-17245 Added unit tests for CreateShardInfoV3 --- process/block/shardinfo_test.go | 198 +++++++++++++++++++++++++------- 1 file changed, 157 insertions(+), 41 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 4418546f279..1f5ff58b2f5 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -118,6 +118,122 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { }) } +func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { + t.Parallel() + + hdrHash0 := []byte("header hash for shard 0") + hdrHash1 := []byte("header hash for shard 1") + hdrHash2 := []byte("header hash for shard 2") + hdrHash3 := []byte("header hash for shard 2 V3") + + header0 := getHeaderV3ForShard(uint32(0), hdrHash0) + header1 := getShardHeaderForShard(uint32(1)) + header2 := getShardHeaderForShard(uint32(2)) + header3 := getHeaderV3ForShard(uint32(2), hdrHash3) + headers := make([]data.HeaderHandler, 0) + headers = append(headers, []data.HeaderHandler{header0, header1, header2, header3}...) + + headerHashes := make([][]byte, 0) + headerHashes = append(headerHashes, [][]byte{hdrHash0, hdrHash1, hdrHash2, hdrHash3}...) + + pool := dataRetrieverMock.NewPoolsHolderMock() + pool.Headers().AddHeader(hdrHash0, header0) + pool.Headers().AddHeader(hdrHash1, header1) + pool.Headers().AddHeader(hdrHash2, header2) + pool.Headers().AddHeader(hdrHash3, header3) + + round := uint64(10) + metaHdrV3 := &block.MetaBlockV3{Round: round} + + t.Run("should fail with Legacy meta header", func(t *testing.T) { + t.Parallel() + + metaHdr := &block.MetaBlock{Round: round} + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoV3(metaHdr, headers, headerHashes[:2]) + require.NotNil(t, err) + require.Nil(t, shardInfo) + assert.Equal(t, process.ErrInvalidHeader, err) + }) + t.Run("should fail with inconsistent headers and hashes", func(t *testing.T) { + t.Parallel() + + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes[:2]) + require.NotNil(t, err) + require.Nil(t, shardInfo) + assert.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) + }) + t.Run("should fail when createShardInfoFromHeader errors", func(t *testing.T) { + t.Parallel() + + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + invalidHashes := make([][]byte, len(headerHashes)) + invalidHashes[0] = []byte("") + shardInfo, err := sic.CreateShardInfoV3(metaHdrV3, headers, invalidHashes) + require.NotNil(t, err) + require.Nil(t, shardInfo) + assert.Equal(t, process.ErrInvalidHash, err) + }) + t.Run("should work", func(t *testing.T) { + t.Parallel() + + expectedNonce := uint64(12345) + args := createDefaultShardInfoCreateDataArgs() + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { + return [][]byte{[]byte("hash1"), []byte("hash2")} + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: headers[shardID].GetNonce()}, []byte("selfNotarizedHash"), nil + } + args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { + return true + } + args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { + return true + } + args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { + return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil + } + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes) + require.Nil(t, err) + require.NotNil(t, shardInfo) + require.Equal(t, 4, len(shardInfo)) + }) +} + func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { t.Parallel() @@ -325,7 +441,7 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { }) t.Run("should work with Legacy", func(t *testing.T) { t.Parallel() - header := getShardHeaderForShard1() + header := getShardHeaderForShard(uint32(1)) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -354,7 +470,7 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { }) t.Run("should work with Legacy no proof for epoch < 1", func(t *testing.T) { t.Parallel() - header := getShardHeaderForShard1() + header := getShardHeaderForShard(uint32(1)) header.(*block.HeaderV2).SetNonce(0) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { @@ -384,7 +500,7 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { }) t.Run("should work with V3", func(t *testing.T) { t.Parallel() - header := getHeaderV3ForShard1() + header := getHeaderV3ForShard(uint32(1), []byte("header hash for shard 1")) expectedNonce := uint64(12345) args := createDefaultShardInfoCreateDataArgs() args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { @@ -423,7 +539,7 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { }) t.Run("should work with V3 no proof for nonce < 1", func(t *testing.T) { t.Parallel() - header := getHeaderV3ForShard1() + header := getHeaderV3ForShard(uint32(1), []byte("header hash for shard 1")) expectedNonce := uint64(0) header.(*block.HeaderV3).SetNonce(expectedNonce) args := createDefaultShardInfoCreateDataArgs() @@ -468,7 +584,7 @@ func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { t.Run("should fail with updateShardDataWithCrossShardInfo error", func(t *testing.T) { t.Parallel() - header := getShardHeaderForShard1() + header := getShardHeaderForShard(uint32(1)) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -494,7 +610,7 @@ func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { t.Run("should work with enable epoch flag disabled", func(t *testing.T) { t.Parallel() - header := getShardHeaderForShard1() + header := getShardHeaderForShard(uint32(1)) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -522,7 +638,7 @@ func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { }) t.Run("should work with enable epoch flag enabled", func(t *testing.T) { t.Parallel() - header := getShardHeaderForShard1() + header := getShardHeaderForShard(uint32(1)) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -590,7 +706,7 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { t.Run("should fail with createShardDataFromExecutionResult error", func(t *testing.T) { t.Parallel() expectedNonce := uint64(12345) - header := getHeaderV3ForShard1() + header := getHeaderV3ForShard(uint32(1), []byte("header hash for shard 1")) args := createDefaultShardInfoCreateDataArgs() // GetHeaderByHash error will fail createShardDataFromExecutionResult args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { @@ -620,7 +736,7 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { t.Run("should work", func(t *testing.T) { t.Parallel() expectedNonce := uint64(12345) - header := getHeaderV3ForShard1() + header := getHeaderV3ForShard(uint32(1), []byte("header hash for shard 1")) args := createDefaultShardInfoCreateDataArgs() args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { return header, nil @@ -700,7 +816,7 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - execResult := getExecutionResultForShard1() + execResult := getExecutionResultForShard(uint32(1), []byte("header hash for shard 1")) shardData, err := sic.createShardDataFromExecutionResult(execResult) require.NotNil(t, err) require.Nil(t, shardData) @@ -711,7 +827,7 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { t.Parallel() args := createDefaultShardInfoCreateDataArgs() args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { - return getShardHeaderForShard1(), nil + return getShardHeaderForShard(uint32(1)), nil } sic, err := NewShardInfoCreateData( @@ -722,7 +838,7 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - execResult := getExecutionResultForShard1() + execResult := getExecutionResultForShard(uint32(1), []byte("header hash for shard 1")) shardData, err := sic.createShardDataFromExecutionResult(execResult) require.NotNil(t, err) require.Nil(t, shardData) @@ -732,7 +848,7 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { t.Run("should work", func(t *testing.T) { t.Parallel() expectedNonce := uint64(1) - header := getShardHeaderForShard1() + header := getShardHeaderForShard(uint32(1)) args := createDefaultShardInfoCreateDataArgs() args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { return header, nil @@ -751,7 +867,7 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - execResult := getExecutionResultForShard1() + execResult := getExecutionResultForShard(uint32(1), []byte("header hash for shard 1")) shardData, err := sic.createShardDataFromExecutionResult(execResult) require.Nil(t, err) require.NotNil(t, shardData) @@ -776,7 +892,7 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { t.Run("ScheduledMiniBlocksFlag disabled", func(t *testing.T) { t.Parallel() - headerHandler := getShardHeaderForShard1() + headerHandler := getShardHeaderForShard(uint32(1)) enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) @@ -785,7 +901,7 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { }) t.Run("ScheduledMiniBlocksFlag enabled, all miniblocks final", func(t *testing.T) { t.Parallel() - headerHandler := getShardHeaderForShard1() + headerHandler := getShardHeaderForShard(uint32(1)) enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { return flag == common.ScheduledMiniBlocksFlag @@ -797,7 +913,7 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { }) t.Run("ScheduledMiniBlocksFlag enabled, not all miniblocks final", func(t *testing.T) { t.Parallel() - headerHandler := getShardHeaderForShard1() + headerHandler := getShardHeaderForShard(uint32(1)) enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { return flag == common.ScheduledMiniBlocksFlag @@ -811,7 +927,7 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { }) t.Run("ScheduledMiniBlocksFlag enabled, no final miniblocks", func(t *testing.T) { t.Parallel() - headerHandler := getShardHeaderForShard1() + headerHandler := getShardHeaderForShard(uint32(1)) enableEpochsHandler := enableEpochsHandlerMock.NewEnableEpochsHandlerStub() enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool { return flag == common.ScheduledMiniBlocksFlag @@ -831,7 +947,7 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { func TestShardInfoCreateData_createShardMiniBlockHeaderFromExecutionResultHandler(t *testing.T) { t.Parallel() - execResultHandler := getExecutionResultForShard1() + execResultHandler := getExecutionResultForShard(uint32(1), []byte("header hash for shard 1")) shardMiniBlockHeaders := createShardMiniBlockHeaderFromExecutionResultHandler(execResultHandler) require.NotNil(t, shardMiniBlockHeaders) require.Equal(t, 3, len(shardMiniBlockHeaders)) @@ -913,30 +1029,30 @@ func createDefaultShardInfoCreateDataArgs() *shardInfoCreateDataTestArgs { } } -func getMiniBlockHeadersForShard1() []block.MiniBlockHeader { - mbHash1 := []byte("mb hash 1") - mbHash2 := []byte("mb hash 2") - mbHash3 := []byte("mb hash 3") +func getMiniBlockHeadersForShard(shardID uint32) []block.MiniBlockHeader { + mbHash1 := []byte(fmt.Sprintf("mb hash 1 for shard %d", shardID)) + mbHash2 := []byte(fmt.Sprintf("mb hash 2 for shard %d", shardID)) + mbHash3 := []byte(fmt.Sprintf("mb hash 3 for shard %d", shardID)) miniBlockHeader1 := block.MiniBlockHeader{ Hash: mbHash1, Type: block.TxBlock, TxCount: 10, - SenderShardID: 1, + SenderShardID: shardID, ReceiverShardID: 2, } miniBlockHeader2 := block.MiniBlockHeader{ Hash: mbHash2, Type: block.InvalidBlock, TxCount: 1, - SenderShardID: 1, + SenderShardID: shardID, ReceiverShardID: 2, } miniBlockHeader3 := block.MiniBlockHeader{ Hash: mbHash3, Type: block.SmartContractResultBlock, TxCount: 5, - SenderShardID: 1, + SenderShardID: shardID, ReceiverShardID: 0, } @@ -947,10 +1063,10 @@ func getMiniBlockHeadersForShard1() []block.MiniBlockHeader { return miniBlockHeaders } -func getShardHeaderForShard1() data.HeaderHandler { - prevHash := []byte("prevHash") - prevRandSeed := []byte("prevRandSeed") - currRandSeed := []byte("currRandSeed") +func getShardHeaderForShard(shardID uint32) data.HeaderHandler { + prevHash := []byte(fmt.Sprintf("prevHash for shard %d", shardID)) + prevRandSeed := []byte(fmt.Sprintf("prevRandSeed for shard %d", shardID)) + currRandSeed := []byte(fmt.Sprintf("currRandSeed for shard %d", shardID)) return &block.HeaderV2{ Header: &block.Header{ Round: 10, @@ -959,15 +1075,15 @@ func getShardHeaderForShard1() data.HeaderHandler { PrevRandSeed: prevRandSeed, RandSeed: currRandSeed, PrevHash: prevHash, - MiniBlockHeaders: getMiniBlockHeadersForShard1(), + MiniBlockHeaders: getMiniBlockHeadersForShard(shardID), }, } } -func getHeaderV3ForShard1() data.HeaderHandler { - prevHash := []byte("prevHash") - prevRandSeed := []byte("prevRandSeed") - currRandSeed := []byte("currRandSeed") +func getHeaderV3ForShard(shardID uint32, hash []byte) data.HeaderHandler { + prevHash := []byte(fmt.Sprintf("prevHash for shard %d", shardID)) + prevRandSeed := []byte(fmt.Sprintf("prevRandSeed for shard %d", shardID)) + currRandSeed := []byte(fmt.Sprintf("currRandSeed for shard %d", shardID)) return &block.HeaderV3{ Epoch: 7, Round: 10, @@ -976,22 +1092,22 @@ func getHeaderV3ForShard1() data.HeaderHandler { PrevRandSeed: prevRandSeed, RandSeed: currRandSeed, PrevHash: prevHash, - MiniBlockHeaders: getMiniBlockHeadersForShard1(), - ExecutionResults: []*block.ExecutionResult{getExecutionResultForShard1()}, + MiniBlockHeaders: getMiniBlockHeadersForShard(shardID), + ExecutionResults: []*block.ExecutionResult{getExecutionResultForShard(shardID, hash)}, } } -func getExecutionResultForShard1() *block.ExecutionResult { +func getExecutionResultForShard(shardID uint32, hash []byte) *block.ExecutionResult { return &block.ExecutionResult{ ExecutedTxCount: 100, - MiniBlockHeaders: getMiniBlockHeadersForShard1(), + MiniBlockHeaders: getMiniBlockHeadersForShard(shardID), BaseExecutionResult: &block.BaseExecutionResult{ - HeaderHash: []byte("header hash"), + HeaderHash: hash, HeaderNonce: 12345, HeaderEpoch: 7, HeaderRound: 15, - RootHash: []byte("root hash"), + RootHash: []byte(fmt.Sprintf("root hash for shard %d", shardID)), GasUsed: 5000, }, } From 76500366f2b21ce432c07165306d742b02dea1da Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 28 Oct 2025 15:50:45 +0200 Subject: [PATCH 32/51] format imports --- txcache/selectionTracker.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/txcache/selectionTracker.go b/txcache/selectionTracker.go index c99909411a1..a62814c3113 100644 --- a/txcache/selectionTracker.go +++ b/txcache/selectionTracker.go @@ -7,9 +7,10 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" - "github.com/multiversx/mx-chain-go/common" logger "github.com/multiversx/mx-chain-logger-go" "golang.org/x/exp/slices" + + "github.com/multiversx/mx-chain-go/common" ) type selectionTracker struct { From 35de2671524f62e3ff4e03c0998e498e8fe832b0 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Tue, 28 Oct 2025 18:00:50 +0200 Subject: [PATCH 33/51] linter fixes --- process/block/mbsSelectionSession_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/process/block/mbsSelectionSession_test.go b/process/block/mbsSelectionSession_test.go index 1df7c75c665..8192434e7f2 100644 --- a/process/block/mbsSelectionSession_test.go +++ b/process/block/mbsSelectionSession_test.go @@ -105,18 +105,16 @@ func TestMiniBlockSelectionSession_AddMiniBlocksAndHashes(t *testing.T) { session, _ := NewMiniBlocksSelectionSession(1, marshaller, hasher) err := session.AddMiniBlocksAndHashes([]block.MiniblockAndHash{ - {&block.MiniBlock{}, []byte("hash1")}, - {&block.MiniBlock{}, []byte("hash2")}, - {&block.MiniBlock{}, []byte("hash3")}, + {Miniblock: &block.MiniBlock{}, Hash: []byte("hash1")}, + {Miniblock: &block.MiniBlock{}, Hash: []byte("hash2")}, + {Miniblock: &block.MiniBlock{}, Hash: []byte("hash3")}, }) require.NoError(t, err) require.Equal(t, 3, len(session.GetMiniBlocks())) require.Equal(t, 3, len(session.GetMiniBlockHashes())) - err = session.AddMiniBlocksAndHashes([]block.MiniblockAndHash{ - {&block.MiniBlock{}, []byte("hash1")}, - }) + err = session.AddMiniBlocksAndHashes([]block.MiniblockAndHash{{Miniblock: &block.MiniBlock{}, Hash: []byte("hash1")}}) require.NoError(t, err) require.Equal(t, 3, len(session.GetMiniBlocks())) From e7828e0b1c69f3825dce1650aad728541813d042 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Wed, 29 Oct 2025 10:43:06 +0200 Subject: [PATCH 34/51] MX-17245 Fixes after copilot review --- process/block/shardinfo_test.go | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 1f5ff58b2f5..f04d2b081c3 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -202,7 +202,6 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { t.Run("should work", func(t *testing.T) { t.Parallel() - expectedNonce := uint64(12345) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -216,9 +215,7 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { args.proofsPool.HasProofCalled = func(shardID uint32, headerHash []byte) bool { return true } - args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { - return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil - } + sic, err := NewShardInfoCreateData( args.enableEpochsHandler, pool.Headers(), @@ -501,17 +498,11 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { t.Run("should work with V3", func(t *testing.T) { t.Parallel() header := getHeaderV3ForShard(uint32(1), []byte("header hash for shard 1")) - expectedNonce := uint64(12345) args := createDefaultShardInfoCreateDataArgs() args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { return header, nil } - args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { - return [][]byte{[]byte("hash1"), []byte("hash2")} - } - args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { - return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil - } + args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} } @@ -549,12 +540,6 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} } - args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { - return &block.Header{Nonce: expectedNonce}, []byte("selfNotarizedHash"), nil - } - args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { - return [][]byte{[]byte("hash1"), []byte("hash2")} - } args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { return &block.Header{Nonce: header.GetNonce()}, []byte("selfNotarizedHash"), nil } @@ -933,8 +918,6 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { return flag == common.ScheduledMiniBlocksFlag } for i := 0; i < len(headerHandler.GetMiniBlockHeaderHandlers()); i++ { - fmt.Printf("MiniBlockHeader %d: %v\n", i, headerHandler.GetMiniBlockHeaderHandlers()[i]) - _ = headerHandler.GetMiniBlockHeaderHandlers()[i].SetConstructionState(int32(block.Proposed)) require.False(t, headerHandler.GetMiniBlockHeaderHandlers()[i].IsFinal()) } From 858940417350dcd1e63883f9c87e6711f7db8bce Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Wed, 29 Oct 2025 14:04:40 +0200 Subject: [PATCH 35/51] MX-17245 Fix --- process/block/shardinfo_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index f04d2b081c3..08d737cac21 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -918,6 +918,7 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { return flag == common.ScheduledMiniBlocksFlag } for i := 0; i < len(headerHandler.GetMiniBlockHeaderHandlers()); i++ { + _ = headerHandler.GetMiniBlockHeaderHandlers()[i].SetConstructionState(int32(block.Proposed)) require.False(t, headerHandler.GetMiniBlockHeaderHandlers()[i].IsFinal()) } From 56e7f6e92fbb67a5e50315a11b4d2f67c3882e99 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 30 Oct 2025 18:55:39 +0200 Subject: [PATCH 36/51] added extra logging for rating increase for leader --- process/peer/process.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/process/peer/process.go b/process/peer/process.go index 24c89a08dc6..86946711317 100644 --- a/process/peer/process.go +++ b/process/peer/process.go @@ -1089,7 +1089,9 @@ func (vs *validatorStatistics) updateValidatorInfoOnSuccessfulBlock( log.Debug("updateValidatorInfoOnSuccessfulBlock", "leaderAccumulatedFees in current block", leaderAccumulatedFees.String(), "leader fees in Epoch", peerAcc.GetAccumulatedFees().String(), - "leader", core.GetTrimmedPk(string(peerAcc.AddressBytes()))) + "newRating", newRating, + "leader", core.GetTrimmedPk(string(peerAcc.AddressBytes())), + ) case validatorSuccess: peerAcc.IncreaseValidatorSuccessRate(1) newRating = vs.rater.ComputeIncreaseValidator(shardId, peerAcc.GetTempRating()) From 58321237469acae0e6b07c72c507a8da80b6f903 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 3 Nov 2025 14:28:53 +0200 Subject: [PATCH 37/51] shard data proposal integration --- go.mod | 2 +- go.sum | 4 +- process/block/metablockProposal.go | 11 +++- process/block/metablockProposal_test.go | 25 ++++++-- process/block/shardInfo.go | 60 +++++++++++++------ process/interface.go | 2 +- .../processMocks/shardInfoCreatorMock.go | 6 +- 7 files changed, 78 insertions(+), 32 deletions(-) diff --git a/go.mod b/go.mod index 4a101b0cad3..b76307794bc 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.13.0 github.com/mitchellh/mapstructure v1.5.0 github.com/multiversx/mx-chain-communication-go v1.3.0 - github.com/multiversx/mx-chain-core-go v1.4.2-0.20251024104613-22f9707b43a7 + github.com/multiversx/mx-chain-core-go v1.4.2-0.20251031132042-8b022e12754b github.com/multiversx/mx-chain-crypto-go v1.3.0 github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251021150757-bd6aa66a0a90 github.com/multiversx/mx-chain-logger-go v1.1.0 diff --git a/go.sum b/go.sum index 4922e286ddf..dc4f62333db 100644 --- a/go.sum +++ b/go.sum @@ -401,8 +401,8 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-communication-go v1.3.0 h1:ziNM1dRuiR/7al2L/jGEA/a/hjurtJ/HEqgazHNt9P8= github.com/multiversx/mx-chain-communication-go v1.3.0/go.mod h1:gDVWn6zUW6aCN1YOm/FbbT5MUmhgn/L1Rmpl8EoH3Yg= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251024104613-22f9707b43a7 h1:Lug7MovB5AvSZR8YlJYv2/MunD6lq+5BKkYJHtRORHA= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251024104613-22f9707b43a7/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251031132042-8b022e12754b h1:Jz56rxo1jQnfnOxkJEq0YxaqkIOwzsZFDN7LHBn24i8= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251031132042-8b022e12754b/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= github.com/multiversx/mx-chain-crypto-go v1.3.0 h1:0eK2bkDOMi8VbSPrB1/vGJSYT81IBtfL4zw+C4sWe/k= github.com/multiversx/mx-chain-crypto-go v1.3.0/go.mod h1:nPIkxxzyTP8IquWKds+22Q2OJ9W7LtusC7cAosz7ojM= github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251021150757-bd6aa66a0a90 h1:Hf6AqpCSHccBo5ZV5Bfaxz3UdPYhtYCynU+3CF4jAa8= diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 89fd6441746..bc56302f62a 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -125,12 +125,17 @@ func (mp *metaProcessor) CreateBlockProposal( // TODO: referenced shard headers should be also notarized, not only the headers corresponding to the execution results // this will be needed for metachain to keep track of the already processed headers. - shardDataHandler, err := mp.shardInfoCreateData.CreateShardInfoV3(metaHdr, referencedShardHeaders, referencedShardHeaderHashes) + shardDataProposalHandlers, shardDataHandlers, err := mp.shardInfoCreateData.CreateShardInfoV3(metaHdr, referencedShardHeaders, referencedShardHeaderHashes) if err != nil { return nil, nil, err } - err = metaHdr.SetShardInfoHandlers(shardDataHandler) + err = metaHdr.SetShardInfoHandlers(shardDataHandlers) + if err != nil { + return nil, nil, err + } + + err = metaHdr.SetShardInfoProposalHandlers(shardDataProposalHandlers) if err != nil { return nil, nil, err } @@ -145,7 +150,7 @@ func (mp *metaProcessor) CreateBlockProposal( return nil, nil, err } - totalProcessedTxs := getTxCount(shardDataHandler) + txsInExecutionResults + totalProcessedTxs := getTxCount(shardDataHandlers) + txsInExecutionResults // TODO: consider if tx count per metablock header is still needed // as we still have it in the execution results err = metaHdr.SetTxCount(totalProcessedTxs) diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index fd15549e696..059a67ba331 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -557,8 +557,8 @@ func TestMetaProcessor_CreateBlockProposal(t *testing.T) { coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) arguments.ShardInfoCreator = &processMocks.ShardInfoCreatorMock{ - CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) { - return nil, expectedErr + CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) { + return nil, nil, expectedErr }, } @@ -580,8 +580,25 @@ func TestMetaProcessor_CreateBlockProposal(t *testing.T) { } var invalidShardData data.ShardDataHandler arguments.ShardInfoCreator = &processMocks.ShardInfoCreatorMock{ - CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) { - return []data.ShardDataHandler{invalidShardData}, nil + CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) { + return nil, []data.ShardDataHandler{invalidShardData}, nil + }, + } + + mp, err := blproc.NewMetaProcessor(arguments) + require.Nil(t, err) + + validMetaHeaderV3 := &block.MetaBlockV3{} + checkCreateBlockProposalResult(t, mp, validMetaHeaderV3, haveTimeTrue, data.ErrInvalidTypeAssertion) + }) + t.Run("set shard info proposal error", func(t *testing.T) { + t.Parallel() + + coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() + arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + arguments.ShardInfoCreator = &processMocks.ShardInfoCreatorMock{ + CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) { + return nil, []data.ShardDataHandler{}, nil // nil shard data proposal }, } diff --git a/process/block/shardInfo.go b/process/block/shardInfo.go index c4fff54954d..a0a8695859b 100644 --- a/process/block/shardInfo.go +++ b/process/block/shardInfo.go @@ -60,28 +60,30 @@ func (sic *ShardInfoCreateData) CreateShardInfoV3( metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte, -) ([]data.ShardDataHandler, error) { +) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) { if check.IfNil(metaHeader) { - return nil, process.ErrNilHeaderHandler + return nil, nil, process.ErrNilHeaderHandler } if !metaHeader.IsHeaderV3() { - return nil, process.ErrInvalidHeader + return nil, nil, process.ErrInvalidHeader } var shardInfo []data.ShardDataHandler + var shardInfoProposal []data.ShardDataProposalHandler if len(shardHeaders) != len(shardHeaderHashes) { - return nil, process.ErrInconsistentShardHeadersAndHashes + return nil, nil, process.ErrInconsistentShardHeadersAndHashes } for i := 0; i < len(shardHeaders); i++ { - shardData, err := sic.createShardInfoFromHeader(shardHeaders[i], shardHeaderHashes[i]) + shardDataProposal, shardData, err := sic.createShardInfoFromHeader(shardHeaders[i], shardHeaderHashes[i]) if err != nil { - return nil, err + return nil, nil, err } shardInfo = append(shardInfo, shardData...) + shardInfoProposal = append(shardInfoProposal, shardDataProposal) } - return shardInfo, nil + return shardInfoProposal, shardInfo, nil } // CreateShardInfoFromLegacyMeta creates shard info for legacy meta header @@ -113,24 +115,28 @@ func (sic *ShardInfoCreateData) CreateShardInfoFromLegacyMeta( return shardInfo, nil } -func (sic *ShardInfoCreateData) createShardInfoFromHeader(shardHeader data.HeaderHandler, hdrHash []byte) ([]data.ShardDataHandler, error) { +func (sic *ShardInfoCreateData) createShardInfoFromHeader( + shardHeader data.HeaderHandler, + hdrHash []byte, +) (data.ShardDataProposalHandler, []data.ShardDataHandler, error) { if check.IfNil(shardHeader) { - return nil, process.ErrNilHeaderHandler + return nil, nil, process.ErrNilHeaderHandler } if len(hdrHash) == 0 { - return nil, process.ErrInvalidHash + return nil, nil, process.ErrInvalidHash } hasMissingShardHdrProof := shardHeader.GetNonce() >= 1 && !sic.proofsPool.HasProof(shardHeader.GetShardID(), hdrHash) if hasMissingShardHdrProof { - return nil, fmt.Errorf("%w for shard header with hash %s", process.ErrMissingHeaderProof, hex.EncodeToString(hdrHash)) + return nil, nil, fmt.Errorf("%w for shard header with hash %s", process.ErrMissingHeaderProof, hex.EncodeToString(hdrHash)) } if !shardHeader.IsHeaderV3() { - return sic.createShardDataFromLegacyHeader(shardHeader, hdrHash) + shardData, err := sic.createShardDataFromLegacyHeader(shardHeader, hdrHash) + return &block.ShardDataProposal{}, shardData, err // no shard data proposal for legacy header } - return sic.createShardDataFromV3Header(shardHeader) + return sic.createShardDataFromV3Header(shardHeader, hdrHash) } func (sic *ShardInfoCreateData) createShardDataFromLegacyHeader(shardHdr data.HeaderHandler, hdrHash []byte) ([]data.ShardDataHandler, error) { @@ -157,25 +163,43 @@ func (sic *ShardInfoCreateData) createShardDataFromLegacyHeader(shardHdr data.He return []data.ShardDataHandler{shardData}, nil } -func (sic *ShardInfoCreateData) createShardDataFromV3Header(shardHeader data.HeaderHandler) ([]data.ShardDataHandler, error) { +func (sic *ShardInfoCreateData) createShardDataFromV3Header( + shardHeader data.HeaderHandler, + hdrHash []byte, +) (data.ShardDataProposalHandler, []data.ShardDataHandler, error) { if check.IfNil(shardHeader) { - return nil, process.ErrNilHeaderHandler + return nil, nil, process.ErrNilHeaderHandler } + shardDataProposal := createShardDataProposalFromHeader(shardHeader, hdrHash) executionResults := shardHeader.GetExecutionResultsHandlers() if len(executionResults) == 0 { - return []data.ShardDataHandler{}, nil + // return shard data proposal even though the shard header does not hold any execution result + return shardDataProposal, []data.ShardDataHandler{}, nil } shardDataHandlers := make([]data.ShardDataHandler, len(executionResults)) for i, execResult := range executionResults { shardData, err := sic.createShardDataFromExecutionResult(execResult) if err != nil { - return nil, err + return nil, nil, err } shardDataHandlers[i] = shardData } - return shardDataHandlers, nil + return shardDataProposal, shardDataHandlers, nil +} + +func createShardDataProposalFromHeader( + header data.HeaderHandler, + hdrHash []byte, +) data.ShardDataProposalHandler { + return &block.ShardDataProposal{ + HeaderHash: hdrHash, + Round: header.GetRound(), + Nonce: header.GetNonce(), + ShardID: header.GetShardID(), + Epoch: header.GetEpoch(), + } } func (sic *ShardInfoCreateData) createShardDataFromExecutionResult( diff --git a/process/interface.go b/process/interface.go index 4ab37f0b931..ed29ed6c9a7 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1589,7 +1589,7 @@ type InclusionEstimator interface { // ShardInfoCreator defines the functionality to create shard info type ShardInfoCreator interface { - CreateShardInfoV3(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) + CreateShardInfoV3(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) CreateShardInfoFromLegacyMeta(metaHeader data.MetaHeaderHandler, shardHeaders []data.ShardHeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) IsInterfaceNil() bool } diff --git a/testscommon/processMocks/shardInfoCreatorMock.go b/testscommon/processMocks/shardInfoCreatorMock.go index 439424abe50..67c612a8bf7 100644 --- a/testscommon/processMocks/shardInfoCreatorMock.go +++ b/testscommon/processMocks/shardInfoCreatorMock.go @@ -6,7 +6,7 @@ import ( // ShardInfoCreatorMock is a mock implementation of ShardInfoCreator interface type ShardInfoCreatorMock struct { - CreateShardInfoV3Called func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) + CreateShardInfoV3Called func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) CreateShardInfoFromLegacyMetaCalled func(metaHeader data.MetaHeaderHandler, shardHeaders []data.ShardHeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataHandler, error) } @@ -15,11 +15,11 @@ func (scm *ShardInfoCreatorMock) CreateShardInfoV3( metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte, -) ([]data.ShardDataHandler, error) { +) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) { if scm.CreateShardInfoV3Called != nil { return scm.CreateShardInfoV3Called(metaHeader, shardHeaders, shardHeaderHashes) } - return nil, nil + return nil, nil, nil } // CreateShardInfoFromLegacyMeta - From d272d305e7118e9856dac0dda689323d98013bac Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 3 Nov 2025 16:22:57 +0200 Subject: [PATCH 38/51] fixes after merge --- common/common.go | 1 - common/common_test.go | 11 ++++++----- epochStart/bootstrap/process.go | 2 +- epochStart/bootstrap/shardStorageHandler.go | 5 +++-- process/block/baseProcess.go | 4 ++-- process/block/gasConsumption.go | 8 ++------ process/block/metablockProposal.go | 2 +- process/interface.go | 1 - testscommon/gasComputationMock.go | 8 -------- 9 files changed, 15 insertions(+), 27 deletions(-) diff --git a/common/common.go b/common/common.go index ba48a524eb5..12067a514f5 100644 --- a/common/common.go +++ b/common/common.go @@ -416,7 +416,6 @@ func ExtractBaseExecutionResultHandler(lastExecResultsHandler data.LastExecution // GetMiniBlocksHeaderHandlersFromExecResult returns miniblock handlers based on execution result func GetMiniBlocksHeaderHandlersFromExecResult( baseExecResult data.BaseExecutionResultHandler, - headerShard uint32, ) ([]data.MiniBlockHeaderHandler, error) { if check.IfNil(baseExecResult) { return nil, ErrNilBaseExecutionResult diff --git a/common/common_test.go b/common/common_test.go index e0c244536c4..50ffd4ca67c 100644 --- a/common/common_test.go +++ b/common/common_test.go @@ -11,13 +11,14 @@ import ( "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/data/smartContractResult" "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" commonErrors "github.com/multiversx/mx-chain-go/errors" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/chainParameters" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" - "github.com/stretchr/testify/require" ) var testFlag = core.EnableEpochFlag("test flag") @@ -584,7 +585,7 @@ func TestGetMiniBlockHeaderHandlersFromExecResults(t *testing.T) { t.Run("should fail if nil base execution result", func(t *testing.T) { t.Parallel() - retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(nil, 1) + retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(nil) require.Equal(t, common.ErrNilBaseExecutionResult, err) require.Nil(t, retExecResult) }) @@ -594,7 +595,7 @@ func TestGetMiniBlockHeaderHandlersFromExecResults(t *testing.T) { execResult := &block.BaseExecutionResult{} - retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult, 1) + retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult) require.Equal(t, common.ErrWrongTypeAssertion, err) require.Nil(t, retExecResult) }) @@ -623,7 +624,7 @@ func TestGetMiniBlockHeaderHandlersFromExecResults(t *testing.T) { &mbh2, } - retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult, 1) + retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult) require.Nil(t, err) require.Equal(t, expMiniBlockHandlers, retExecResult) }) @@ -652,7 +653,7 @@ func TestGetMiniBlockHeaderHandlersFromExecResults(t *testing.T) { &mbh2, } - retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult, core.MetachainShardId) + retExecResult, err := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult) require.Nil(t, err) require.Equal(t, expMiniBlockHandlers, retExecResult) }) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 6f1c1061fa6..1b2e47dfb78 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -1357,7 +1357,7 @@ func getStartOfEpochRootHashFromExecutionResults( for i := len(header.GetExecutionResultsHandlers()) - 1; i >= 0; i-- { executionResult := header.GetExecutionResultsHandlers()[i] - miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(executionResult, header.GetShardID()) + miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(executionResult) if err != nil { return nil, err } diff --git a/epochStart/bootstrap/shardStorageHandler.go b/epochStart/bootstrap/shardStorageHandler.go index ce322653e7d..20ca491403b 100644 --- a/epochStart/bootstrap/shardStorageHandler.go +++ b/epochStart/bootstrap/shardStorageHandler.go @@ -10,13 +10,14 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/epochStart/bootstrap/disabled" "github.com/multiversx/mx-chain-go/process/block/bootstrapStorage" "github.com/multiversx/mx-chain-go/storage/factory" - logger "github.com/multiversx/mx-chain-logger-go" ) type shardStorageHandler struct { @@ -942,7 +943,7 @@ func getMetaHeaderMiniBlockHandlersFromExecutionResults( execResultsMiniBlockHeaderHandlers := make([]data.MiniBlockHeaderHandler, 0) for _, baseExecutionResult := range baseExecutionResults { - miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecutionResult, metaBlock.GetShardID()) + miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecutionResult) if err != nil { log.Warn("failed to get mini blocks header handlers from execution result", "err", err) return nil diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 61ba4566fd0..df6fce2fb4d 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -1310,7 +1310,7 @@ func (bp *baseProcessor) getFinalMiniBlocksFromExecutionResults( executedMiniBlocksCache := bp.dataPool.ExecutedMiniBlocks() for _, baseExecutionResult := range baseExecutionResults { - miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecutionResult, header.GetShardID()) + miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecutionResult) if err != nil { return nil, err } @@ -2534,7 +2534,7 @@ func (bp *baseProcessor) saveMiniBlocksFromExecutionResults(header data.HeaderHa } for _, baseExecutionResult := range baseExecutionResults { - miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecutionResult, header.GetShardID()) + miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecutionResult) if err != nil { return err } diff --git a/process/block/gasConsumption.go b/process/block/gasConsumption.go index 5a642e23a05..a05c208f3dd 100644 --- a/process/block/gasConsumption.go +++ b/process/block/gasConsumption.go @@ -8,8 +8,9 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" - "github.com/multiversx/mx-chain-go/process" "golang.org/x/exp/slices" + + "github.com/multiversx/mx-chain-go/process" ) // gasType defines the type of gas consumption @@ -573,11 +574,6 @@ func (gc *gasConsumption) maxGasLimitPerMiniBlock(shardID uint32) uint64 { return gc.economicsFee.MaxGasLimitPerMiniBlock(shardID) } -// RevertIncomingMiniBlocks reverts the gas consumption for the given incoming mini blocks -func (gc *gasConsumption) RevertIncomingMiniBlocks(miniBlockHashes [][]byte) { - // TODO: implement this -} - // IsInterfaceNil checks if the interface is nil func (gc *gasConsumption) IsInterfaceNil() bool { return gc == nil diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 89fd6441746..5b7f5e77f7d 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -202,7 +202,7 @@ func (mp *metaProcessor) hasStartOfEpochExecutionResults(metaHeader data.MetaHea } execResults := metaHeader.GetExecutionResultsHandlers() for _, execResult := range execResults { - mbHeaders, err := mp.extractMiniBlocksHeaderHandlersFromExecResult(execResult, common.MetachainShardId) + mbHeaders, err := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult) if err != nil { return false, err } diff --git a/process/interface.go b/process/interface.go index 4ab37f0b931..955d8c1c27b 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1538,7 +1538,6 @@ type GasComputation interface { txHashes [][]byte, transactions []data.TransactionHandler, ) (addedTxHashes [][]byte, pendingMiniBlocksAdded []data.MiniBlockHeaderHandler, err error) - RevertIncomingMiniBlocks(miniBlockHashes [][]byte) GetBandwidthForTransactions() uint64 RevertIncomingMiniBlocks(miniBlockHashes [][]byte) TotalGasConsumed() uint64 diff --git a/testscommon/gasComputationMock.go b/testscommon/gasComputationMock.go index 1e81286a2f2..9cfcdbbd341 100644 --- a/testscommon/gasComputationMock.go +++ b/testscommon/gasComputationMock.go @@ -14,7 +14,6 @@ type GasComputationMock struct { txHashes [][]byte, transactions []data.TransactionHandler, ) ([][]byte, []data.MiniBlockHeaderHandler, error) - RevertIncomingMiniBlocksCalled func(miniBlockHashes [][]byte) GetBandwidthForTransactionsCalled func() uint64 TotalGasConsumedCalled func() uint64 DecreaseIncomingLimitCalled func() @@ -64,13 +63,6 @@ func (mock *GasComputationMock) GetBandwidthForTransactions() uint64 { return 0 } -// RevertIncomingMiniBlocks - -func (mock *GasComputationMock) RevertIncomingMiniBlocks(miniBlockHashes [][]byte) { - if mock.RevertIncomingMiniBlocksCalled != nil { - mock.RevertIncomingMiniBlocksCalled(miniBlockHashes) - } -} - // TotalGasConsumed - func (mock *GasComputationMock) TotalGasConsumed() uint64 { if mock.TotalGasConsumedCalled != nil { From eb500141af9823d2dc2efb98ea56e1fc4378e45a Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 3 Nov 2025 16:42:13 +0200 Subject: [PATCH 39/51] fixes tests --- process/block/metablockProposal_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index fd15549e696..3d6ab749ccd 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -223,9 +223,7 @@ func TestMetaProcessor_CreateNewHeaderProposal(t *testing.T) { metaBlockWithInvalidExecutionResult := validMetaHeaderV3 metaBlockWithInvalidExecutionResult.GetExecutionResultsHandlersCalled = func() []data.BaseExecutionResultHandler { return []data.BaseExecutionResultHandler{ - &block.ExecutionResult{ - BaseExecutionResult: &block.BaseExecutionResult{}, - }, // invalid for meta block + &block.BaseExecutionResult{}, // invalid for meta block } } @@ -831,7 +829,7 @@ func TestMetaProcessor_hasStartOfEpochExecutionResults(t *testing.T) { validMetaHeaderV3 := &testscommon.HeaderHandlerStub{ GetExecutionResultsHandlersCalled: func() []data.BaseExecutionResultHandler { return []data.BaseExecutionResultHandler{ - &block.ExecutionResult{}, + &block.BaseExecutionResult{}, // invalid for meta block } }, } From f5ac835c685e85b8ad4c04c0b2ee35817c197d4c Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Mon, 3 Nov 2025 16:58:28 +0200 Subject: [PATCH 40/51] fix after merge --- process/block/pendingMb/pendingMiniBlocks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/block/pendingMb/pendingMiniBlocks.go b/process/block/pendingMb/pendingMiniBlocks.go index 8d99517f650..1d055dfe8fc 100644 --- a/process/block/pendingMb/pendingMiniBlocks.go +++ b/process/block/pendingMb/pendingMiniBlocks.go @@ -69,7 +69,7 @@ func getMiniBlocksFromHeaderReadyForCrossShardExecution(header data.MetaHeaderHa miniBlocks := make([]data.MiniBlockHeaderHandler, 0) execResultHandlers := header.GetExecutionResultsHandlers() for _, execResult := range execResultHandlers { - mbs, errGetMbs := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult, common.MetachainShardId) + mbs, errGetMbs := common.GetMiniBlocksHeaderHandlersFromExecResult(execResult) if errGetMbs != nil { return nil, errGetMbs } From 3d33c6ca6c6e1ef374b67763fdb99aba44250d2c Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 3 Nov 2025 17:19:21 +0200 Subject: [PATCH 41/51] updated core-go after merge --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b76307794bc..2e6e394de6c 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.13.0 github.com/mitchellh/mapstructure v1.5.0 github.com/multiversx/mx-chain-communication-go v1.3.0 - github.com/multiversx/mx-chain-core-go v1.4.2-0.20251031132042-8b022e12754b + github.com/multiversx/mx-chain-core-go v1.4.2-0.20251103151001-9fa760b48eff github.com/multiversx/mx-chain-crypto-go v1.3.0 github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251021150757-bd6aa66a0a90 github.com/multiversx/mx-chain-logger-go v1.1.0 diff --git a/go.sum b/go.sum index dc4f62333db..a6d4d4e62c9 100644 --- a/go.sum +++ b/go.sum @@ -401,8 +401,8 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-communication-go v1.3.0 h1:ziNM1dRuiR/7al2L/jGEA/a/hjurtJ/HEqgazHNt9P8= github.com/multiversx/mx-chain-communication-go v1.3.0/go.mod h1:gDVWn6zUW6aCN1YOm/FbbT5MUmhgn/L1Rmpl8EoH3Yg= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251031132042-8b022e12754b h1:Jz56rxo1jQnfnOxkJEq0YxaqkIOwzsZFDN7LHBn24i8= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251031132042-8b022e12754b/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251103151001-9fa760b48eff h1:rPvmYqCUL+S0TQFOLgI3oERGuyF3U1QK3+MoW53mrUs= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251103151001-9fa760b48eff/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= github.com/multiversx/mx-chain-crypto-go v1.3.0 h1:0eK2bkDOMi8VbSPrB1/vGJSYT81IBtfL4zw+C4sWe/k= github.com/multiversx/mx-chain-crypto-go v1.3.0/go.mod h1:nPIkxxzyTP8IquWKds+22Q2OJ9W7LtusC7cAosz7ojM= github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251021150757-bd6aa66a0a90 h1:Hf6AqpCSHccBo5ZV5Bfaxz3UdPYhtYCynU+3CF4jAa8= From 2496cca5a9c8fee4feec19006bbeed65ce7a876d Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 4 Nov 2025 11:31:25 +0200 Subject: [PATCH 42/51] fix after review --- go.mod | 2 +- go.sum | 4 ++-- process/block/shardInfo.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 2e6e394de6c..16827fe47ec 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.13.0 github.com/mitchellh/mapstructure v1.5.0 github.com/multiversx/mx-chain-communication-go v1.3.0 - github.com/multiversx/mx-chain-core-go v1.4.2-0.20251103151001-9fa760b48eff + github.com/multiversx/mx-chain-core-go v1.4.2-0.20251104092828-1dd9514c928a github.com/multiversx/mx-chain-crypto-go v1.3.0 github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251021150757-bd6aa66a0a90 github.com/multiversx/mx-chain-logger-go v1.1.0 diff --git a/go.sum b/go.sum index a6d4d4e62c9..89a13e151a3 100644 --- a/go.sum +++ b/go.sum @@ -401,8 +401,8 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-communication-go v1.3.0 h1:ziNM1dRuiR/7al2L/jGEA/a/hjurtJ/HEqgazHNt9P8= github.com/multiversx/mx-chain-communication-go v1.3.0/go.mod h1:gDVWn6zUW6aCN1YOm/FbbT5MUmhgn/L1Rmpl8EoH3Yg= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251103151001-9fa760b48eff h1:rPvmYqCUL+S0TQFOLgI3oERGuyF3U1QK3+MoW53mrUs= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251103151001-9fa760b48eff/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251104092828-1dd9514c928a h1:sOp+4UkIJNbLFlpefo3G1cFKjYnVbMIpVbQsTSZzooo= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251104092828-1dd9514c928a/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= github.com/multiversx/mx-chain-crypto-go v1.3.0 h1:0eK2bkDOMi8VbSPrB1/vGJSYT81IBtfL4zw+C4sWe/k= github.com/multiversx/mx-chain-crypto-go v1.3.0/go.mod h1:nPIkxxzyTP8IquWKds+22Q2OJ9W7LtusC7cAosz7ojM= github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251021150757-bd6aa66a0a90 h1:Hf6AqpCSHccBo5ZV5Bfaxz3UdPYhtYCynU+3CF4jAa8= diff --git a/process/block/shardInfo.go b/process/block/shardInfo.go index a0a8695859b..d1bb98bd140 100644 --- a/process/block/shardInfo.go +++ b/process/block/shardInfo.go @@ -133,7 +133,7 @@ func (sic *ShardInfoCreateData) createShardInfoFromHeader( if !shardHeader.IsHeaderV3() { shardData, err := sic.createShardDataFromLegacyHeader(shardHeader, hdrHash) - return &block.ShardDataProposal{}, shardData, err // no shard data proposal for legacy header + return createShardDataProposalFromHeader(shardHeader, hdrHash), shardData, err } return sic.createShardDataFromV3Header(shardHeader, hdrHash) From 3e659c73db83059622d36d1cd101b8e45ebfe800 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 4 Nov 2025 12:13:13 +0200 Subject: [PATCH 43/51] fixed tests --- process/block/metablockProposal_test.go | 3 ++- testscommon/headerHandlerStub.go | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index 5fad29c410e..9d4e66cc9bb 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -594,9 +594,10 @@ func TestMetaProcessor_CreateBlockProposal(t *testing.T) { coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() arguments := createMockMetaArguments(coreComponents, dataComponents, bootstrapComponents, statusComponents) + var invalidShardDataProposal data.ShardDataProposalHandler arguments.ShardInfoCreator = &processMocks.ShardInfoCreatorMock{ CreateShardInfoV3Called: func(metaHeader data.MetaHeaderHandler, shardHeaders []data.HeaderHandler, shardHeaderHashes [][]byte) ([]data.ShardDataProposalHandler, []data.ShardDataHandler, error) { - return nil, []data.ShardDataHandler{}, nil // nil shard data proposal + return []data.ShardDataProposalHandler{invalidShardDataProposal}, []data.ShardDataHandler{}, nil }, } diff --git a/testscommon/headerHandlerStub.go b/testscommon/headerHandlerStub.go index 0b3421b623c..e9bea524507 100644 --- a/testscommon/headerHandlerStub.go +++ b/testscommon/headerHandlerStub.go @@ -71,6 +71,8 @@ type HeaderHandlerStub struct { SetRoundCalled func(round uint64) error SetNonceCalled func(nonce uint64) error SetShardInfoHandlersCalled func(shardInfo []data.ShardDataHandler) error + GetShardInfoProposalHandlersCalled func() []data.ShardDataProposalHandler + SetShardInfoProposalHandlersCalled func(shardInfo []data.ShardDataProposalHandler) error } // SetEpochStartHandler - @@ -566,3 +568,19 @@ func (hhs *HeaderHandlerStub) GetGasLimit() uint32 { return 0 } + +// GetShardInfoProposalHandlers - +func (hhs *HeaderHandlerStub) GetShardInfoProposalHandlers() []data.ShardDataProposalHandler { + if hhs.GetShardInfoProposalHandlersCalled != nil { + return hhs.GetShardInfoProposalHandlersCalled() + } + return nil +} + +// SetShardInfoProposalHandlers - +func (hhs *HeaderHandlerStub) SetShardInfoProposalHandlers(shardInfo []data.ShardDataProposalHandler) error { + if hhs.SetShardInfoProposalHandlersCalled != nil { + return hhs.SetShardInfoProposalHandlersCalled(shardInfo) + } + return nil +} From 666212fcc0232746293f747705976c16c00c4912 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Tue, 4 Nov 2025 17:48:34 +0200 Subject: [PATCH 44/51] MX-17245 Fixes after review --- process/block/shardinfo_test.go | 55 ++++++++++++--------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 08d737cac21..d8a1142dc3c 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -130,11 +130,9 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { header1 := getShardHeaderForShard(uint32(1)) header2 := getShardHeaderForShard(uint32(2)) header3 := getHeaderV3ForShard(uint32(2), hdrHash3) - headers := make([]data.HeaderHandler, 0) - headers = append(headers, []data.HeaderHandler{header0, header1, header2, header3}...) + headers := []data.HeaderHandler{header0, header1, header2, header3} - headerHashes := make([][]byte, 0) - headerHashes = append(headerHashes, [][]byte{hdrHash0, hdrHash1, hdrHash2, hdrHash3}...) + headerHashes := [][]byte{hdrHash0, hdrHash1, hdrHash2, hdrHash3} pool := dataRetrieverMock.NewPoolsHolderMock() pool.Headers().AddHeader(hdrHash0, header0) @@ -248,17 +246,9 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { miniBlockHeader2 := block.MiniBlockHeader{Hash: mbHash2} miniBlockHeader3 := block.MiniBlockHeader{Hash: mbHash3} - miniBlockHeaders1 := make([]block.MiniBlockHeader, 0) - miniBlockHeaders1 = append(miniBlockHeaders1, miniBlockHeader1) - miniBlockHeaders1 = append(miniBlockHeaders1, miniBlockHeader2) - miniBlockHeaders1 = append(miniBlockHeaders1, miniBlockHeader3) - - miniBlockHeaders2 := make([]block.MiniBlockHeader, 0) - miniBlockHeaders2 = append(miniBlockHeaders2, miniBlockHeader1) - miniBlockHeaders2 = append(miniBlockHeaders2, miniBlockHeader2) - - miniBlockHeaders3 := make([]block.MiniBlockHeader, 0) - miniBlockHeaders3 = append(miniBlockHeaders3, miniBlockHeader1) + miniBlockHeaders1 := []block.MiniBlockHeader{miniBlockHeader1, miniBlockHeader2, miniBlockHeader3} + miniBlockHeaders2 := []block.MiniBlockHeader{miniBlockHeader1, miniBlockHeader2} + miniBlockHeaders3 := []block.MiniBlockHeader{miniBlockHeader1} header1 := &block.Header{ Round: 1, @@ -280,10 +270,8 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { pool.Headers().AddHeader(hdrHash2, header2) pool.Headers().AddHeader(hdrHash3, header3) - headerHashes := make([][]byte, 0) - headers := make([]data.ShardHeaderHandler, 0) - headers = append(headers, []data.ShardHeaderHandler{header1, header2, header3}...) - headerHashes = append(headerHashes, [][]byte{hdrHash1, hdrHash2, hdrHash3}...) + headerHashes := [][]byte{hdrHash1, hdrHash2, hdrHash3} + headers := []data.ShardHeaderHandler{header1, header2, header3} round := uint64(10) metaHdr := &block.MetaBlock{Round: round} @@ -301,9 +289,8 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { ) require.Nil(t, err) shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdrV3, headers, headerHashes) - require.NotNil(t, err) + require.Equal(t, process.ErrInvalidHeader, err) require.Nil(t, shardInfo) - assert.Equal(t, process.ErrInvalidHeader, err) }) t.Run("should fail with inconsistent headers and hashes", func(t *testing.T) { t.Parallel() @@ -318,18 +305,20 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { ) require.Nil(t, err) shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdr, headers, headerHashes[:1]) - require.NotNil(t, err) + require.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) require.Nil(t, shardInfo) - assert.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) + }) t.Run("should fail when createShardDataFromLegacyHeader errors", func(t *testing.T) { t.Parallel() + + errExpected := fmt.Errorf("GetLastSelfNotarizedHeader error") args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} } args.blockTracker.GetLastSelfNotarizedHeaderCalled = func(shardID uint32) (data.HeaderHandler, []byte, error) { - return nil, nil, fmt.Errorf("GetLastSelfNotarizedHeader error") + return nil, nil, errExpected } args.enableEpochsHandler.IsFlagEnabledInEpochCalled = func(flag core.EnableEpochFlag, epoch uint32) bool { return true @@ -348,6 +337,7 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdr, headers, headerHashes) require.NotNil(t, err) require.Nil(t, shardInfo) + require.Equal(t, errExpected, err) }) t.Run("should work", func(t *testing.T) { t.Parallel() @@ -763,9 +753,8 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { ) require.Nil(t, err) shardData, err := sic.createShardDataFromExecutionResult(nil) - require.NotNil(t, err) - require.Nil(t, shardData) require.ErrorIs(t, err, process.ErrNilExecutionResultHandler) + require.Nil(t, shardData) }) t.Run("should fail with wrong type of execution result", func(t *testing.T) { @@ -781,9 +770,8 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { require.Nil(t, err) var execResult data.BaseExecutionResultHandler = &block.BaseExecutionResult{} shardData, err := sic.createShardDataFromExecutionResult(execResult) - require.NotNil(t, err) - require.Nil(t, shardData) require.ErrorIs(t, err, process.ErrWrongTypeAssertion) + require.Nil(t, shardData) }) t.Run("should fail when GetHeaderByHash errors", func(t *testing.T) { @@ -803,9 +791,8 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { require.Nil(t, err) execResult := getExecutionResultForShard(uint32(1), []byte("header hash for shard 1")) shardData, err := sic.createShardDataFromExecutionResult(execResult) - require.NotNil(t, err) - require.Nil(t, shardData) require.Equal(t, fmt.Errorf("GetHeaderByHash error"), err) + require.Nil(t, shardData) }) t.Run("should fail when updateShardDataWithCrossShardInfo fails", func(t *testing.T) { @@ -825,9 +812,8 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { require.Nil(t, err) execResult := getExecutionResultForShard(uint32(1), []byte("header hash for shard 1")) shardData, err := sic.createShardDataFromExecutionResult(execResult) - require.NotNil(t, err) - require.Nil(t, shardData) require.Equal(t, fmt.Errorf("notarized headers slice is nil"), err) + require.Nil(t, shardData) }) t.Run("should work", func(t *testing.T) { @@ -1040,10 +1026,7 @@ func getMiniBlockHeadersForShard(shardID uint32) []block.MiniBlockHeader { ReceiverShardID: 0, } - miniBlockHeaders := make([]block.MiniBlockHeader, 0) - miniBlockHeaders = append(miniBlockHeaders, miniBlockHeader1) - miniBlockHeaders = append(miniBlockHeaders, miniBlockHeader2) - miniBlockHeaders = append(miniBlockHeaders, miniBlockHeader3) + miniBlockHeaders := []block.MiniBlockHeader{miniBlockHeader1, miniBlockHeader2, miniBlockHeader3} return miniBlockHeaders } From 6a5fccf1daf268506ca45f21706c74ca6ab30751 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Wed, 5 Nov 2025 11:28:58 +0200 Subject: [PATCH 45/51] MX-17245 Fixes after merge --- process/block/shardinfo_test.go | 128 +++++++++++++++++++++----------- 1 file changed, 86 insertions(+), 42 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index d8a1142dc3c..cbca5476fb1 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -143,6 +143,23 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { round := uint64(10) metaHdrV3 := &block.MetaBlockV3{Round: round} + t.Run("should fail with nil meta header", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(nil, headers, headerHashes) + require.ErrorIs(t, err, process.ErrNilHeaderHandler) + require.Nil(t, shardDataProposalHandlers) + require.Nil(t, shardDataHandlers) + }) + t.Run("should fail with Legacy meta header", func(t *testing.T) { t.Parallel() @@ -156,10 +173,10 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardInfo, err := sic.CreateShardInfoV3(metaHdr, headers, headerHashes[:2]) - require.NotNil(t, err) - require.Nil(t, shardInfo) - assert.Equal(t, process.ErrInvalidHeader, err) + shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(metaHdr, headers, headerHashes) + require.Equal(t, process.ErrInvalidHeader, err) + require.Nil(t, shardDataProposalHandlers) + require.Nil(t, shardDataHandlers) }) t.Run("should fail with inconsistent headers and hashes", func(t *testing.T) { t.Parallel() @@ -173,10 +190,10 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardInfo, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes[:2]) - require.NotNil(t, err) - require.Nil(t, shardInfo) - assert.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) + shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes[:2]) + require.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) + require.Nil(t, shardDataProposalHandlers) + require.Nil(t, shardDataHandlers) }) t.Run("should fail when createShardInfoFromHeader errors", func(t *testing.T) { t.Parallel() @@ -190,12 +207,10 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - invalidHashes := make([][]byte, len(headerHashes)) - invalidHashes[0] = []byte("") - shardInfo, err := sic.CreateShardInfoV3(metaHdrV3, headers, invalidHashes) - require.NotNil(t, err) - require.Nil(t, shardInfo) - assert.Equal(t, process.ErrInvalidHash, err) + shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes) + require.Contains(t, err.Error(), process.ErrMissingHeaderProof.Error()) + require.Nil(t, shardDataProposalHandlers) + require.Nil(t, shardDataHandlers) }) t.Run("should work", func(t *testing.T) { t.Parallel() @@ -222,10 +237,12 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardInfo, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes) + shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes) require.Nil(t, err) - require.NotNil(t, shardInfo) - require.Equal(t, 4, len(shardInfo)) + require.NotNil(t, shardDataHandlers) + require.NotNil(t, shardDataProposalHandlers) + require.Equal(t, 4, len(shardDataHandlers)) + require.Equal(t, 4, len(shardDataProposalHandlers)) }) } @@ -275,6 +292,21 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { round := uint64(10) metaHdr := &block.MetaBlock{Round: round} + t.Run("should fail with nil meta header", func(t *testing.T) { + t.Parallel() + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoFromLegacyMeta(nil, headers, headerHashes) + require.Equal(t, process.ErrNilHeaderHandler, err) + require.Nil(t, shardInfo) + }) t.Run("should fail with V3 meta header", func(t *testing.T) { t.Parallel() @@ -383,9 +415,10 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { ) require.Nil(t, err) - shardData, err := sic.createShardInfoFromHeader(nil, nil) + shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(nil, nil) require.NotNil(t, err) - require.Nil(t, shardData) + require.Nil(t, shardDataProposalHandlers) + require.Nil(t, shardDataHandlers) require.ErrorIs(t, err, process.ErrNilHeaderHandler) }) t.Run("should fail with invalid hash", func(t *testing.T) { @@ -400,9 +433,10 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { ) require.Nil(t, err) - shardData, err := sic.createShardInfoFromHeader(&block.Header{}, []byte{}) + shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(&block.Header{}, []byte{}) require.NotNil(t, err) - require.Nil(t, shardData) + require.Nil(t, shardDataProposalHandlers) + require.Nil(t, shardDataHandlers) require.ErrorIs(t, err, process.ErrInvalidHash) }) @@ -421,9 +455,10 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { ) require.Nil(t, err) - shardData, err := sic.createShardInfoFromHeader(&block.Header{Nonce: 1}, []byte("hash")) + shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(&block.Header{Nonce: 1}, []byte("hash")) require.NotNil(t, err) - require.Nil(t, shardData) + require.Nil(t, shardDataProposalHandlers) + require.Nil(t, shardDataHandlers) require.ErrorIs(t, err, process.ErrMissingHeaderProof) }) t.Run("should work with Legacy", func(t *testing.T) { @@ -451,9 +486,10 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { ) require.Nil(t, err) - shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardData) + require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataHandlers) }) t.Run("should work with Legacy no proof for epoch < 1", func(t *testing.T) { t.Parallel() @@ -481,9 +517,10 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { ) require.Nil(t, err) - shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardData) + require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataHandlers) }) t.Run("should work with V3", func(t *testing.T) { t.Parallel() @@ -514,9 +551,10 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { ) require.Nil(t, err) - shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardData) + require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataHandlers) }) t.Run("should work with V3 no proof for nonce < 1", func(t *testing.T) { t.Parallel() @@ -548,9 +586,10 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { ) require.Nil(t, err) - shardData, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardData) + require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataHandlers) }) } @@ -654,9 +693,10 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardDataList, err := sic.createShardDataFromV3Header(nil) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardDataFromV3Header(nil, nil) require.NotNil(t, err) - require.Nil(t, shardDataList) + require.Nil(t, shardDataHandlers) + require.Nil(t, shardDataProposalHandler) require.ErrorIs(t, err, process.ErrNilHeaderHandler) }) t.Run("should return early if no execution results", func(t *testing.T) { @@ -673,10 +713,11 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardDataList, err := sic.createShardDataFromV3Header(header) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardDataFromV3Header(header, []byte("headerHash")) require.Nil(t, err) - require.NotNil(t, shardDataList) - require.Equal(t, 0, len(shardDataList)) + require.NotNil(t, shardDataHandlers) + require.NotNil(t, shardDataProposalHandler) + require.Equal(t, 0, len(shardDataHandlers)) }) t.Run("should fail with createShardDataFromExecutionResult error", func(t *testing.T) { t.Parallel() @@ -702,9 +743,10 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardDataList, err := sic.createShardDataFromV3Header(header) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardDataFromV3Header(header, []byte("headerHash")) require.NotNil(t, err) - require.Nil(t, shardDataList) + require.Nil(t, shardDataHandlers) + require.Nil(t, shardDataProposalHandler) require.Equal(t, fmt.Errorf("GetHeaderByHash error"), err) }) @@ -730,11 +772,13 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - shardDataList, err := sic.createShardDataFromV3Header(header) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardDataFromV3Header(header, []byte("headerHash")) require.Nil(t, err) - require.NotNil(t, shardDataList) - require.Equal(t, 1, len(shardDataList)) - require.Equal(t, expectedNonce, shardDataList[0].GetNonce()) + require.NotNil(t, shardDataHandlers) + require.Equal(t, 1, len(shardDataHandlers)) + require.Equal(t, expectedNonce, shardDataHandlers[0].GetNonce()) + require.NotNil(t, shardDataProposalHandler) + require.Equal(t, int(header.GetNonce()), int(shardDataProposalHandler.GetNonce())) }) } From a6ff0e5e482439565ad0e55592a3844925640650 Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Wed, 5 Nov 2025 12:23:18 +0200 Subject: [PATCH 46/51] MX-17245 Fixes after review --- process/block/shardinfo_test.go | 89 ++++++++++++++++----------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index cbca5476fb1..8de0f7f3544 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -13,10 +13,18 @@ import ( dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/pool" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +func TestShardInfo_IsInterfaceNil(t *testing.T) { + t.Parallel() + var si *ShardInfoCreateData + require.True(t, si.IsInterfaceNil()) + si = &ShardInfoCreateData{} + require.False(t, si.IsInterfaceNil()) +} + func TestShardInfo_NewShardInfoCreateData(t *testing.T) { t.Parallel() @@ -31,9 +39,8 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { args.pendingMiniBlocksHandler, args.blockTracker, ) - assert.Nil(t, sicd) - assert.True(t, sicd.IsInterfaceNil()) - assert.Equal(t, process.ErrNilEnableEpochsHandler, err) + require.Nil(t, sicd) + require.Equal(t, process.ErrNilEnableEpochsHandler, err) }) t.Run("nil headersPool", func(t *testing.T) { @@ -46,9 +53,8 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { args.pendingMiniBlocksHandler, args.blockTracker, ) - assert.Nil(t, sicd) - assert.True(t, sicd.IsInterfaceNil()) - assert.Equal(t, process.ErrNilHeadersDataPool, err) + require.Nil(t, sicd) + require.Equal(t, process.ErrNilHeadersDataPool, err) }) t.Run("nil proofsPool", func(t *testing.T) { @@ -63,9 +69,8 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { args.pendingMiniBlocksHandler, args.blockTracker, ) - assert.Nil(t, sicd) - assert.True(t, sicd.IsInterfaceNil()) - assert.Equal(t, process.ErrNilProofsPool, err) + require.Nil(t, sicd) + require.Equal(t, process.ErrNilProofsPool, err) }) t.Run("nil pendingMiniBlocksHandler", func(t *testing.T) { @@ -80,9 +85,8 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { nil, args.blockTracker, ) - assert.Nil(t, sicd) - assert.True(t, sicd.IsInterfaceNil()) - assert.Equal(t, process.ErrNilPendingMiniBlocksHandler, err) + require.Nil(t, sicd) + require.Equal(t, process.ErrNilPendingMiniBlocksHandler, err) }) t.Run("nil blockTracker", func(t *testing.T) { @@ -96,9 +100,8 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { args.pendingMiniBlocksHandler, nil, ) - assert.Nil(t, sicd) - assert.True(t, sicd.IsInterfaceNil()) - assert.Equal(t, process.ErrNilBlockTracker, err) + require.Nil(t, sicd) + require.Equal(t, process.ErrNilBlockTracker, err) }) t.Run("should work", func(t *testing.T) { t.Parallel() @@ -112,9 +115,8 @@ func TestShardInfo_NewShardInfoCreateData(t *testing.T) { args.pendingMiniBlocksHandler, args.blockTracker, ) - assert.NotNil(t, sicd) - assert.False(t, sicd.IsInterfaceNil()) - assert.Nil(t, err) + require.NotNil(t, sicd) + require.Nil(t, err) }) } @@ -416,7 +418,6 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { require.Nil(t, err) shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(nil, nil) - require.NotNil(t, err) require.Nil(t, shardDataProposalHandlers) require.Nil(t, shardDataHandlers) require.ErrorIs(t, err, process.ErrNilHeaderHandler) @@ -434,7 +435,6 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { require.Nil(t, err) shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(&block.Header{}, []byte{}) - require.NotNil(t, err) require.Nil(t, shardDataProposalHandlers) require.Nil(t, shardDataHandlers) require.ErrorIs(t, err, process.ErrInvalidHash) @@ -456,7 +456,6 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { require.Nil(t, err) shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(&block.Header{Nonce: 1}, []byte("hash")) - require.NotNil(t, err) require.Nil(t, shardDataProposalHandlers) require.Nil(t, shardDataHandlers) require.ErrorIs(t, err, process.ErrMissingHeaderProof) @@ -618,7 +617,7 @@ func TestShardInfoCreateData_createShardDataFromLegacyHeader(t *testing.T) { ) require.Nil(t, err) shardDataList, err := sic.createShardDataFromLegacyHeader(header, []byte("headerHash")) - require.NotNil(t, err) + require.Contains(t, err.Error(), "GetLastSelfNotarizedHeader error") require.Nil(t, shardDataList) }) @@ -694,7 +693,6 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { ) require.Nil(t, err) shardDataProposalHandler, shardDataHandlers, err := sic.createShardDataFromV3Header(nil, nil) - require.NotNil(t, err) require.Nil(t, shardDataHandlers) require.Nil(t, shardDataProposalHandler) require.ErrorIs(t, err, process.ErrNilHeaderHandler) @@ -744,7 +742,6 @@ func TestShardInfoCreateData_createShardDataFromV3Header(t *testing.T) { ) require.Nil(t, err) shardDataProposalHandler, shardDataHandlers, err := sic.createShardDataFromV3Header(header, []byte("headerHash")) - require.NotNil(t, err) require.Nil(t, shardDataHandlers) require.Nil(t, shardDataProposalHandler) require.Equal(t, fmt.Errorf("GetHeaderByHash error"), err) @@ -886,18 +883,18 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { shardData, err := sic.createShardDataFromExecutionResult(execResult) require.Nil(t, err) require.NotNil(t, shardData) - assert.Equal(t, uint32(2), shardData.GetNumPendingMiniBlocks()) - assert.Equal(t, uint32(execResult.GetExecutedTxCount()), shardData.GetTxCount()) - assert.Equal(t, uint32(1), shardData.GetShardID()) - assert.Equal(t, execResult.GetAccumulatedFees(), shardData.GetAccumulatedFees()) - assert.Equal(t, execResult.GetHeaderHash(), shardData.GetHeaderHash()) - assert.Equal(t, execResult.GetHeaderRound(), shardData.GetRound()) - assert.Equal(t, header.GetPrevHash(), shardData.GetPrevHash()) - assert.Equal(t, execResult.GetHeaderNonce(), shardData.GetNonce()) - assert.Equal(t, header.GetPrevRandSeed(), shardData.GetPrevRandSeed()) - assert.Equal(t, header.GetPubKeysBitmap(), shardData.GetPubKeysBitmap()) - assert.Equal(t, execResult.GetAccumulatedFees(), shardData.GetAccumulatedFees()) - assert.Equal(t, execResult.GetDeveloperFees(), shardData.GetDeveloperFees()) + require.Equal(t, uint32(2), shardData.GetNumPendingMiniBlocks()) + require.Equal(t, uint32(execResult.GetExecutedTxCount()), shardData.GetTxCount()) + require.Equal(t, uint32(1), shardData.GetShardID()) + require.Equal(t, execResult.GetAccumulatedFees(), shardData.GetAccumulatedFees()) + require.Equal(t, execResult.GetHeaderHash(), shardData.GetHeaderHash()) + require.Equal(t, execResult.GetHeaderRound(), shardData.GetRound()) + require.Equal(t, header.GetPrevHash(), shardData.GetPrevHash()) + require.Equal(t, execResult.GetHeaderNonce(), shardData.GetNonce()) + require.Equal(t, header.GetPrevRandSeed(), shardData.GetPrevRandSeed()) + require.Equal(t, header.GetPubKeysBitmap(), shardData.GetPubKeysBitmap()) + require.Equal(t, execResult.GetAccumulatedFees(), shardData.GetAccumulatedFees()) + require.Equal(t, execResult.GetDeveloperFees(), shardData.GetDeveloperFees()) require.Equal(t, header.GetEpoch(), shardData.(*block.ShardData).GetEpoch()) }) } @@ -966,11 +963,11 @@ func TestShardInfoCreateData_createShardMiniBlockHeaderFromExecutionResultHandle require.NotNil(t, shardMiniBlockHeaders) require.Equal(t, 3, len(shardMiniBlockHeaders)) for i := 0; i < len(shardMiniBlockHeaders); i++ { - assert.Equal(t, execResultHandler.MiniBlockHeaders[i].Hash, shardMiniBlockHeaders[i].Hash) - assert.Equal(t, execResultHandler.MiniBlockHeaders[i].Type, shardMiniBlockHeaders[i].Type) - assert.Equal(t, execResultHandler.MiniBlockHeaders[i].TxCount, shardMiniBlockHeaders[i].TxCount) - assert.Equal(t, execResultHandler.MiniBlockHeaders[i].SenderShardID, shardMiniBlockHeaders[i].SenderShardID) - assert.Equal(t, execResultHandler.MiniBlockHeaders[i].ReceiverShardID, shardMiniBlockHeaders[i].ReceiverShardID) + require.Equal(t, execResultHandler.MiniBlockHeaders[i].Hash, shardMiniBlockHeaders[i].Hash) + require.Equal(t, execResultHandler.MiniBlockHeaders[i].Type, shardMiniBlockHeaders[i].Type) + require.Equal(t, execResultHandler.MiniBlockHeaders[i].TxCount, shardMiniBlockHeaders[i].TxCount) + require.Equal(t, execResultHandler.MiniBlockHeaders[i].SenderShardID, shardMiniBlockHeaders[i].SenderShardID) + require.Equal(t, execResultHandler.MiniBlockHeaders[i].ReceiverShardID, shardMiniBlockHeaders[i].ReceiverShardID) } } @@ -995,7 +992,7 @@ func TestShardInfoCreateData_updateShardDataWithCrossShardInfo(t *testing.T) { ) require.Nil(t, err) err = sic.updateShardDataWithCrossShardInfo(shardData, &header) - assert.Error(t, err) + require.Contains(t, err.Error(), "GetLastSelfNotarizedHeader error") }) t.Run("should work with no data", func(t *testing.T) { @@ -1017,10 +1014,10 @@ func TestShardInfoCreateData_updateShardDataWithCrossShardInfo(t *testing.T) { ) require.Nil(t, err) err = sic.updateShardDataWithCrossShardInfo(shardData, &header) - assert.NotNil(t, shardData) + require.NotNil(t, shardData) require.Nil(t, err) - assert.Equal(t, uint32(2), shardData.NumPendingMiniBlocks) - assert.Equal(t, uint64(expectedNonce), shardData.LastIncludedMetaNonce) + require.Equal(t, uint32(2), shardData.NumPendingMiniBlocks) + require.Equal(t, uint64(expectedNonce), shardData.LastIncludedMetaNonce) }) } From 1d3fc910d37ccab3c7f586cfa448513e9cc9f3a8 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Wed, 5 Nov 2025 13:19:22 +0200 Subject: [PATCH 47/51] fix after merge --- dblookupext/common.go | 3 ++- dblookupext/esdtSupply/esdtSuppliesProcessor.go | 5 +++-- go.sum | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/dblookupext/common.go b/dblookupext/common.go index 641ae506bcb..396d4cd896c 100644 --- a/dblookupext/common.go +++ b/dblookupext/common.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/storage" @@ -61,7 +62,7 @@ func getIntraMbs(cache storage.Cacher, marshaller marshal.Marshalizer, headerHas } func getBody(cache storage.Cacher, marshaller marshal.Marshalizer, baseExecResult data.BaseExecutionResultHandler, shardID uint32) (*block.Body, error) { - miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecResult, shardID) + miniBlockHeaderHandlers, err := common.GetMiniBlocksHeaderHandlersFromExecResult(baseExecResult) if err != nil { return nil, err } diff --git a/dblookupext/esdtSupply/esdtSuppliesProcessor.go b/dblookupext/esdtSupply/esdtSuppliesProcessor.go index bd23a50774f..0a09f1668a8 100644 --- a/dblookupext/esdtSupply/esdtSuppliesProcessor.go +++ b/dblookupext/esdtSupply/esdtSuppliesProcessor.go @@ -10,9 +10,10 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/storage" - logger "github.com/multiversx/mx-chain-logger-go" ) var log = logger.GetOrCreate("dblookupext/esdtSupply") @@ -89,7 +90,7 @@ func (sp *suppliesProcessor) RevertChanges(header data.HeaderHandler, body data. func (sp *suppliesProcessor) revertChangesBasedOnExecutionResults(header data.HeaderHandler) error { for _, executionResult := range header.GetExecutionResultsHandlers() { - mbHeaders, err := common.GetMiniBlocksHeaderHandlersFromExecResult(executionResult, header.GetShardID()) + mbHeaders, err := common.GetMiniBlocksHeaderHandlersFromExecResult(executionResult) if err != nil { return err } diff --git a/go.sum b/go.sum index b3fd028fdde..89a13e151a3 100644 --- a/go.sum +++ b/go.sum @@ -401,8 +401,8 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-communication-go v1.3.0 h1:ziNM1dRuiR/7al2L/jGEA/a/hjurtJ/HEqgazHNt9P8= github.com/multiversx/mx-chain-communication-go v1.3.0/go.mod h1:gDVWn6zUW6aCN1YOm/FbbT5MUmhgn/L1Rmpl8EoH3Yg= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251028132358-ff06ba9e2822 h1:BsbYhJaA70o9wt4boKslLau+f98IsOxZAMex8LcrbQw= -github.com/multiversx/mx-chain-core-go v1.4.2-0.20251028132358-ff06ba9e2822/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251104092828-1dd9514c928a h1:sOp+4UkIJNbLFlpefo3G1cFKjYnVbMIpVbQsTSZzooo= +github.com/multiversx/mx-chain-core-go v1.4.2-0.20251104092828-1dd9514c928a/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g= github.com/multiversx/mx-chain-crypto-go v1.3.0 h1:0eK2bkDOMi8VbSPrB1/vGJSYT81IBtfL4zw+C4sWe/k= github.com/multiversx/mx-chain-crypto-go v1.3.0/go.mod h1:nPIkxxzyTP8IquWKds+22Q2OJ9W7LtusC7cAosz7ojM= github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251021150757-bd6aa66a0a90 h1:Hf6AqpCSHccBo5ZV5Bfaxz3UdPYhtYCynU+3CF4jAa8= From 0f1b025187baeaac747a24314e44604d4cc2b80b Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Thu, 6 Nov 2025 11:03:02 +0200 Subject: [PATCH 48/51] MX-17245 Fixes after review --- process/block/shardinfo_test.go | 188 +++++++++++++++++--------------- 1 file changed, 102 insertions(+), 86 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 8de0f7f3544..27ea36c4aa1 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -1,6 +1,7 @@ package block import ( + "bytes" "fmt" "testing" @@ -12,7 +13,7 @@ import ( "github.com/multiversx/mx-chain-go/process/mock" dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" - "github.com/multiversx/mx-chain-go/testscommon/pool" + poolMock "github.com/multiversx/mx-chain-go/testscommon/pool" "github.com/stretchr/testify/require" ) @@ -144,37 +145,30 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { round := uint64(10) metaHdrV3 := &block.MetaBlockV3{Round: round} + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + pool.Headers(), + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) t.Run("should fail with nil meta header", func(t *testing.T) { t.Parallel() - args := createDefaultShardInfoCreateDataArgs() - sic, err := NewShardInfoCreateData( - args.enableEpochsHandler, - pool.Headers(), - args.proofsPool, - args.pendingMiniBlocksHandler, - args.blockTracker, - ) - require.Nil(t, err) + shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(nil, headers, headerHashes) require.ErrorIs(t, err, process.ErrNilHeaderHandler) require.Nil(t, shardDataProposalHandlers) require.Nil(t, shardDataHandlers) }) - t.Run("should fail with Legacy meta header", func(t *testing.T) { + t.Run("should fail with legacy meta header", func(t *testing.T) { t.Parallel() metaHdr := &block.MetaBlock{Round: round} - args := createDefaultShardInfoCreateDataArgs() - sic, err := NewShardInfoCreateData( - args.enableEpochsHandler, - pool.Headers(), - args.proofsPool, - args.pendingMiniBlocksHandler, - args.blockTracker, - ) - require.Nil(t, err) + shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(metaHdr, headers, headerHashes) require.Equal(t, process.ErrInvalidHeader, err) require.Nil(t, shardDataProposalHandlers) @@ -183,15 +177,6 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { t.Run("should fail with inconsistent headers and hashes", func(t *testing.T) { t.Parallel() - args := createDefaultShardInfoCreateDataArgs() - sic, err := NewShardInfoCreateData( - args.enableEpochsHandler, - pool.Headers(), - args.proofsPool, - args.pendingMiniBlocksHandler, - args.blockTracker, - ) - require.Nil(t, err) shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes[:2]) require.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) require.Nil(t, shardDataProposalHandlers) @@ -200,15 +185,6 @@ func TestShardInfoCreateData_CreateShardInfoV3(t *testing.T) { t.Run("should fail when createShardInfoFromHeader errors", func(t *testing.T) { t.Parallel() - args := createDefaultShardInfoCreateDataArgs() - sic, err := NewShardInfoCreateData( - args.enableEpochsHandler, - pool.Headers(), - args.proofsPool, - args.pendingMiniBlocksHandler, - args.blockTracker, - ) - require.Nil(t, err) shardDataProposalHandlers, shardDataHandlers, err := sic.CreateShardInfoV3(metaHdrV3, headers, headerHashes) require.Contains(t, err.Error(), process.ErrMissingHeaderProof.Error()) require.Nil(t, shardDataProposalHandlers) @@ -294,17 +270,18 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { round := uint64(10) metaHdr := &block.MetaBlock{Round: round} + args := createDefaultShardInfoCreateDataArgs() + sic, err := NewShardInfoCreateData( + args.enableEpochsHandler, + args.headersPool, + args.proofsPool, + args.pendingMiniBlocksHandler, + args.blockTracker, + ) + require.Nil(t, err) t.Run("should fail with nil meta header", func(t *testing.T) { t.Parallel() - args := createDefaultShardInfoCreateDataArgs() - sic, err := NewShardInfoCreateData( - args.enableEpochsHandler, - args.headersPool, - args.proofsPool, - args.pendingMiniBlocksHandler, - args.blockTracker, - ) - require.Nil(t, err) + shardInfo, err := sic.CreateShardInfoFromLegacyMeta(nil, headers, headerHashes) require.Equal(t, process.ErrNilHeaderHandler, err) require.Nil(t, shardInfo) @@ -312,16 +289,7 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { t.Run("should fail with V3 meta header", func(t *testing.T) { t.Parallel() - args := createDefaultShardInfoCreateDataArgs() metaHdrV3 := &block.MetaBlockV3{Round: round} - sic, err := NewShardInfoCreateData( - args.enableEpochsHandler, - args.headersPool, - args.proofsPool, - args.pendingMiniBlocksHandler, - args.blockTracker, - ) - require.Nil(t, err) shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdrV3, headers, headerHashes) require.Equal(t, process.ErrInvalidHeader, err) require.Nil(t, shardInfo) @@ -329,15 +297,6 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { t.Run("should fail with inconsistent headers and hashes", func(t *testing.T) { t.Parallel() - args := createDefaultShardInfoCreateDataArgs() - sic, err := NewShardInfoCreateData( - args.enableEpochsHandler, - args.headersPool, - args.proofsPool, - args.pendingMiniBlocksHandler, - args.blockTracker, - ) - require.Nil(t, err) shardInfo, err := sic.CreateShardInfoFromLegacyMeta(metaHdr, headers, headerHashes[:1]) require.Equal(t, process.ErrInconsistentShardHeadersAndHashes, err) require.Nil(t, shardInfo) @@ -346,7 +305,6 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { t.Run("should fail when createShardDataFromLegacyHeader errors", func(t *testing.T) { t.Parallel() - errExpected := fmt.Errorf("GetLastSelfNotarizedHeader error") args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -405,6 +363,7 @@ func TestShardInfoCreateData_CreateShardInfoFromLegacyMeta(t *testing.T) { func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { t.Parallel() + t.Run("should fail with nil header", func(t *testing.T) { t.Parallel() args := createDefaultShardInfoCreateDataArgs() @@ -484,16 +443,24 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { args.blockTracker, ) require.Nil(t, err) + expectedProposalHandler := &block.ShardDataProposal{ + HeaderHash: []byte("hash"), + Round: 10, + Nonce: 45, + ShardID: 1, + Epoch: 0, + } - shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataProposalHandler) require.NotNil(t, shardDataHandlers) + require.Equal(t, expectedProposalHandler, shardDataProposalHandler) }) - t.Run("should work with Legacy no proof for epoch < 1", func(t *testing.T) { + t.Run("should work with Legacy no proof for nonce < 1", func(t *testing.T) { t.Parallel() header := getShardHeaderForShard(uint32(1)) - header.(*block.HeaderV2).SetNonce(0) + header.SetNonce(0) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -515,11 +482,19 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { args.blockTracker, ) require.Nil(t, err) + expectedProposalHandler := &block.ShardDataProposal{ + HeaderHash: []byte("hash"), + Round: 10, + Nonce: 0, + ShardID: 1, + Epoch: 0, + } - shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataProposalHandler) require.NotNil(t, shardDataHandlers) + require.Equal(t, expectedProposalHandler, shardDataProposalHandler) }) t.Run("should work with V3", func(t *testing.T) { t.Parallel() @@ -549,17 +524,25 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { args.blockTracker, ) require.Nil(t, err) + expectedProposalHandler := &block.ShardDataProposal{ + HeaderHash: []byte("hash"), + Round: 10, + Nonce: 45, + ShardID: 1, + Epoch: 7, + } - shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataProposalHandler) require.NotNil(t, shardDataHandlers) + require.Equal(t, expectedProposalHandler, shardDataProposalHandler) }) t.Run("should work with V3 no proof for nonce < 1", func(t *testing.T) { t.Parallel() header := getHeaderV3ForShard(uint32(1), []byte("header hash for shard 1")) expectedNonce := uint64(0) - header.(*block.HeaderV3).SetNonce(expectedNonce) + _ = header.SetNonce(expectedNonce) args := createDefaultShardInfoCreateDataArgs() args.headersPool.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { return header, nil @@ -584,11 +567,19 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { args.blockTracker, ) require.Nil(t, err) + expectedProposalHandler := &block.ShardDataProposal{ + HeaderHash: []byte("hash"), + Round: 10, + Nonce: 0, + ShardID: 1, + Epoch: 7, + } - shardDataProposalHandlers, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) + shardDataProposalHandler, shardDataHandlers, err := sic.createShardInfoFromHeader(header, []byte("hash")) require.Nil(t, err) - require.NotNil(t, shardDataProposalHandlers) + require.NotNil(t, shardDataProposalHandler) require.NotNil(t, shardDataHandlers) + require.Equal(t, expectedProposalHandler, shardDataProposalHandler) }) } @@ -809,8 +800,7 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { args.blockTracker, ) require.Nil(t, err) - var execResult data.BaseExecutionResultHandler = &block.BaseExecutionResult{} - shardData, err := sic.createShardDataFromExecutionResult(execResult) + shardData, err := sic.createShardDataFromExecutionResult(&block.BaseExecutionResult{}) require.ErrorIs(t, err, process.ErrWrongTypeAssertion) require.Nil(t, shardData) }) @@ -853,7 +843,7 @@ func TestShardInfoCreateData_createShardDataFromExecutionResult(t *testing.T) { require.Nil(t, err) execResult := getExecutionResultForShard(uint32(1), []byte("header hash for shard 1")) shardData, err := sic.createShardDataFromExecutionResult(execResult) - require.Equal(t, fmt.Errorf("notarized headers slice is nil"), err) + require.Equal(t, process.ErrNotarizedHeadersSliceIsNil, err) require.Nil(t, shardData) }) @@ -910,6 +900,9 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) require.NotNil(t, miniblockHeaders) require.Equal(t, 3, len(miniblockHeaders)) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0])) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[1], miniblockHeaders[1])) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[2])) }) t.Run("ScheduledMiniBlocksFlag enabled, all miniblocks final", func(t *testing.T) { t.Parallel() @@ -922,6 +915,9 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) require.NotNil(t, miniblockHeaders) require.Equal(t, 3, len(miniblockHeaders)) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0])) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[1], miniblockHeaders[1])) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[2])) }) t.Run("ScheduledMiniBlocksFlag enabled, not all miniblocks final", func(t *testing.T) { t.Parallel() @@ -936,6 +932,8 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) require.NotNil(t, miniblockHeaders) require.Equal(t, 2, len(miniblockHeaders)) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0])) + require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[1])) }) t.Run("ScheduledMiniBlocksFlag enabled, no final miniblocks", func(t *testing.T) { t.Parallel() @@ -1019,11 +1017,10 @@ func TestShardInfoCreateData_updateShardDataWithCrossShardInfo(t *testing.T) { require.Equal(t, uint32(2), shardData.NumPendingMiniBlocks) require.Equal(t, uint64(expectedNonce), shardData.LastIncludedMetaNonce) }) - } type shardInfoCreateDataTestArgs struct { - headersPool *pool.HeadersPoolStub + headersPool *poolMock.HeadersPoolStub proofsPool *dataRetrieverMock.ProofsPoolMock pendingMiniBlocksHandler *mock.PendingMiniBlocksHandlerStub blockTracker *mock.BlockTrackerMock @@ -1032,7 +1029,7 @@ type shardInfoCreateDataTestArgs struct { func createDefaultShardInfoCreateDataArgs() *shardInfoCreateDataTestArgs { return &shardInfoCreateDataTestArgs{ - headersPool: &pool.HeadersPoolStub{}, + headersPool: &poolMock.HeadersPoolStub{}, proofsPool: &dataRetrieverMock.ProofsPoolMock{}, pendingMiniBlocksHandler: &mock.PendingMiniBlocksHandlerStub{}, blockTracker: &mock.BlockTrackerMock{}, @@ -1079,7 +1076,7 @@ func getShardHeaderForShard(shardID uint32) data.HeaderHandler { Header: &block.Header{ Round: 10, Nonce: 45, - ShardID: 1, + ShardID: shardID, PrevRandSeed: prevRandSeed, RandSeed: currRandSeed, PrevHash: prevHash, @@ -1096,7 +1093,7 @@ func getHeaderV3ForShard(shardID uint32, hash []byte) data.HeaderHandler { Epoch: 7, Round: 10, Nonce: 45, - ShardID: 1, + ShardID: shardID, PrevRandSeed: prevRandSeed, RandSeed: currRandSeed, PrevHash: prevHash, @@ -1106,7 +1103,6 @@ func getHeaderV3ForShard(shardID uint32, hash []byte) data.HeaderHandler { } func getExecutionResultForShard(shardID uint32, hash []byte) *block.ExecutionResult { - return &block.ExecutionResult{ ExecutedTxCount: 100, MiniBlockHeaders: getMiniBlockHeadersForShard(shardID), @@ -1120,3 +1116,23 @@ func getExecutionResultForShard(shardID uint32, hash []byte) *block.ExecutionRes }, } } + +// compares only the fields that are set in createShardMiniBlockHeaderFromExecutionResultHandler +func isMiniBlockHeaderComparable(mbHeader1 data.MiniBlockHeaderHandler, mbHeader2 block.MiniBlockHeader) bool { + if !bytes.Equal(mbHeader1.GetHash(), mbHeader2.Hash) { + return false + } + if block.Type(mbHeader1.GetTypeInt32()) != mbHeader2.Type { + return false + } + if mbHeader1.GetTxCount() != mbHeader2.TxCount { + return false + } + if mbHeader1.GetSenderShardID() != mbHeader2.SenderShardID { + return false + } + if mbHeader1.GetReceiverShardID() != mbHeader2.ReceiverShardID { + return false + } + return true +} From d6cd4cb948706c23b166318125b9a88c3e42682d Mon Sep 17 00:00:00 2001 From: Mihaela Radian Date: Thu, 6 Nov 2025 12:13:18 +0200 Subject: [PATCH 49/51] MX-17245 Fixes after re-review --- process/block/shardinfo_test.go | 44 ++++++++++++--------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index 27ea36c4aa1..e9a69a13010 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -1,7 +1,6 @@ package block import ( - "bytes" "fmt" "testing" @@ -460,7 +459,7 @@ func TestShardInfoCreateData_createShardInfoFromHeader(t *testing.T) { t.Run("should work with Legacy no proof for nonce < 1", func(t *testing.T) { t.Parallel() header := getShardHeaderForShard(uint32(1)) - header.SetNonce(0) + _ = header.SetNonce(0) args := createDefaultShardInfoCreateDataArgs() args.pendingMiniBlocksHandler.GetPendingMiniBlocksCalled = func(shardID uint32) [][]byte { return [][]byte{[]byte("hash1"), []byte("hash2")} @@ -900,9 +899,9 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) require.NotNil(t, miniblockHeaders) require.Equal(t, 3, len(miniblockHeaders)) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0])) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[1], miniblockHeaders[1])) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[2])) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0]) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[1], miniblockHeaders[1]) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[2]) }) t.Run("ScheduledMiniBlocksFlag enabled, all miniblocks final", func(t *testing.T) { t.Parallel() @@ -915,9 +914,9 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) require.NotNil(t, miniblockHeaders) require.Equal(t, 3, len(miniblockHeaders)) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0])) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[1], miniblockHeaders[1])) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[2])) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0]) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[1], miniblockHeaders[1]) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[2]) }) t.Run("ScheduledMiniBlocksFlag enabled, not all miniblocks final", func(t *testing.T) { t.Parallel() @@ -932,8 +931,8 @@ func TestShardInfoCreateData_miniBlockHeaderFromMiniBlockHeader(t *testing.T) { miniblockHeaders := createShardMiniBlockHeaderFromHeader(headerHandler, enableEpochsHandler) require.NotNil(t, miniblockHeaders) require.Equal(t, 2, len(miniblockHeaders)) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0])) - require.True(t, isMiniBlockHeaderComparable(headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[1])) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[0], miniblockHeaders[0]) + checkMiniBlockHeadersComparable(t, headerHandler.GetMiniBlockHeaderHandlers()[2], miniblockHeaders[1]) }) t.Run("ScheduledMiniBlocksFlag enabled, no final miniblocks", func(t *testing.T) { t.Parallel() @@ -1015,7 +1014,7 @@ func TestShardInfoCreateData_updateShardDataWithCrossShardInfo(t *testing.T) { require.NotNil(t, shardData) require.Nil(t, err) require.Equal(t, uint32(2), shardData.NumPendingMiniBlocks) - require.Equal(t, uint64(expectedNonce), shardData.LastIncludedMetaNonce) + require.Equal(t, expectedNonce, shardData.LastIncludedMetaNonce) }) } @@ -1118,21 +1117,10 @@ func getExecutionResultForShard(shardID uint32, hash []byte) *block.ExecutionRes } // compares only the fields that are set in createShardMiniBlockHeaderFromExecutionResultHandler -func isMiniBlockHeaderComparable(mbHeader1 data.MiniBlockHeaderHandler, mbHeader2 block.MiniBlockHeader) bool { - if !bytes.Equal(mbHeader1.GetHash(), mbHeader2.Hash) { - return false - } - if block.Type(mbHeader1.GetTypeInt32()) != mbHeader2.Type { - return false - } - if mbHeader1.GetTxCount() != mbHeader2.TxCount { - return false - } - if mbHeader1.GetSenderShardID() != mbHeader2.SenderShardID { - return false - } - if mbHeader1.GetReceiverShardID() != mbHeader2.ReceiverShardID { - return false - } - return true +func checkMiniBlockHeadersComparable(t *testing.T, mbHeader1 data.MiniBlockHeaderHandler, mbHeader2 block.MiniBlockHeader) { + require.Equal(t, mbHeader1.GetHash(), mbHeader2.Hash) + require.Equal(t, block.Type(mbHeader1.GetTypeInt32()), mbHeader2.Type) + require.Equal(t, mbHeader1.GetTxCount(), mbHeader2.TxCount) + require.Equal(t, mbHeader1.GetSenderShardID(), mbHeader2.SenderShardID) + require.Equal(t, mbHeader1.GetReceiverShardID(), mbHeader2.ReceiverShardID) } From b71641da44668a4745e1957aa7c48a6be5f5cd38 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Thu, 6 Nov 2025 13:14:00 +0200 Subject: [PATCH 50/51] fixes after review --- process/block/baseProcess.go | 8 +------- process/block/mbsSelectionSession.go | 6 +++--- process/block/metablock.go | 4 ++-- process/block/metablockProposal.go | 5 ++++- process/block/metablockProposal_test.go | 2 +- process/block/shardblockProposal.go | 3 +++ 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 5febdbaab6a..b508ff65af1 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -2802,16 +2802,10 @@ func (bp *baseProcessor) createMbsCrossShardDstMe( "hash", currentBlockHash, "num mbs added", len(currMiniBlocksAdded), "num txs added", currNumTxsAdded) - - return &CrossShardIncomingMbsCreationResult{ - HeaderFinished: false, - PendingMiniBlocks: pendingMiniBlocks, - AddedMiniBlocks: currMiniBlocksAdded, - }, nil } return &CrossShardIncomingMbsCreationResult{ - HeaderFinished: true, + HeaderFinished: hdrFinished, PendingMiniBlocks: pendingMiniBlocks, AddedMiniBlocks: currMiniBlocksAdded, }, nil diff --git a/process/block/mbsSelectionSession.go b/process/block/mbsSelectionSession.go index 213079fde8d..2af925d89cc 100644 --- a/process/block/mbsSelectionSession.go +++ b/process/block/mbsSelectionSession.go @@ -131,13 +131,13 @@ func (s *miniBlocksSelectionSession) GetMiniBlockHashes() [][]byte { // AddReferencedHeader adds a header and its hash to the session func (s *miniBlocksSelectionSession) AddReferencedHeader(header data.HeaderHandler, headerHash []byte) { - s.mut.Lock() - defer s.mut.Unlock() - if check.IfNil(header) || len(headerHash) == 0 { return } + s.mut.Lock() + defer s.mut.Unlock() + _, ok := s.referenceHeaderHashesUnique[string(headerHash)] if !ok { s.referenceHeaderHashesUnique[string(headerHash)] = struct{}{} diff --git a/process/block/metablock.go b/process/block/metablock.go index 09d85dccce7..e24236b8bdf 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -1725,7 +1725,7 @@ func (mp *metaProcessor) saveLastNotarizedHeader(header *block.MetaBlock) error } func (mp *metaProcessor) getLastCrossNotarizedShardHdrsAndAddToCurrentBlock() (map[uint32]data.HeaderHandler, error) { - lastCrossNotarizedHeader, err := mp.getLastCrossNotarizedShardHdrs() + lastCrossNotarizedHeader, err := mp.getLastCrossNotarizedShardHeaders() if err != nil { return nil, err } @@ -1739,7 +1739,7 @@ func (mp *metaProcessor) getLastCrossNotarizedShardHdrsAndAddToCurrentBlock() (m return headers, nil } -func (mp *metaProcessor) getLastCrossNotarizedShardHdrs() (map[uint32]ShardHeaderInfo, error) { +func (mp *metaProcessor) getLastCrossNotarizedShardHeaders() (map[uint32]ShardHeaderInfo, error) { lastCrossNotarizedHeader := make(map[uint32]ShardHeaderInfo, mp.shardCoordinator.NumberOfShards()) for shardID := uint32(0); shardID < mp.shardCoordinator.NumberOfShards(); shardID++ { lastCrossNotarizedHeaderForShard, hash, err := mp.blockTracker.GetLastCrossNotarizedHeader(shardID) diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index f3396987d5e..07fd3b2f2bb 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -279,7 +279,7 @@ func (mp *metaProcessor) selectIncomingMiniBlocksForProposal( "num shard headers", len(orderedHdrs), ) - lastShardHdr, err := mp.getLastCrossNotarizedShardHdrs() + lastShardHdr, err := mp.getLastCrossNotarizedShardHeaders() if err != nil { return err } @@ -400,5 +400,8 @@ func (mp *metaProcessor) selectIncomingMiniBlocks( hdrsAdded++ } + // TODO: wold need to request in advance new shard headers and proofs if last added headers are old (on an old epoch) + // maybe move this logic in processing a block, so it is common for all nodes in shard. + return nil } diff --git a/process/block/metablockProposal_test.go b/process/block/metablockProposal_test.go index 9d4e66cc9bb..799e9224ec3 100644 --- a/process/block/metablockProposal_test.go +++ b/process/block/metablockProposal_test.go @@ -1087,7 +1087,7 @@ func TestMetaProcessor_selectIncomingMiniBlocksForProposal(t *testing.T) { err = mp.SelectIncomingMiniBlocksForProposal(haveTimeTrue) require.Equal(t, expectedErr, err) }) - t.Run("error from getLastCrossNotarizedShardHdrs", func(t *testing.T) { + t.Run("error from getLastCrossNotarizedShardHeaders", func(t *testing.T) { t.Parallel() coreComponents, dataComponents, bootstrapComponents, statusComponents := createMockComponentHolders() diff --git a/process/block/shardblockProposal.go b/process/block/shardblockProposal.go index 65e40118ee5..edfae140094 100644 --- a/process/block/shardblockProposal.go +++ b/process/block/shardblockProposal.go @@ -30,6 +30,9 @@ func (sp *shardProcessor) CreateNewHeaderProposal(round uint64, nonce uint64) (d if !ok { return nil, process.ErrWrongTypeAssertion } + if !shardHeader.IsHeaderV3() { + return nil, process.ErrInvalidHeader + } err := shardHeader.SetRound(round) if err != nil { From 5e15a6091f33ba88e9c6a5121f444455f59c0e20 Mon Sep 17 00:00:00 2001 From: Adrian Dobrita Date: Thu, 6 Nov 2025 13:17:53 +0200 Subject: [PATCH 51/51] sort imports --- process/block/shardinfo_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/process/block/shardinfo_test.go b/process/block/shardinfo_test.go index e9a69a13010..b0f4d76f982 100644 --- a/process/block/shardinfo_test.go +++ b/process/block/shardinfo_test.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/mock"