From f5192bb33c891493c3440af50ded24dfc2586687 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Fri, 27 Mar 2026 12:07:27 +0200 Subject: [PATCH 01/12] drop proofs and headers received too late in the next round --- process/interface.go | 2 ++ process/mock/rounderMock.go | 6 ++++- process/track/baseBlockTrack.go | 16 ++++++++++++ process/track/baseBlockTrack_test.go | 38 +++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/process/interface.go b/process/interface.go index 0b168bb6529..7a5e7a80bfa 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1189,6 +1189,8 @@ type RoundTimeDurationHandler interface { type RoundHandler interface { Index() int64 TimeDuration() time.Duration + RemainingTime(startTime time.Time, maxTime time.Duration) time.Duration + TimeStamp() time.Time IsInterfaceNil() bool } diff --git a/process/mock/rounderMock.go b/process/mock/rounderMock.go index 5f1234c3aa6..1c88a8213fc 100644 --- a/process/mock/rounderMock.go +++ b/process/mock/rounderMock.go @@ -11,6 +11,7 @@ type RoundHandlerMock struct { RoundTimeStamp time.Time RoundTimeDuration time.Duration BeforeGenesisCalled func() bool + RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration } // BeforeGenesis - @@ -55,7 +56,10 @@ func (rndm *RoundHandlerMock) UpdateRound(genesisRoundTimeStamp time.Time, timeS } // RemainingTime - -func (rndm *RoundHandlerMock) RemainingTime(_ time.Time, _ time.Duration) time.Duration { +func (rndm *RoundHandlerMock) RemainingTime(startTime time.Time, maxTime time.Duration) time.Duration { + if rndm.RemainingTimeCalled != nil { + return rndm.RemainingTimeCalled(startTime, maxTime) + } return rndm.RoundTimeDuration } diff --git a/process/track/baseBlockTrack.go b/process/track/baseBlockTrack.go index 424671e981f..221578d24d3 100644 --- a/process/track/baseBlockTrack.go +++ b/process/track/baseBlockTrack.go @@ -5,6 +5,7 @@ import ( "fmt" "sort" "sync" + "time" "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" @@ -25,6 +26,9 @@ var log = logger.GetOrCreate("process/track") const maxNonceDifference = 3 // TODO move this to a config file +// receivedProofDelay is the fraction of the full round time to accept a proof +const receivedProofDelay = 0.5 + // HeaderInfo holds the information about a header type HeaderInfo struct { Hash []byte @@ -494,6 +498,18 @@ func (bbt *baseBlockTrack) checkAgainstRoundHandler(round uint64) error { nextRound) } + currentRoundStart := bbt.roundHandler.TimeStamp() + roundDuration := float64(bbt.roundHandler.TimeDuration()) + maxTimeToAcceptProof := time.Duration(roundDuration + roundDuration*receivedProofDelay) + timeLeftToAcceptProof := bbt.roundHandler.RemainingTime(currentRoundStart, maxTimeToAcceptProof) + if timeLeftToAcceptProof <= 0 { + return fmt.Errorf("%w header round: %d, current round timestamp: %d, time left to accept proof: %d", + process.ErrHigherRoundInBlock, + round, + currentRoundStart.UnixMilli(), + timeLeftToAcceptProof.Milliseconds()) + } + return nil } diff --git a/process/track/baseBlockTrack_test.go b/process/track/baseBlockTrack_test.go index efc9d0ccc67..92321340fbf 100644 --- a/process/track/baseBlockTrack_test.go +++ b/process/track/baseBlockTrack_test.go @@ -5,6 +5,7 @@ import ( "fmt" "sync" "testing" + "time" "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" @@ -2371,7 +2372,9 @@ func TestBaseBlockTrack_CheckBlockAgainstRoundHandlerShouldWork(t *testing.T) { currentRound := int64(50) bbt.SetRoundHandler( &mock.RoundHandlerMock{ - RoundIndex: currentRound, + RoundIndex: currentRound, + RoundTimeStamp: time.Now(), + RoundTimeDuration: time.Second, }, ) @@ -2383,6 +2386,39 @@ func TestBaseBlockTrack_CheckBlockAgainstRoundHandlerShouldWork(t *testing.T) { assert.Nil(t, err) } +func TestBaseBlockTrack_CheckBlockAgainstRoundHandlerShouldFailOnInvalidWindow(t *testing.T) { + t.Parallel() + + bbt := track.NewBaseBlockTrack() + currentRound := int64(50) + roundDuration := time.Millisecond * 200 + bbt.SetRoundHandler( + &mock.RoundHandlerMock{ + RoundIndex: currentRound, + RoundTimeStamp: time.Now(), + RoundTimeDuration: roundDuration, + RemainingTimeCalled: func(startTime time.Time, maxTime time.Duration) time.Duration { + currentTime := time.Now() + elapsedTime := currentTime.Sub(startTime) + remainingTime := maxTime - elapsedTime + + return remainingTime + }, + }, + ) + + hdr := &block.Header{ + Round: uint64(currentRound + 1), // proper round but received too late + } + + // wait until after half of the next round passed + timeToSleep := roundDuration + time.Duration(float64(roundDuration)*0.6) + time.Sleep(timeToSleep) + err := bbt.CheckBlockAgainstRoundHandler(hdr) + require.ErrorIs(t, err, process.ErrHigherRoundInBlock) + require.Contains(t, err.Error(), "current round timestamp") +} + // ------- CheckBlockAgainstFinal func TestBaseBlockTrack_CheckBlockAgainstFinalNilHeaderShouldErr(t *testing.T) { From 47e280eb3fc1855a017935d4c3e6f1004bad9ae5 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Fri, 27 Mar 2026 12:51:35 +0200 Subject: [PATCH 02/12] fix tests --- integrationTests/testProcessorNode.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index 0a4f06b6d14..ce145e50daf 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -3540,7 +3540,10 @@ func (tpn *TestProcessorNode) MiniBlocksPresent(hashes [][]byte) bool { } func (tpn *TestProcessorNode) initRoundHandler(roundTime time.Duration) { - tpn.RoundHandler = &mock.RoundHandlerMock{TimeDurationField: roundTime} + tpn.RoundHandler = &mock.RoundHandlerMock{ + TimeDurationField: roundTime, + RemainingTimeField: roundTime, + } } func (tpn *TestProcessorNode) initRequestedItemsHandler() { From ed3e604c9877da70db5a262bcdab46d247e47842 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu <34831323+sstanculeanu@users.noreply.github.com> Date: Mon, 30 Mar 2026 13:21:05 +0300 Subject: [PATCH 03/12] Update process/track/baseBlockTrack.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- process/track/baseBlockTrack.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/process/track/baseBlockTrack.go b/process/track/baseBlockTrack.go index 221578d24d3..d367c9b509d 100644 --- a/process/track/baseBlockTrack.go +++ b/process/track/baseBlockTrack.go @@ -26,7 +26,8 @@ var log = logger.GetOrCreate("process/track") const maxNonceDifference = 3 // TODO move this to a config file -// receivedProofDelay is the fraction of the full round time to accept a proof +// receivedProofDelay is the extra fraction of one full round time during which +// a proof is still accepted, i.e. total allowed time = roundDuration * (1 + receivedProofDelay) const receivedProofDelay = 0.5 // HeaderInfo holds the information about a header From d66e7bfce30327f192ee558d9fbb65f9953b95dd Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 30 Mar 2026 13:30:44 +0300 Subject: [PATCH 04/12] fixes after copilot --- process/interface.go | 2 +- process/track/baseBlockTrack.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/process/interface.go b/process/interface.go index 7a5e7a80bfa..e3c175da651 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1190,7 +1190,7 @@ type RoundHandler interface { Index() int64 TimeDuration() time.Duration RemainingTime(startTime time.Time, maxTime time.Duration) time.Duration - TimeStamp() time.Time + GetTimeStampForRound(round uint64) uint64 IsInterfaceNil() bool } diff --git a/process/track/baseBlockTrack.go b/process/track/baseBlockTrack.go index d367c9b509d..862a4958078 100644 --- a/process/track/baseBlockTrack.go +++ b/process/track/baseBlockTrack.go @@ -499,15 +499,15 @@ func (bbt *baseBlockTrack) checkAgainstRoundHandler(round uint64) error { nextRound) } - currentRoundStart := bbt.roundHandler.TimeStamp() + roundTimestamp := time.UnixMilli(int64(bbt.roundHandler.GetTimeStampForRound(round))) roundDuration := float64(bbt.roundHandler.TimeDuration()) maxTimeToAcceptProof := time.Duration(roundDuration + roundDuration*receivedProofDelay) - timeLeftToAcceptProof := bbt.roundHandler.RemainingTime(currentRoundStart, maxTimeToAcceptProof) + timeLeftToAcceptProof := bbt.roundHandler.RemainingTime(roundTimestamp, maxTimeToAcceptProof) if timeLeftToAcceptProof <= 0 { return fmt.Errorf("%w header round: %d, current round timestamp: %d, time left to accept proof: %d", process.ErrHigherRoundInBlock, round, - currentRoundStart.UnixMilli(), + roundTimestamp.UnixMilli(), timeLeftToAcceptProof.Milliseconds()) } From 7dc66fdef36849a82dff3890b3ef8500e694c432 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 30 Mar 2026 13:53:57 +0300 Subject: [PATCH 05/12] fixed linter --- epochStart/mock/rounderStub.go | 20 +++++++++++++++----- process/mock/roundStub.go | 20 +++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/epochStart/mock/rounderStub.go b/epochStart/mock/rounderStub.go index c1d6b86675a..4c3539e87b6 100644 --- a/epochStart/mock/rounderStub.go +++ b/epochStart/mock/rounderStub.go @@ -8,11 +8,12 @@ import ( type RoundHandlerStub struct { RoundIndex int64 - IndexCalled func() int64 - TimeDurationCalled func() time.Duration - TimeStampCalled func() time.Time - UpdateRoundCalled func(time.Time, time.Time) - RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration + IndexCalled func() int64 + TimeDurationCalled func() time.Duration + TimeStampCalled func() time.Time + UpdateRoundCalled func(time.Time, time.Time) + RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration + GetTimeStampForRoundCalled func(round uint64) uint64 } // Index - @@ -61,6 +62,15 @@ func (rndm *RoundHandlerStub) RemainingTime(startTime time.Time, maxTime time.Du return 4000 * time.Millisecond } +// GetTimeStampForRound - +func (rndm *RoundHandlerStub) GetTimeStampForRound(round uint64) uint64 { + if rndm.GetTimeStampForRoundCalled != nil { + return rndm.GetTimeStampForRoundCalled(round) + } + + return uint64(time.Unix(0, 0).UnixMilli()) +} + // IsInterfaceNil returns true if there is no value under the interface func (rndm *RoundHandlerStub) IsInterfaceNil() bool { return rndm == nil diff --git a/process/mock/roundStub.go b/process/mock/roundStub.go index 8b99f5d256d..de554ef9bb5 100644 --- a/process/mock/roundStub.go +++ b/process/mock/roundStub.go @@ -6,11 +6,12 @@ import ( // RoundStub - type RoundStub struct { - IndexCalled func() int64 - TimeDurationCalled func() time.Duration - TimeStampCalled func() time.Time - UpdateRoundCalled func(time.Time, time.Time) - RemainingTimeCalled func(time.Time, time.Duration) time.Duration + IndexCalled func() int64 + TimeDurationCalled func() time.Duration + TimeStampCalled func() time.Time + UpdateRoundCalled func(time.Time, time.Time) + RemainingTimeCalled func(time.Time, time.Duration) time.Duration + GetTimeStampForRoundCalled func(round uint64) uint64 } // Index - @@ -38,6 +39,15 @@ func (rnds *RoundStub) RemainingTime(startTime time.Time, maxTime time.Duration) return rnds.RemainingTimeCalled(startTime, maxTime) } +// GetTimeStampForRound - +func (rnds *RoundStub) GetTimeStampForRound(round uint64) uint64 { + if rnds.GetTimeStampForRoundCalled != nil { + return rnds.GetTimeStampForRoundCalled(round) + } + + return uint64(time.Unix(0, 0).UnixMilli()) +} + // IsInterfaceNil -- func (rnds *RoundStub) IsInterfaceNil() bool { return rnds == nil From f7972149e2137df70602ee276ce2946151b47e0d Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 30 Mar 2026 17:05:51 +0300 Subject: [PATCH 06/12] fix after review --- process/errors.go | 3 +++ process/track/baseBlockTrack.go | 2 +- process/track/baseBlockTrack_test.go | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/process/errors.go b/process/errors.go index 91626191256..c9280de07af 100644 --- a/process/errors.go +++ b/process/errors.go @@ -1490,3 +1490,6 @@ var ErrInvalidShardInfo = errors.New("invalid shard info") // ErrNilClosingNodeStartedFlag signals that the closing node started flag is nil var ErrNilClosingNodeStartedFlag = errors.New("closing node started flag is nil") + +// ErrInvalidRound signals that an invalid round has been provided +var ErrInvalidRound = errors.New("invalid round") diff --git a/process/track/baseBlockTrack.go b/process/track/baseBlockTrack.go index 862a4958078..40ad24dcb1b 100644 --- a/process/track/baseBlockTrack.go +++ b/process/track/baseBlockTrack.go @@ -505,7 +505,7 @@ func (bbt *baseBlockTrack) checkAgainstRoundHandler(round uint64) error { timeLeftToAcceptProof := bbt.roundHandler.RemainingTime(roundTimestamp, maxTimeToAcceptProof) if timeLeftToAcceptProof <= 0 { return fmt.Errorf("%w header round: %d, current round timestamp: %d, time left to accept proof: %d", - process.ErrHigherRoundInBlock, + process.ErrInvalidRound, round, roundTimestamp.UnixMilli(), timeLeftToAcceptProof.Milliseconds()) diff --git a/process/track/baseBlockTrack_test.go b/process/track/baseBlockTrack_test.go index 92321340fbf..1fcf77c086d 100644 --- a/process/track/baseBlockTrack_test.go +++ b/process/track/baseBlockTrack_test.go @@ -2415,7 +2415,7 @@ func TestBaseBlockTrack_CheckBlockAgainstRoundHandlerShouldFailOnInvalidWindow(t timeToSleep := roundDuration + time.Duration(float64(roundDuration)*0.6) time.Sleep(timeToSleep) err := bbt.CheckBlockAgainstRoundHandler(hdr) - require.ErrorIs(t, err, process.ErrHigherRoundInBlock) + require.ErrorIs(t, err, process.ErrInvalidRound) require.Contains(t, err.Error(), "current round timestamp") } From 147e242b9a24589402be256d9f1f5eb42101e162 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Tue, 31 Mar 2026 11:36:57 +0300 Subject: [PATCH 07/12] fix after test: bring broadcast method into interceptor --- .../argInterceptedBlockHeader.go | 2 ++ .../interceptedBlockHeader.go | 11 ++++++++--- .../interceptedBlockHeader_test.go | 11 +++++++++++ .../interceptedEquivalentProof.go | 17 ++++++++++++----- .../interceptedEquivalentProof_test.go | 18 +++++++++++++++++- .../interceptedMetaBlockHeader.go | 11 ++++++++--- .../interceptedMetaBlockHeader_test.go | 2 ++ .../interceptedEquivalentProofsFactory.go | 3 ++- .../interceptedEquivalentProofsFactory_test.go | 2 +- .../factory/interceptedHeartbeatDataFactory.go | 3 ++- .../interceptedHeartbeatDataFactory_test.go | 2 +- .../interceptedMetaHeaderDataFactory.go | 4 +++- .../interceptedMetaHeaderDataFactory_test.go | 2 +- .../factory/interceptedMiniblockDataFactory.go | 3 ++- .../interceptedMiniblockDataFactory_test.go | 2 +- ...interceptedPeerAuthenticationDataFactory.go | 3 ++- ...ceptedPeerAuthenticationDataFactory_test.go | 2 +- .../factory/interceptedPeerShardFactory.go | 3 ++- .../interceptedPeerShardFactory_test.go | 2 +- .../factory/interceptedRewardTxDataFactory.go | 3 ++- .../interceptedRewardTxDataFactory_test.go | 2 +- .../interceptedShardHeaderDataFactory.go | 4 +++- .../interceptedShardHeaderDataFactory_test.go | 2 +- .../factory/interceptedTrieNodeDataFactory.go | 3 ++- .../factory/interceptedTxDataFactory.go | 3 ++- .../factory/interceptedTxDataFactory_test.go | 2 +- .../interceptedUnsignedTxDataFactory.go | 3 ++- .../interceptedUnsignedTxDataFactory_test.go | 2 +- .../interceptedValidatorInfoDataFactory.go | 3 ++- ...interceptedValidatorInfoDataFactory_test.go | 4 ++-- process/interceptors/multiDataInterceptor.go | 2 +- process/interceptors/singleDataInterceptor.go | 2 +- process/interface.go | 2 +- process/mock/interceptedDataFactoryStub.go | 3 ++- process/track/baseBlockTrack.go | 8 ++++---- 35 files changed, 107 insertions(+), 44 deletions(-) diff --git a/process/block/interceptedBlocks/argInterceptedBlockHeader.go b/process/block/interceptedBlocks/argInterceptedBlockHeader.go index 3e763e64ce4..119a92e1958 100644 --- a/process/block/interceptedBlocks/argInterceptedBlockHeader.go +++ b/process/block/interceptedBlocks/argInterceptedBlockHeader.go @@ -3,6 +3,7 @@ package interceptedBlocks import ( "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" @@ -21,4 +22,5 @@ type ArgInterceptedBlockHeader struct { EpochStartTrigger process.EpochStartTriggerHandler EnableEpochsHandler common.EnableEpochsHandler EpochChangeGracePeriodHandler common.EpochChangeGracePeriodHandler + BroadcastMethod p2p.BroadcastMethod } diff --git a/process/block/interceptedBlocks/interceptedBlockHeader.go b/process/block/interceptedBlocks/interceptedBlockHeader.go index 255e32ef5df..0d7224f76fe 100644 --- a/process/block/interceptedBlocks/interceptedBlockHeader.go +++ b/process/block/interceptedBlocks/interceptedBlockHeader.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/hashing" + "github.com/multiversx/mx-chain-go/p2p" logger "github.com/multiversx/mx-chain-logger-go" "github.com/multiversx/mx-chain-go/common" @@ -31,6 +32,7 @@ type InterceptedHeader struct { epochStartTrigger process.EpochStartTriggerHandler enableEpochsHandler common.EnableEpochsHandler epochChangeGracePeriodHandler common.EpochChangeGracePeriodHandler + broadcastMethod p2p.BroadcastMethod } // NewInterceptedHeader creates a new instance of InterceptedHeader struct @@ -55,6 +57,7 @@ func NewInterceptedHeader(arg *ArgInterceptedBlockHeader) (*InterceptedHeader, e epochStartTrigger: arg.EpochStartTrigger, enableEpochsHandler: arg.EnableEpochsHandler, epochChangeGracePeriodHandler: arg.EpochChangeGracePeriodHandler, + broadcastMethod: arg.BroadcastMethod, } inHdr.processFields(arg.HdrBuff) @@ -154,9 +157,11 @@ func (inHdr *InterceptedHeader) integrity() error { } } - err = inHdr.validityAttester.CheckBlockAgainstRoundHandler(inHdr.HeaderHandler()) - if err != nil { - return err + if inHdr.broadcastMethod == p2p.Broadcast { + err = inHdr.validityAttester.CheckBlockAgainstRoundHandler(inHdr.HeaderHandler()) + if err != nil { + return err + } } err = checkMiniBlocksHeaders(inHdr.hdr.GetMiniBlockHeaderHandlers(), inHdr.shardCoordinator) diff --git a/process/block/interceptedBlocks/interceptedBlockHeader_test.go b/process/block/interceptedBlocks/interceptedBlockHeader_test.go index 24ce863d610..cec8e821d04 100644 --- a/process/block/interceptedBlocks/interceptedBlockHeader_test.go +++ b/process/block/interceptedBlocks/interceptedBlockHeader_test.go @@ -10,6 +10,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data" dataBlock "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -45,6 +46,7 @@ func createDefaultShardArgument() *interceptedBlocks.ArgInterceptedBlockHeader { EpochStartTrigger: &mock.EpochStartTriggerStub{}, EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, EpochChangeGracePeriodHandler: gracePeriod, + BroadcastMethod: p2p.Broadcast, } hdr := createMockShardHeader() @@ -65,6 +67,7 @@ func createDefaultShardArgumentWithV2Support() *interceptedBlocks.ArgIntercepted EpochStartTrigger: &mock.EpochStartTriggerStub{}, EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, EpochChangeGracePeriodHandler: gracePeriod, + BroadcastMethod: p2p.Broadcast, } hdr := createMockShardHeader() arg.HdrBuff, _ = arg.Marshalizer.Marshal(hdr) @@ -113,6 +116,7 @@ func createDefaultShardArgumentWithV3Support() *interceptedBlocks.ArgIntercepted }, }, EpochChangeGracePeriodHandler: gracePeriod, + BroadcastMethod: p2p.Broadcast, } hdr := createMockShardHeaderV3() arg.HdrBuff, _ = arg.Marshalizer.Marshal(hdr) @@ -639,6 +643,13 @@ func TestInterceptedHeader_CheckValidityShouldWorkHeaderV3(t *testing.T) { t.Parallel() arg := createDefaultShardArgumentWithV3Support() + arg.BroadcastMethod = p2p.Direct + arg.ValidityAttester = &mock.ValidityAttesterStub{ + CheckBlockAgainstRoundHandlerCalled: func(headerHandler data.HeaderHandler) error { + require.Fail(t, "should not be called") + return nil + }, + } inHdr, err := interceptedBlocks.NewInterceptedHeader(arg) assert.Nil(t, err) assert.NotNil(t, inHdr) diff --git a/process/block/interceptedBlocks/interceptedEquivalentProof.go b/process/block/interceptedBlocks/interceptedEquivalentProof.go index e4dccfd7fe3..35f418f89e2 100644 --- a/process/block/interceptedBlocks/interceptedEquivalentProof.go +++ b/process/block/interceptedBlocks/interceptedEquivalentProof.go @@ -10,6 +10,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" logger "github.com/multiversx/mx-chain-logger-go" "github.com/multiversx/mx-chain-go/common" @@ -33,6 +34,7 @@ type ArgInterceptedEquivalentProof struct { ProofSizeChecker common.FieldsSizeChecker KeyRWMutexHandler sync.KeyRWMutexHandler ValidityAttester process.ValidityAttester + BroadcastMethod p2p.BroadcastMethod } type interceptedEquivalentProof struct { @@ -46,6 +48,7 @@ type interceptedEquivalentProof struct { proofSizeChecker common.FieldsSizeChecker km sync.KeyRWMutexHandler validityAttester process.ValidityAttester + broadcastMethod p2p.BroadcastMethod } // NewInterceptedEquivalentProof returns a new instance of interceptedEquivalentProof @@ -55,7 +58,7 @@ func NewInterceptedEquivalentProof(args ArgInterceptedEquivalentProof) (*interce return nil, err } - equivalentProof, err := createEquivalentProof(args.Marshaller, args.DataBuff) + equivalentProof, err := createEquivalentProof(args.Marshaller, args.DataBuff, args.BroadcastMethod) if err != nil { return nil, err } @@ -73,6 +76,7 @@ func NewInterceptedEquivalentProof(args ArgInterceptedEquivalentProof) (*interce hash: hash, km: args.KeyRWMutexHandler, validityAttester: args.ValidityAttester, + broadcastMethod: args.BroadcastMethod, }, nil } @@ -108,7 +112,7 @@ func checkArgInterceptedEquivalentProof(args ArgInterceptedEquivalentProof) erro return nil } -func createEquivalentProof(marshaller marshal.Marshalizer, buff []byte) (*block.HeaderProof, error) { +func createEquivalentProof(marshaller marshal.Marshalizer, buff []byte, broadcastMethod p2p.BroadcastMethod) (*block.HeaderProof, error) { headerProof := &block.HeaderProof{} err := marshaller.Unmarshal(headerProof, buff) if err != nil { @@ -124,6 +128,7 @@ func createEquivalentProof(marshaller marshal.Marshalizer, buff []byte) (*block. "bitmap", logger.DisplayByteSlice(headerProof.PubKeysBitmap), "signature", logger.DisplayByteSlice(headerProof.AggregatedSignature), "isEpochStart", headerProof.IsStartOfEpoch, + "broadcastMethod", broadcastMethod, ) return headerProof, nil @@ -157,9 +162,11 @@ func (iep *interceptedEquivalentProof) CheckValidity() error { } } - err = iep.validityAttester.CheckProofAgainstRoundHandler(iep.proof) - if err != nil { - return err + if iep.broadcastMethod == p2p.Broadcast { + err = iep.validityAttester.CheckProofAgainstRoundHandler(iep.proof) + if err != nil { + return err + } } headerHash := string(iep.proof.GetHeaderHash()) diff --git a/process/block/interceptedBlocks/interceptedEquivalentProof_test.go b/process/block/interceptedBlocks/interceptedEquivalentProof_test.go index 12aebf66f97..6a9bf40537e 100644 --- a/process/block/interceptedBlocks/interceptedEquivalentProof_test.go +++ b/process/block/interceptedBlocks/interceptedEquivalentProof_test.go @@ -10,6 +10,7 @@ import ( coreSync "github.com/multiversx/mx-chain-core-go/core/sync" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/p2p" logger "github.com/multiversx/mx-chain-logger-go" "github.com/stretchr/testify/require" @@ -75,6 +76,7 @@ func createMockArgInterceptedEquivalentProof() ArgInterceptedEquivalentProof { ProofSizeChecker: &testscommon.FieldsSizeCheckerMock{}, KeyRWMutexHandler: coreSync.NewKeyRWMutex(), ValidityAttester: &processMock.ValidityAttesterStub{}, + BroadcastMethod: p2p.Broadcast, } } @@ -308,7 +310,21 @@ func TestInterceptedEquivalentProof_CheckValidity(t *testing.T) { t.Run("should work", func(t *testing.T) { t.Parallel() - iep, err := NewInterceptedEquivalentProof(createMockArgInterceptedEquivalentProof()) + args := createMockArgInterceptedEquivalentProof() + args.BroadcastMethod = p2p.Direct // should skip round check + args.ValidityAttester = &processMock.ValidityAttesterStub{ + CheckAgainstWhitelistCalled: func(interceptedData process.InterceptedData) bool { + return true + }, + CheckProofAgainstFinalCalled: func(proof data.HeaderProofHandler) error { + return nil + }, + CheckProofAgainstRoundHandlerCalled: func(proof data.HeaderProofHandler) error { + require.Fail(t, "should not be called") + return nil + }, + } + iep, err := NewInterceptedEquivalentProof(args) require.NoError(t, err) err = iep.CheckValidity() diff --git a/process/block/interceptedBlocks/interceptedMetaBlockHeader.go b/process/block/interceptedBlocks/interceptedMetaBlockHeader.go index 3f71cd0ffab..76a10a2a085 100644 --- a/process/block/interceptedBlocks/interceptedMetaBlockHeader.go +++ b/process/block/interceptedBlocks/interceptedMetaBlockHeader.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/hashing" + "github.com/multiversx/mx-chain-go/p2p" logger "github.com/multiversx/mx-chain-logger-go" "github.com/multiversx/mx-chain-go/common" @@ -30,6 +31,7 @@ type InterceptedMetaHeader struct { validityAttester process.ValidityAttester epochStartTrigger process.EpochStartTriggerHandler enableEpochsHandler common.EnableEpochsHandler + broadcastMethod p2p.BroadcastMethod } // NewInterceptedMetaHeader creates a new instance of InterceptedMetaHeader struct @@ -53,6 +55,7 @@ func NewInterceptedMetaHeader(arg *ArgInterceptedBlockHeader) (*InterceptedMetaH validityAttester: arg.ValidityAttester, epochStartTrigger: arg.EpochStartTrigger, enableEpochsHandler: arg.EnableEpochsHandler, + broadcastMethod: arg.BroadcastMethod, } inHdr.processFields(arg.HdrBuff) @@ -98,9 +101,11 @@ func (imh *InterceptedMetaHeader) CheckValidity() error { } } - err = imh.validityAttester.CheckBlockAgainstRoundHandler(imh.HeaderHandler()) - if err != nil { - return err + if imh.broadcastMethod == p2p.Broadcast { + err = imh.validityAttester.CheckBlockAgainstRoundHandler(imh.HeaderHandler()) + if err != nil { + return err + } } err = imh.sigVerifier.VerifyRandSeedAndLeaderSignature(imh.hdr) diff --git a/process/block/interceptedBlocks/interceptedMetaBlockHeader_test.go b/process/block/interceptedBlocks/interceptedMetaBlockHeader_test.go index dba717347d9..06c633fea11 100644 --- a/process/block/interceptedBlocks/interceptedMetaBlockHeader_test.go +++ b/process/block/interceptedBlocks/interceptedMetaBlockHeader_test.go @@ -9,6 +9,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" dataBlock "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/multiversx/mx-chain-go/p2p" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -54,6 +55,7 @@ func createMetaArgumentWithShardCoordinatorAndHeader(shardCoordinator sharding.C }, EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, EpochChangeGracePeriodHandler: gracePeriod, + BroadcastMethod: p2p.Broadcast, } arg.HdrBuff, _ = testMarshalizer.Marshal(hdr) diff --git a/process/interceptors/factory/interceptedEquivalentProofsFactory.go b/process/interceptors/factory/interceptedEquivalentProofsFactory.go index 7930e58aa87..4515ec7ad41 100644 --- a/process/interceptors/factory/interceptedEquivalentProofsFactory.go +++ b/process/interceptors/factory/interceptedEquivalentProofsFactory.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/sync" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/consensus" @@ -46,7 +47,7 @@ func NewInterceptedEquivalentProofsFactory(args ArgInterceptedEquivalentProofsFa } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (factory *interceptedEquivalentProofsFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (factory *interceptedEquivalentProofsFactory) Create(buff []byte, _ core.PeerID, broadcastMethod p2p.BroadcastMethod) (process.InterceptedData, error) { args := interceptedBlocks.ArgInterceptedEquivalentProof{ DataBuff: buff, Marshaller: factory.marshaller, diff --git a/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go b/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go index 26331df5cd4..331c6bfaaa6 100644 --- a/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go +++ b/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go @@ -69,7 +69,7 @@ func TestInterceptedEquivalentProofsFactory_Create(t *testing.T) { HeaderShardId: 0, } providedDataBuff, _ := args.CoreComponents.InternalMarshalizer().Marshal(providedProof) - interceptedData, err := factory.Create(providedDataBuff, "") + interceptedData, err := factory.Create(providedDataBuff, "", "") require.NoError(t, err) require.NotNil(t, interceptedData) diff --git a/process/interceptors/factory/interceptedHeartbeatDataFactory.go b/process/interceptors/factory/interceptedHeartbeatDataFactory.go index 5d5c3fed2e6..03069e836db 100644 --- a/process/interceptors/factory/interceptedHeartbeatDataFactory.go +++ b/process/interceptors/factory/interceptedHeartbeatDataFactory.go @@ -4,6 +4,7 @@ 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/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/heartbeat" ) @@ -29,7 +30,7 @@ func NewInterceptedHeartbeatDataFactory(arg ArgInterceptedDataFactory) (*interce } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (ihdf *interceptedHeartbeatDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (ihdf *interceptedHeartbeatDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { arg := heartbeat.ArgBaseInterceptedHeartbeat{ DataBuff: buff, Marshaller: ihdf.marshalizer, diff --git a/process/interceptors/factory/interceptedHeartbeatDataFactory_test.go b/process/interceptors/factory/interceptedHeartbeatDataFactory_test.go index 055830b685d..1c4297675ed 100644 --- a/process/interceptors/factory/interceptedHeartbeatDataFactory_test.go +++ b/process/interceptors/factory/interceptedHeartbeatDataFactory_test.go @@ -67,7 +67,7 @@ func TestNewInterceptedHeartbeatDataFactory(t *testing.T) { marshaledHeartbeat, err := marshaller.Marshal(hb) assert.Nil(t, err) - interceptedData, err := ihdf.Create(marshaledHeartbeat, "") + interceptedData, err := ihdf.Create(marshaledHeartbeat, "", "") assert.NotNil(t, interceptedData) assert.Nil(t, err) assert.True(t, strings.Contains(fmt.Sprintf("%T", interceptedData), "*heartbeat.interceptedHeartbeat")) diff --git a/process/interceptors/factory/interceptedMetaHeaderDataFactory.go b/process/interceptors/factory/interceptedMetaHeaderDataFactory.go index 7068734cd72..914333bf2e9 100644 --- a/process/interceptors/factory/interceptedMetaHeaderDataFactory.go +++ b/process/interceptors/factory/interceptedMetaHeaderDataFactory.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" @@ -81,7 +82,7 @@ func NewInterceptedMetaHeaderDataFactory(argument *ArgInterceptedMetaHeaderFacto } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (imhdf *interceptedMetaHeaderDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (imhdf *interceptedMetaHeaderDataFactory) Create(buff []byte, _ core.PeerID, broadcastMethod p2p.BroadcastMethod) (process.InterceptedData, error) { arg := &interceptedBlocks.ArgInterceptedBlockHeader{ HdrBuff: buff, Marshalizer: imhdf.marshalizer, @@ -93,6 +94,7 @@ func (imhdf *interceptedMetaHeaderDataFactory) Create(buff []byte, _ core.PeerID EpochStartTrigger: imhdf.epochStartTrigger, EnableEpochsHandler: imhdf.enableEpochsHandler, EpochChangeGracePeriodHandler: imhdf.epochChangeGracePeriodHandler, + BroadcastMethod: broadcastMethod, } return interceptedBlocks.NewInterceptedMetaHeader(arg) diff --git a/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go b/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go index e36b1f1954b..a8814cd97a5 100644 --- a/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go +++ b/process/interceptors/factory/interceptedMetaHeaderDataFactory_test.go @@ -261,7 +261,7 @@ func TestNewInterceptedMetaHeaderDataFactory_ShouldWorkAndCreate(t *testing.T) { marshalizer := &processMocks.MarshalizerMock{} emptyMetaHeader := &block.Header{} emptyMetaHeaderBuff, _ := marshalizer.Marshal(emptyMetaHeader) - interceptedData, err := imh.Create(emptyMetaHeaderBuff, "") + interceptedData, err := imh.Create(emptyMetaHeaderBuff, "", "") assert.Nil(t, err) _, ok := interceptedData.(*interceptedBlocks.InterceptedMetaHeader) diff --git a/process/interceptors/factory/interceptedMiniblockDataFactory.go b/process/interceptors/factory/interceptedMiniblockDataFactory.go index c51c78dac16..977d335e664 100644 --- a/process/interceptors/factory/interceptedMiniblockDataFactory.go +++ b/process/interceptors/factory/interceptedMiniblockDataFactory.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/block/interceptedBlocks" "github.com/multiversx/mx-chain-go/sharding" @@ -44,7 +45,7 @@ func NewInterceptedMiniblockDataFactory(argument *ArgInterceptedDataFactory) (*i } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (imfd *interceptedMiniblockDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (imfd *interceptedMiniblockDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { arg := &interceptedBlocks.ArgInterceptedMiniblock{ MiniblockBuff: buff, Marshalizer: imfd.marshalizer, diff --git a/process/interceptors/factory/interceptedMiniblockDataFactory_test.go b/process/interceptors/factory/interceptedMiniblockDataFactory_test.go index 3a15d006751..8cbef5e6f08 100644 --- a/process/interceptors/factory/interceptedMiniblockDataFactory_test.go +++ b/process/interceptors/factory/interceptedMiniblockDataFactory_test.go @@ -69,7 +69,7 @@ func TestInterceptedMiniblockDataFactory_ShouldWorkAndCreate(t *testing.T) { marshalizer := &mock.MarshalizerMock{} emptyBlockBody := &block.Body{} emptyBlockBodyBuff, _ := marshalizer.Marshal(emptyBlockBody) - interceptedData, err := imdf.Create(emptyBlockBodyBuff, "") + interceptedData, err := imdf.Create(emptyBlockBodyBuff, "", "") assert.Nil(t, err) _, ok := interceptedData.(*interceptedBlocks.InterceptedMiniblock) diff --git a/process/interceptors/factory/interceptedPeerAuthenticationDataFactory.go b/process/interceptors/factory/interceptedPeerAuthenticationDataFactory.go index 18b4a4f40a2..2d5b339e726 100644 --- a/process/interceptors/factory/interceptedPeerAuthenticationDataFactory.go +++ b/process/interceptors/factory/interceptedPeerAuthenticationDataFactory.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/marshal" crypto "github.com/multiversx/mx-chain-crypto-go" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/heartbeat" "github.com/multiversx/mx-chain-go/process/heartbeat/validator" @@ -72,7 +73,7 @@ func checkArgInterceptedDataFactory(args ArgInterceptedDataFactory) error { } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (ipadf *interceptedPeerAuthenticationDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (ipadf *interceptedPeerAuthenticationDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { arg := heartbeat.ArgInterceptedPeerAuthentication{ ArgBaseInterceptedHeartbeat: heartbeat.ArgBaseInterceptedHeartbeat{ DataBuff: buff, diff --git a/process/interceptors/factory/interceptedPeerAuthenticationDataFactory_test.go b/process/interceptors/factory/interceptedPeerAuthenticationDataFactory_test.go index d1de48a25ed..e1fb04c5f9b 100644 --- a/process/interceptors/factory/interceptedPeerAuthenticationDataFactory_test.go +++ b/process/interceptors/factory/interceptedPeerAuthenticationDataFactory_test.go @@ -121,7 +121,7 @@ func TestNewInterceptedPeerAuthenticationDataFactory(t *testing.T) { marshaledPeerAuthentication, err := marshaller.Marshal(peerAuthentication) assert.Nil(t, err) - interceptedData, err := ipadf.Create(marshaledPeerAuthentication, "") + interceptedData, err := ipadf.Create(marshaledPeerAuthentication, "", "") assert.NotNil(t, interceptedData) assert.Nil(t, err) assert.True(t, strings.Contains(fmt.Sprintf("%T", interceptedData), "*heartbeat.interceptedPeerAuthentication")) diff --git a/process/interceptors/factory/interceptedPeerShardFactory.go b/process/interceptors/factory/interceptedPeerShardFactory.go index 3234bb89681..9876d37ea53 100644 --- a/process/interceptors/factory/interceptedPeerShardFactory.go +++ b/process/interceptors/factory/interceptedPeerShardFactory.go @@ -4,6 +4,7 @@ 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/marshal" + p "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/p2p" "github.com/multiversx/mx-chain-go/sharding" @@ -42,7 +43,7 @@ func checkInterceptedDirectConnectionInfoFactoryArgs(args ArgInterceptedDataFact } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (ipsf *interceptedPeerShardFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (ipsf *interceptedPeerShardFactory) Create(buff []byte, _ core.PeerID, _ p.BroadcastMethod) (process.InterceptedData, error) { args := p2p.ArgInterceptedPeerShard{ Marshaller: ipsf.marshaller, DataBuff: buff, diff --git a/process/interceptors/factory/interceptedPeerShardFactory_test.go b/process/interceptors/factory/interceptedPeerShardFactory_test.go index 797a5109113..1d014e0d41b 100644 --- a/process/interceptors/factory/interceptedPeerShardFactory_test.go +++ b/process/interceptors/factory/interceptedPeerShardFactory_test.go @@ -60,7 +60,7 @@ func TestNewInterceptedPeerShardFactory(t *testing.T) { ShardId: "5", } msgBuff, _ := arg.CoreComponents.InternalMarshalizer().Marshal(msg) - interceptedData, err := idcif.Create(msgBuff, "") + interceptedData, err := idcif.Create(msgBuff, "", "") assert.Nil(t, err) assert.False(t, check.IfNil(interceptedData)) assert.True(t, strings.Contains(fmt.Sprintf("%T", interceptedData), "*p2p.interceptedPeerShard")) diff --git a/process/interceptors/factory/interceptedRewardTxDataFactory.go b/process/interceptors/factory/interceptedRewardTxDataFactory.go index 1ceec65e05f..ad99eac9ec3 100644 --- a/process/interceptors/factory/interceptedRewardTxDataFactory.go +++ b/process/interceptors/factory/interceptedRewardTxDataFactory.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/rewardTransaction" "github.com/multiversx/mx-chain-go/sharding" @@ -52,7 +53,7 @@ func NewInterceptedRewardTxDataFactory(argument *ArgInterceptedDataFactory) (*in } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (irtdf *interceptedRewardTxDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (irtdf *interceptedRewardTxDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { return rewardTransaction.NewInterceptedRewardTransaction( buff, irtdf.protoMarshalizer, diff --git a/process/interceptors/factory/interceptedRewardTxDataFactory_test.go b/process/interceptors/factory/interceptedRewardTxDataFactory_test.go index da7971d86b2..76493ed7920 100644 --- a/process/interceptors/factory/interceptedRewardTxDataFactory_test.go +++ b/process/interceptors/factory/interceptedRewardTxDataFactory_test.go @@ -93,7 +93,7 @@ func TestInterceptedRewardTxDataFactory_ShouldWorkAndCreate(t *testing.T) { marshalizer := &mock.MarshalizerMock{} emptyRewardTx := &rewardTx.RewardTx{} emptyRewardTxBuff, _ := marshalizer.Marshal(emptyRewardTx) - interceptedData, err := imh.Create(emptyRewardTxBuff, "") + interceptedData, err := imh.Create(emptyRewardTxBuff, "", "") assert.Nil(t, err) _, ok := interceptedData.(*rewardTransaction.InterceptedRewardTransaction) diff --git a/process/interceptors/factory/interceptedShardHeaderDataFactory.go b/process/interceptors/factory/interceptedShardHeaderDataFactory.go index a2a52db7594..581efcdc56b 100644 --- a/process/interceptors/factory/interceptedShardHeaderDataFactory.go +++ b/process/interceptors/factory/interceptedShardHeaderDataFactory.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/process" @@ -76,7 +77,7 @@ func NewInterceptedShardHeaderDataFactory(argument *ArgInterceptedDataFactory) ( } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (ishdf *interceptedShardHeaderDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (ishdf *interceptedShardHeaderDataFactory) Create(buff []byte, _ core.PeerID, broadcastMethod p2p.BroadcastMethod) (process.InterceptedData, error) { arg := &interceptedBlocks.ArgInterceptedBlockHeader{ HdrBuff: buff, Marshalizer: ishdf.marshalizer, @@ -88,6 +89,7 @@ func (ishdf *interceptedShardHeaderDataFactory) Create(buff []byte, _ core.PeerI EpochStartTrigger: ishdf.epochStartTrigger, EnableEpochsHandler: ishdf.enableEpochsHandler, EpochChangeGracePeriodHandler: ishdf.epochChangeGracePeriodHandler, + BroadcastMethod: broadcastMethod, } return interceptedBlocks.NewInterceptedHeader(arg) diff --git a/process/interceptors/factory/interceptedShardHeaderDataFactory_test.go b/process/interceptors/factory/interceptedShardHeaderDataFactory_test.go index 31adf2802a1..8f7d0ca0755 100644 --- a/process/interceptors/factory/interceptedShardHeaderDataFactory_test.go +++ b/process/interceptors/factory/interceptedShardHeaderDataFactory_test.go @@ -106,7 +106,7 @@ func TestInterceptedShardHeaderDataFactory_ShouldWorkAndCreate(t *testing.T) { marshalizer := &mock.MarshalizerMock{} emptyBlockHeader := &block.Header{} emptyBlockHeaderBuff, _ := marshalizer.Marshal(emptyBlockHeader) - interceptedData, err := imh.Create(emptyBlockHeaderBuff, "") + interceptedData, err := imh.Create(emptyBlockHeaderBuff, "", "") assert.Nil(t, err) _, ok := interceptedData.(*interceptedBlocks.InterceptedHeader) diff --git a/process/interceptors/factory/interceptedTrieNodeDataFactory.go b/process/interceptors/factory/interceptedTrieNodeDataFactory.go index 33e09286487..d96d69a1894 100644 --- a/process/interceptors/factory/interceptedTrieNodeDataFactory.go +++ b/process/interceptors/factory/interceptedTrieNodeDataFactory.go @@ -4,6 +4,7 @@ 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/hashing" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/trie" ) @@ -35,7 +36,7 @@ func NewInterceptedTrieNodeDataFactory( } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (sidf *interceptedTrieNodeDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (sidf *interceptedTrieNodeDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { return trie.NewInterceptedTrieNode(buff, sidf.hasher) } diff --git a/process/interceptors/factory/interceptedTxDataFactory.go b/process/interceptors/factory/interceptedTxDataFactory.go index 65fe2f69e7c..bc33bfa23d3 100644 --- a/process/interceptors/factory/interceptedTxDataFactory.go +++ b/process/interceptors/factory/interceptedTxDataFactory.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-core-go/marshal" "github.com/multiversx/mx-chain-crypto-go" "github.com/multiversx/mx-chain-go/common" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/transaction" "github.com/multiversx/mx-chain-go/sharding" @@ -113,7 +114,7 @@ func NewInterceptedTxDataFactory(argument *ArgInterceptedDataFactory) (*intercep } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (itdf *interceptedTxDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (itdf *interceptedTxDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { return transaction.NewInterceptedTransaction( buff, itdf.protoMarshalizer, diff --git a/process/interceptors/factory/interceptedTxDataFactory_test.go b/process/interceptors/factory/interceptedTxDataFactory_test.go index 56efc31b681..414a9eb0ddc 100644 --- a/process/interceptors/factory/interceptedTxDataFactory_test.go +++ b/process/interceptors/factory/interceptedTxDataFactory_test.go @@ -196,7 +196,7 @@ func TestInterceptedTxDataFactory_ShouldWorkAndCreate(t *testing.T) { Value: big.NewInt(0), } emptyTxBuff, _ := marshalizer.Marshal(emptyTx) - interceptedData, err := imh.Create(emptyTxBuff, "") + interceptedData, err := imh.Create(emptyTxBuff, "", "") assert.Nil(t, err) _, ok := interceptedData.(*transaction.InterceptedTransaction) diff --git a/process/interceptors/factory/interceptedUnsignedTxDataFactory.go b/process/interceptors/factory/interceptedUnsignedTxDataFactory.go index 44233ae1ef6..8bf508f295d 100644 --- a/process/interceptors/factory/interceptedUnsignedTxDataFactory.go +++ b/process/interceptors/factory/interceptedUnsignedTxDataFactory.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/unsigned" "github.com/multiversx/mx-chain-go/sharding" @@ -52,7 +53,7 @@ func NewInterceptedUnsignedTxDataFactory(argument *ArgInterceptedDataFactory) (* } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (iutdf *interceptedUnsignedTxDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (iutdf *interceptedUnsignedTxDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { return unsigned.NewInterceptedUnsignedTransaction( buff, iutdf.protoMarshalizer, diff --git a/process/interceptors/factory/interceptedUnsignedTxDataFactory_test.go b/process/interceptors/factory/interceptedUnsignedTxDataFactory_test.go index 41ab63596b1..439f76b60ae 100644 --- a/process/interceptors/factory/interceptedUnsignedTxDataFactory_test.go +++ b/process/interceptors/factory/interceptedUnsignedTxDataFactory_test.go @@ -93,7 +93,7 @@ func TestInterceptedUnsignedTxDataFactory_ShouldWorkAndCreate(t *testing.T) { marshalizer := &mock.MarshalizerMock{} emptyTx := &smartContractResult.SmartContractResult{} emptyTxBuff, _ := marshalizer.Marshal(emptyTx) - interceptedData, err := imh.Create(emptyTxBuff, "") + interceptedData, err := imh.Create(emptyTxBuff, "", "") assert.Nil(t, err) _, ok := interceptedData.(*unsigned.InterceptedUnsignedTransaction) diff --git a/process/interceptors/factory/interceptedValidatorInfoDataFactory.go b/process/interceptors/factory/interceptedValidatorInfoDataFactory.go index 0ae55db3767..a1429350831 100644 --- a/process/interceptors/factory/interceptedValidatorInfoDataFactory.go +++ b/process/interceptors/factory/interceptedValidatorInfoDataFactory.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/peer" ) @@ -42,7 +43,7 @@ func checkInterceptedValidatorInfoDataFactoryArgs(args ArgInterceptedDataFactory } // Create creates instances of InterceptedData by unmarshalling provided buffer -func (ividf *interceptedValidatorInfoDataFactory) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (ividf *interceptedValidatorInfoDataFactory) Create(buff []byte, _ core.PeerID, _ p2p.BroadcastMethod) (process.InterceptedData, error) { args := peer.ArgInterceptedValidatorInfo{ DataBuff: buff, Marshalizer: ividf.marshaller, diff --git a/process/interceptors/factory/interceptedValidatorInfoDataFactory_test.go b/process/interceptors/factory/interceptedValidatorInfoDataFactory_test.go index a6f1d9772d6..e15b8fb48b5 100644 --- a/process/interceptors/factory/interceptedValidatorInfoDataFactory_test.go +++ b/process/interceptors/factory/interceptedValidatorInfoDataFactory_test.go @@ -79,7 +79,7 @@ func TestInterceptedValidatorInfoDataFactory_Create(t *testing.T) { ividf, _ := NewInterceptedValidatorInfoDataFactory(*createMockArgument(createMockComponentHolders())) require.False(t, check.IfNil(ividf)) - ivi, err := ividf.Create(nil, "") + ivi, err := ividf.Create(nil, "", "") assert.NotNil(t, err) assert.True(t, check.IfNil(ivi)) }) @@ -88,7 +88,7 @@ func TestInterceptedValidatorInfoDataFactory_Create(t *testing.T) { ividf, _ := NewInterceptedValidatorInfoDataFactory(*createMockArgument(createMockComponentHolders())) require.False(t, check.IfNil(ividf)) - ivi, err := ividf.Create(createMockValidatorInfoBuff(), "") + ivi, err := ividf.Create(createMockValidatorInfoBuff(), "", "") assert.Nil(t, err) assert.False(t, check.IfNil(ivi)) }) diff --git a/process/interceptors/multiDataInterceptor.go b/process/interceptors/multiDataInterceptor.go index a2fba37382c..1ca935c0459 100644 --- a/process/interceptors/multiDataInterceptor.go +++ b/process/interceptors/multiDataInterceptor.go @@ -258,7 +258,7 @@ func (mdi *MultiDataInterceptor) interceptedData( topic string, broadcastMethod p2p.BroadcastMethod, ) (process.InterceptedData, error) { - interceptedData, err := mdi.factory.Create(dataBuff, originator) + interceptedData, err := mdi.factory.Create(dataBuff, originator, broadcastMethod) if err != nil { // this situation is so severe that we need to black list de peers reason := "can not create object from received bytes, topic " + mdi.topic + ", error " + err.Error() diff --git a/process/interceptors/singleDataInterceptor.go b/process/interceptors/singleDataInterceptor.go index f39da2a261d..d874be42630 100644 --- a/process/interceptors/singleDataInterceptor.go +++ b/process/interceptors/singleDataInterceptor.go @@ -94,7 +94,7 @@ func (sdi *SingleDataInterceptor) ProcessReceivedMessage(message p2p.MessageP2P, return nil, err } - interceptedData, err := sdi.factory.Create(message.Data(), message.Peer()) + interceptedData, err := sdi.factory.Create(message.Data(), message.Peer(), message.BroadcastMethod()) if err != nil { sdi.throttler.EndProcessing() diff --git a/process/interface.go b/process/interface.go index e3c175da651..c8f43750497 100644 --- a/process/interface.go +++ b/process/interface.go @@ -132,7 +132,7 @@ type HdrValidatorHandler interface { // InterceptedDataFactory can create new instances of InterceptedData type InterceptedDataFactory interface { - Create(buff []byte, messageOriginator core.PeerID) (InterceptedData, error) + Create(buff []byte, messageOriginator core.PeerID, broadcastMethod p2p.BroadcastMethod) (InterceptedData, error) IsInterfaceNil() bool } diff --git a/process/mock/interceptedDataFactoryStub.go b/process/mock/interceptedDataFactoryStub.go index 3481f42e5b7..0c493f0cc60 100644 --- a/process/mock/interceptedDataFactoryStub.go +++ b/process/mock/interceptedDataFactoryStub.go @@ -2,6 +2,7 @@ package mock import ( "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-go/p2p" "github.com/multiversx/mx-chain-go/process" ) @@ -11,7 +12,7 @@ type InterceptedDataFactoryStub struct { } // Create - -func (idfs *InterceptedDataFactoryStub) Create(buff []byte, _ core.PeerID) (process.InterceptedData, error) { +func (idfs *InterceptedDataFactoryStub) Create(buff []byte, messageOriginator core.PeerID, broadcastMethod p2p.BroadcastMethod) (process.InterceptedData, error) { return idfs.CreateCalled(buff) } diff --git a/process/track/baseBlockTrack.go b/process/track/baseBlockTrack.go index 40ad24dcb1b..a2962eb9b27 100644 --- a/process/track/baseBlockTrack.go +++ b/process/track/baseBlockTrack.go @@ -501,14 +501,14 @@ func (bbt *baseBlockTrack) checkAgainstRoundHandler(round uint64) error { roundTimestamp := time.UnixMilli(int64(bbt.roundHandler.GetTimeStampForRound(round))) roundDuration := float64(bbt.roundHandler.TimeDuration()) - maxTimeToAcceptProof := time.Duration(roundDuration + roundDuration*receivedProofDelay) - timeLeftToAcceptProof := bbt.roundHandler.RemainingTime(roundTimestamp, maxTimeToAcceptProof) - if timeLeftToAcceptProof <= 0 { + maxTimeToAccept := time.Duration(roundDuration + roundDuration*receivedProofDelay) + timeLeftToAccept := bbt.roundHandler.RemainingTime(roundTimestamp, maxTimeToAccept) + if timeLeftToAccept <= 0 { return fmt.Errorf("%w header round: %d, current round timestamp: %d, time left to accept proof: %d", process.ErrInvalidRound, round, roundTimestamp.UnixMilli(), - timeLeftToAcceptProof.Milliseconds()) + timeLeftToAccept.Milliseconds()) } return nil From 1d0b2e2cb2c937a01c92ad664a88eeaf6b112199 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 1 Apr 2026 16:08:05 +0300 Subject: [PATCH 08/12] new method ComputeCurrentRound --- consensus/interface.go | 1 + consensus/round/round.go | 37 ++++++++-- consensus/round/round_test.go | 68 +++++++++++++++++++ epochStart/mock/rounderStub.go | 10 +++ integrationTests/mock/roundHandlerMock.go | 20 ++++-- .../components/manualRoundHandler.go | 5 ++ process/interface.go | 1 + process/mock/roundStub.go | 10 +++ process/mock/rounderMock.go | 20 ++++-- process/track/baseBlockTrack.go | 2 +- process/track/baseBlockTrack_test.go | 6 ++ testscommon/round/rounderMock.go | 10 +++ testscommon/roundHandlerMock.go | 10 +++ 13 files changed, 185 insertions(+), 15 deletions(-) diff --git a/consensus/interface.go b/consensus/interface.go index 92ae90fca36..bb89089a30f 100644 --- a/consensus/interface.go +++ b/consensus/interface.go @@ -24,6 +24,7 @@ type RoundHandler interface { TimeDuration() time.Duration RemainingTime(startTime time.Time, maxTime time.Duration) time.Duration GetTimeStampForRound(round uint64) uint64 + ComputeCurrentRound() int64 IsInterfaceNil() bool } diff --git a/consensus/round/round.go b/consensus/round/round.go index e8dfe6f6d7e..9b889b3ef46 100644 --- a/consensus/round/round.go +++ b/consensus/round/round.go @@ -83,6 +83,14 @@ func NewRound(args ArgsRound) (*round, error) { // UpdateRound updates the index and the time stamp of the round depending on the genesis time and the current time given func (rnd *round) UpdateRound(genesisTimeStamp time.Time, currentTimeStamp time.Time) { + baseTimeStamp, roundDuration, startRound := rnd.getBaseInfo(genesisTimeStamp, currentTimeStamp) + rnd.updateRound(baseTimeStamp, currentTimeStamp, startRound, roundDuration) +} + +func (rnd *round) getBaseInfo( + genesisTimeStamp time.Time, + currentTimeStamp time.Time, +) (time.Time, time.Duration, int64) { baseTimeStamp := rnd.supernovaGenesisTimeStamp roundDuration := rnd.supernovaTimeDuration startRound := rnd.supernovaStartRound @@ -95,7 +103,20 @@ func (rnd *round) UpdateRound(genesisTimeStamp time.Time, currentTimeStamp time. startRound = rnd.startRound } - rnd.updateRound(baseTimeStamp, currentTimeStamp, startRound, roundDuration) + return baseTimeStamp, roundDuration, startRound +} + +func getIndex( + genesisTimeStamp time.Time, + currentTimeStamp time.Time, + roundDuration time.Duration, + startRound int64, +) (int64, int64) { + delta := currentTimeStamp.Sub(genesisTimeStamp).Nanoseconds() + + index := int64(math.Floor(float64(delta)/float64(roundDuration.Nanoseconds()))) + startRound + + return index, delta } func (rnd *round) isSupernovaRoundActivated() bool { @@ -134,9 +155,7 @@ func (rnd *round) updateRound( startRound int64, roundDuration time.Duration, ) { - delta := currentTimeStamp.Sub(genesisTimeStamp).Nanoseconds() - - index := int64(math.Floor(float64(delta)/float64(roundDuration.Nanoseconds()))) + startRound + index, delta := getIndex(genesisTimeStamp, currentTimeStamp, roundDuration, startRound) rnd.Lock() if rnd.index != index { @@ -226,6 +245,16 @@ func (rnd *round) GetTimeStampForRound(round uint64) uint64 { return uint64(roundTimeStampMs) } +// ComputeCurrentRound computes the round that should match the current timestamp +func (rnd *round) ComputeCurrentRound() int64 { + genesisTimeStamp := rnd.genesisTimeStamp + currentTimeStamp := rnd.syncTimer.CurrentTime() + timeStamp, roundDuration, startRound := rnd.getBaseInfo(genesisTimeStamp, currentTimeStamp) + index, _ := getIndex(timeStamp, currentTimeStamp, roundDuration, startRound) + + return index +} + // IsInterfaceNil returns true if there is no value under the interface func (rnd *round) IsInterfaceNil() bool { return rnd == nil diff --git a/consensus/round/round_test.go b/consensus/round/round_test.go index 3aa2611e515..de26a0f98a2 100644 --- a/consensus/round/round_test.go +++ b/consensus/round/round_test.go @@ -697,6 +697,74 @@ func TestRound_Concurrency(t *testing.T) { }) } +func TestRound_ComputeCurrentRound(t *testing.T) { + t.Parallel() + + t.Run("before supernova should return correct round", func(t *testing.T) { + t.Parallel() + + genesisTime := time.Now() + currentTime := genesisTime.Add(3 * roundTimeDuration) + + syncTimerMock := &consensusMocks.SyncTimerMock{ + CurrentTimeCalled: func() time.Time { + return currentTime + }, + } + + args := createDefaultRoundArgs() + args.GenesisTimeStamp = genesisTime + args.SupernovaGenesisTimeStamp = genesisTime.Add(10 * roundTimeDuration) + args.SyncTimer = syncTimerMock + + rnd, err := round.NewRound(args) + require.Nil(t, err) + + computedRound := rnd.ComputeCurrentRound() + assert.Equal(t, int64(3), computedRound) + }) + + t.Run("after supernova should return correct round", func(t *testing.T) { + t.Parallel() + + genesisTime := time.Now() + roundDuration := 10 * time.Millisecond + supernovaRoundDuration := 5 * time.Millisecond + supernovaStartRound := int64(5) + supernovaGenesisTime := genesisTime.Add(time.Duration(supernovaStartRound) * roundDuration) + + // current time is 3 supernova rounds after supernova genesis + currentTime := supernovaGenesisTime.Add(3 * supernovaRoundDuration) + + syncTimerMock := &consensusMocks.SyncTimerMock{ + CurrentTimeCalled: func() time.Time { + return currentTime + }, + } + + args := createDefaultRoundArgs() + args.GenesisTimeStamp = genesisTime + args.SupernovaGenesisTimeStamp = supernovaGenesisTime + args.RoundTimeDuration = roundDuration + args.SupernovaTimeDuration = supernovaRoundDuration + args.SupernovaStartRound = supernovaStartRound + args.CurrentTimeStamp = currentTime + args.SyncTimer = syncTimerMock + args.EnableRoundsHandler = &testscommon.EnableRoundsHandlerStub{ + IsFlagEnabledInRoundCalled: func(flag common.EnableRoundFlag, round uint64) bool { + return flag == common.SupernovaRoundFlag && round >= uint64(supernovaStartRound) + }, + } + + rnd, err := round.NewRound(args) + require.Nil(t, err) + + // delta from supernovaGenesis = 3*5ms = 15ms, index = floor(15ms/5ms) + 5 = 3 + 5 = 8 + computedRound := rnd.ComputeCurrentRound() + assert.Equal(t, int64(8), computedRound) + }) +} + func TestRound_GetTimeStampForRound(t *testing.T) { t.Parallel() diff --git a/epochStart/mock/rounderStub.go b/epochStart/mock/rounderStub.go index 4c3539e87b6..04d5547e41c 100644 --- a/epochStart/mock/rounderStub.go +++ b/epochStart/mock/rounderStub.go @@ -14,6 +14,7 @@ type RoundHandlerStub struct { UpdateRoundCalled func(time.Time, time.Time) RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration GetTimeStampForRoundCalled func(round uint64) uint64 + ComputeCurrentRoundCalled func() int64 } // Index - @@ -71,6 +72,15 @@ func (rndm *RoundHandlerStub) GetTimeStampForRound(round uint64) uint64 { return uint64(time.Unix(0, 0).UnixMilli()) } +// ComputeCurrentRound - +func (rndm *RoundHandlerStub) ComputeCurrentRound() int64 { + if rndm.ComputeCurrentRoundCalled != nil { + return rndm.ComputeCurrentRoundCalled() + } + + return 0 +} + // IsInterfaceNil returns true if there is no value under the interface func (rndm *RoundHandlerStub) IsInterfaceNil() bool { return rndm == nil diff --git a/integrationTests/mock/roundHandlerMock.go b/integrationTests/mock/roundHandlerMock.go index 8051a909e01..485be736b7c 100644 --- a/integrationTests/mock/roundHandlerMock.go +++ b/integrationTests/mock/roundHandlerMock.go @@ -4,11 +4,12 @@ import "time" // RoundHandlerMock - type RoundHandlerMock struct { - IndexField int64 - TimeStampField time.Time - TimeDurationField time.Duration - RemainingTimeField time.Duration - BeforeGenesisCalled func() bool + IndexField int64 + TimeStampField time.Time + TimeDurationField time.Duration + RemainingTimeField time.Duration + BeforeGenesisCalled func() bool + ComputeCurrentRoundCalled func() int64 } // BeforeGenesis - @@ -58,6 +59,15 @@ func (mock *RoundHandlerMock) GetTimeStampForRound(round uint64) uint64 { return round * uint64(mock.TimeDuration().Milliseconds()) } +// ComputeCurrentRound - +func (mock *RoundHandlerMock) ComputeCurrentRound() int64 { + if mock.ComputeCurrentRoundCalled != nil { + return mock.ComputeCurrentRoundCalled() + } + + return 0 +} + // IsInterfaceNil - func (mock *RoundHandlerMock) IsInterfaceNil() bool { return mock == nil diff --git a/node/chainSimulator/components/manualRoundHandler.go b/node/chainSimulator/components/manualRoundHandler.go index f5a3accd792..b7453f08ffb 100644 --- a/node/chainSimulator/components/manualRoundHandler.go +++ b/node/chainSimulator/components/manualRoundHandler.go @@ -124,6 +124,11 @@ func (handler *manualRoundHandler) GetTimeStampForRound(round uint64) uint64 { } +// ComputeCurrentRound returns the current index +func (handler *manualRoundHandler) ComputeCurrentRound() int64 { + return handler.index +} + // IsInterfaceNil returns true if there is no value under the interface func (handler *manualRoundHandler) IsInterfaceNil() bool { return handler == nil diff --git a/process/interface.go b/process/interface.go index c8f43750497..3a93f05ca6e 100644 --- a/process/interface.go +++ b/process/interface.go @@ -1191,6 +1191,7 @@ type RoundHandler interface { TimeDuration() time.Duration RemainingTime(startTime time.Time, maxTime time.Duration) time.Duration GetTimeStampForRound(round uint64) uint64 + ComputeCurrentRound() int64 IsInterfaceNil() bool } diff --git a/process/mock/roundStub.go b/process/mock/roundStub.go index de554ef9bb5..b7c440f6855 100644 --- a/process/mock/roundStub.go +++ b/process/mock/roundStub.go @@ -12,6 +12,7 @@ type RoundStub struct { UpdateRoundCalled func(time.Time, time.Time) RemainingTimeCalled func(time.Time, time.Duration) time.Duration GetTimeStampForRoundCalled func(round uint64) uint64 + ComputeCurrentRoundCalled func() int64 } // Index - @@ -48,6 +49,15 @@ func (rnds *RoundStub) GetTimeStampForRound(round uint64) uint64 { return uint64(time.Unix(0, 0).UnixMilli()) } +// ComputeCurrentRound - +func (rnds *RoundStub) ComputeCurrentRound() int64 { + if rnds.ComputeCurrentRoundCalled != nil { + return rnds.ComputeCurrentRoundCalled() + } + + return 0 +} + // IsInterfaceNil -- func (rnds *RoundStub) IsInterfaceNil() bool { return rnds == nil diff --git a/process/mock/rounderMock.go b/process/mock/rounderMock.go index 1c88a8213fc..d188f7f3f45 100644 --- a/process/mock/rounderMock.go +++ b/process/mock/rounderMock.go @@ -7,11 +7,12 @@ import ( // RoundHandlerMock - type RoundHandlerMock struct { - RoundIndex int64 - RoundTimeStamp time.Time - RoundTimeDuration time.Duration - BeforeGenesisCalled func() bool - RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration + RoundIndex int64 + RoundTimeStamp time.Time + RoundTimeDuration time.Duration + BeforeGenesisCalled func() bool + RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration + ComputeCurrentRoundCalled func() int64 } // BeforeGenesis - @@ -68,6 +69,15 @@ func (rndm *RoundHandlerMock) GetTimeStampForRound(round uint64) uint64 { return 0 } +// ComputeCurrentRound - +func (rndm *RoundHandlerMock) ComputeCurrentRound() int64 { + if rndm.ComputeCurrentRoundCalled != nil { + return rndm.ComputeCurrentRoundCalled() + } + + return 0 +} + // IsInterfaceNil returns true if there is no value under the interface func (rndm *RoundHandlerMock) IsInterfaceNil() bool { return rndm == nil diff --git a/process/track/baseBlockTrack.go b/process/track/baseBlockTrack.go index a2962eb9b27..24e398a0d37 100644 --- a/process/track/baseBlockTrack.go +++ b/process/track/baseBlockTrack.go @@ -491,7 +491,7 @@ func (bbt *baseBlockTrack) CheckProofAgainstRoundHandler(proof data.HeaderProofH } func (bbt *baseBlockTrack) checkAgainstRoundHandler(round uint64) error { - nextRound := bbt.roundHandler.Index() + 1 + nextRound := bbt.roundHandler.ComputeCurrentRound() + 1 if int64(round) > nextRound { return fmt.Errorf("%w header round: %d, next chronology round: %d", process.ErrHigherRoundInBlock, diff --git a/process/track/baseBlockTrack_test.go b/process/track/baseBlockTrack_test.go index 1fcf77c086d..4849d90c623 100644 --- a/process/track/baseBlockTrack_test.go +++ b/process/track/baseBlockTrack_test.go @@ -2375,6 +2375,9 @@ func TestBaseBlockTrack_CheckBlockAgainstRoundHandlerShouldWork(t *testing.T) { RoundIndex: currentRound, RoundTimeStamp: time.Now(), RoundTimeDuration: time.Second, + ComputeCurrentRoundCalled: func() int64 { + return currentRound + }, }, ) @@ -2404,6 +2407,9 @@ func TestBaseBlockTrack_CheckBlockAgainstRoundHandlerShouldFailOnInvalidWindow(t return remainingTime }, + ComputeCurrentRoundCalled: func() int64 { + return currentRound + }, }, ) diff --git a/testscommon/round/rounderMock.go b/testscommon/round/rounderMock.go index 21488b048f5..54327300f6d 100644 --- a/testscommon/round/rounderMock.go +++ b/testscommon/round/rounderMock.go @@ -15,6 +15,7 @@ type RoundHandlerMock struct { RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration GetTimeStampForRoundCalled func(round uint64) uint64 BeforeGenesisCalled func() bool + ComputeCurrentRoundCalled func() int64 } // BeforeGenesis - @@ -83,6 +84,15 @@ func (rndm *RoundHandlerMock) GetTimeStampForRound(round uint64) uint64 { return 0 } +// ComputeCurrentRound - +func (rndm *RoundHandlerMock) ComputeCurrentRound() int64 { + if rndm.ComputeCurrentRoundCalled != nil { + return rndm.ComputeCurrentRoundCalled() + } + + return 0 +} + // IsInterfaceNil returns true if there is no value under the interface func (rndm *RoundHandlerMock) IsInterfaceNil() bool { return rndm == nil diff --git a/testscommon/roundHandlerMock.go b/testscommon/roundHandlerMock.go index 7f5451ac9e9..835d678d2f2 100644 --- a/testscommon/roundHandlerMock.go +++ b/testscommon/roundHandlerMock.go @@ -18,6 +18,7 @@ type RoundHandlerMock struct { BeforeGenesisCalled func() bool IncrementIndexCalled func() GetTimeStampForRoundCalled func(round uint64) uint64 + ComputeCurrentRoundCalled func() int64 } // BeforeGenesis - @@ -98,6 +99,15 @@ func (rndm *RoundHandlerMock) GetTimeStampForRound(round uint64) uint64 { return 0 } +// ComputeCurrentRound - +func (rndm *RoundHandlerMock) ComputeCurrentRound() int64 { + if rndm.ComputeCurrentRoundCalled != nil { + return rndm.ComputeCurrentRoundCalled() + } + + return 0 +} + // IsInterfaceNil returns true if there is no value under the interface func (rndm *RoundHandlerMock) IsInterfaceNil() bool { return rndm == nil From 03df0bc00d84104549198494e6bce8f47f8e02ce Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Wed, 1 Apr 2026 16:24:37 +0300 Subject: [PATCH 09/12] fix tests --- epochStart/mock/rounderStub.go | 2 +- integrationTests/mock/roundHandlerMock.go | 2 +- process/mock/rounderMock.go | 2 +- testscommon/round/rounderMock.go | 2 +- testscommon/roundHandlerMock.go | 6 +++++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/epochStart/mock/rounderStub.go b/epochStart/mock/rounderStub.go index 04d5547e41c..a67288b9041 100644 --- a/epochStart/mock/rounderStub.go +++ b/epochStart/mock/rounderStub.go @@ -78,7 +78,7 @@ func (rndm *RoundHandlerStub) ComputeCurrentRound() int64 { return rndm.ComputeCurrentRoundCalled() } - return 0 + return rndm.RoundIndex } // IsInterfaceNil returns true if there is no value under the interface diff --git a/integrationTests/mock/roundHandlerMock.go b/integrationTests/mock/roundHandlerMock.go index 485be736b7c..5a42cb6a16d 100644 --- a/integrationTests/mock/roundHandlerMock.go +++ b/integrationTests/mock/roundHandlerMock.go @@ -65,7 +65,7 @@ func (mock *RoundHandlerMock) ComputeCurrentRound() int64 { return mock.ComputeCurrentRoundCalled() } - return 0 + return mock.IndexField } // IsInterfaceNil - diff --git a/process/mock/rounderMock.go b/process/mock/rounderMock.go index d188f7f3f45..522f06e47c0 100644 --- a/process/mock/rounderMock.go +++ b/process/mock/rounderMock.go @@ -75,7 +75,7 @@ func (rndm *RoundHandlerMock) ComputeCurrentRound() int64 { return rndm.ComputeCurrentRoundCalled() } - return 0 + return rndm.RoundIndex } // IsInterfaceNil returns true if there is no value under the interface diff --git a/testscommon/round/rounderMock.go b/testscommon/round/rounderMock.go index 54327300f6d..9411fa3a3cf 100644 --- a/testscommon/round/rounderMock.go +++ b/testscommon/round/rounderMock.go @@ -90,7 +90,7 @@ func (rndm *RoundHandlerMock) ComputeCurrentRound() int64 { return rndm.ComputeCurrentRoundCalled() } - return 0 + return rndm.RoundIndex } // IsInterfaceNil returns true if there is no value under the interface diff --git a/testscommon/roundHandlerMock.go b/testscommon/roundHandlerMock.go index 835d678d2f2..077ef99fed8 100644 --- a/testscommon/roundHandlerMock.go +++ b/testscommon/roundHandlerMock.go @@ -105,7 +105,11 @@ func (rndm *RoundHandlerMock) ComputeCurrentRound() int64 { return rndm.ComputeCurrentRoundCalled() } - return 0 + rndm.indexMut.RLock() + idx := rndm.index + rndm.indexMut.RUnlock() + + return idx } // IsInterfaceNil returns true if there is no value under the interface From 03507d5bf6ff5119e40fceb18cdc958d6fd63b2e Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Fri, 3 Apr 2026 14:40:11 +0300 Subject: [PATCH 10/12] remove header by nonce so all headers will be removed --- consensus/spos/worker.go | 4 ++-- process/block/baseProcess.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/consensus/spos/worker.go b/consensus/spos/worker.go index 20556782702..fe42e64cd00 100644 --- a/consensus/spos/worker.go +++ b/consensus/spos/worker.go @@ -37,7 +37,7 @@ const sleepTime = 5 * time.Millisecond const redundancySingleKeySteppedIn = "single-key node stepped in" type blockProcessorWithPool interface { - RemoveHeaderFromPool(headerHash []byte) + RemoveHeaderFromPool(headerNonce uint64) } // Worker defines the data needed by spos to communicate between nodes which are in the validators group @@ -909,7 +909,7 @@ func (wrk *Worker) removeConsensusHeaderFromPool() { return } - blockProcessorWithPoolAccess.RemoveHeaderFromPool(headerHash) + blockProcessorWithPoolAccess.RemoveHeaderFromPool(header.GetNonce()) wrk.forkDetector.RemoveHeader(header.GetNonce(), headerHash) } diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 81b0e1ad9d1..98cc1decde3 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -2353,9 +2353,9 @@ func (bp *baseProcessor) restoreBlockBody(headerHandler data.HeaderHandler, body } // RemoveHeaderFromPool removes the header from the pool -func (bp *baseProcessor) RemoveHeaderFromPool(headerHash []byte) { +func (bp *baseProcessor) RemoveHeaderFromPool(headerNonce uint64) { headersPool := bp.dataPool.Headers() - headersPool.RemoveHeaderByHash(headerHash) + headersPool.RemoveHeaderByNonceAndShardId(headerNonce, bp.shardCoordinator.SelfId()) } // RestoreBlockBodyIntoPools restores the block body into associated pools From b6ba18f63d16c5824a1a2500f9c52af3f354e601 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 29 Jun 2026 17:37:23 +0300 Subject: [PATCH 11/12] fix after merge --- node/mock/rounderMock.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/node/mock/rounderMock.go b/node/mock/rounderMock.go index 9cf1f1a4f42..06b173d0fea 100644 --- a/node/mock/rounderMock.go +++ b/node/mock/rounderMock.go @@ -15,6 +15,15 @@ type RoundHandlerMock struct { RemainingTimeCalled func(startTime time.Time, maxTime time.Duration) time.Duration BeforeGenesisCalled func() bool GetTimeStampForRoundCalled func(round uint64) uint64 + ComputeCurrentRoundCalled func() int64 +} + +// ComputeCurrentRound - +func (rndm *RoundHandlerMock) ComputeCurrentRound() int64 { + if rndm.ComputeCurrentRoundCalled != nil { + return rndm.ComputeCurrentRoundCalled() + } + return 0 } // BeforeGenesis - From b3c3c88d9941d99a7a2d968b129bdb48779460ff Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 29 Jun 2026 18:34:05 +0300 Subject: [PATCH 12/12] fix tests after merge --- consensus/spos/worker_test.go | 6 +++--- testscommon/blockProcessorStub.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/consensus/spos/worker_test.go b/consensus/spos/worker_test.go index 819a4dacc2f..a4b7f379a4e 100644 --- a/consensus/spos/worker_test.go +++ b/consensus/spos/worker_test.go @@ -2208,7 +2208,7 @@ func TestWorker_ExtendShouldNotRemoveConsensusHeaderFromPoolsWhenAsyncExecutionI RevertCurrentBlockCalled: func() { revertCalled = true }, - RemoveHeaderFromPoolCalled: func(headerHash []byte) { + RemoveHeaderFromPoolCalled: func(_ uint64) { removeHeaderFromPoolCalled = true }, } @@ -2251,9 +2251,9 @@ func TestWorker_ExtendShouldRemoveConsensusHeaderFromPoolsWhenAsyncExecutionIsDi RevertCurrentBlockCalled: func() { revertCalled = true }, - RemoveHeaderFromPoolCalled: func(hash []byte) { + RemoveHeaderFromPoolCalled: func(nonce uint64) { removeHeaderFromPoolCalled = true - require.Equal(t, headerHash, hash) + require.Equal(t, header.GetNonce(), nonce) }, } wrk.SetBlockProcessor(blockProcessor) diff --git a/testscommon/blockProcessorStub.go b/testscommon/blockProcessorStub.go index 2b06d3015b7..66f977481e3 100644 --- a/testscommon/blockProcessorStub.go +++ b/testscommon/blockProcessorStub.go @@ -46,7 +46,7 @@ type BlockProcessorStub struct { _ []byte, ) error OnExecutedBlockCalled func(header data.HeaderHandler, rootHash []byte) error - RemoveHeaderFromPoolCalled func(headerHash []byte) + RemoveHeaderFromPoolCalled func(headerNonce uint64) ProposedDirectSentTransactionsToBroadcastCalled func(proposedBody data.BodyHandler) map[string][][]byte PruneTrieAsyncHeaderCalled func() } @@ -280,9 +280,9 @@ func (bps *BlockProcessorStub) OnExecutedBlock(header data.HeaderHandler, rootHa } // RemoveHeaderFromPool - -func (bps *BlockProcessorStub) RemoveHeaderFromPool(headerHash []byte) { +func (bps *BlockProcessorStub) RemoveHeaderFromPool(headerNonce uint64) { if bps.RemoveHeaderFromPoolCalled != nil { - bps.RemoveHeaderFromPoolCalled(headerHash) + bps.RemoveHeaderFromPoolCalled(headerNonce) } }