From 85dca04de0d95d8ddc5bc5c9fed9ff980350106d Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 25 Sep 2024 20:53:56 +0300 Subject: [PATCH 01/29] add proof signature check in header check --- process/headerCheck/headerSignatureVerify.go | 5 +++-- process/headerCheck/headerSignatureVerify_test.go | 3 ++- .../processor/argHdrInterceptorProcessor.go | 1 + .../interceptors/processor/hdrInterceptorProcessor.go | 7 +++++++ .../processor/hdrInterceptorProcessor_test.go | 11 +++++++++++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index 379f6ae6f3c..4da2a27230b 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -262,7 +262,8 @@ func (hsv *HeaderSigVerifier) getPrevHeaderInfo(currentHeader data.HeaderHandler return headerCopy, hash, sig, bitmap, nil } -// VerifyPreviousBlockProof verifies if the structure of the header matches the expected structure in regards with the consensus flag +// VerifyPreviousBlockProof verifies if the structure of the header matches the expected structure in regards with the consensus flag. +// It also verifies previous block proof singature func (hsv *HeaderSigVerifier) VerifyPreviousBlockProof(header data.HeaderHandler) error { previousProof := header.GetPreviousProof() @@ -289,7 +290,7 @@ func (hsv *HeaderSigVerifier) VerifyPreviousBlockProof(header data.HeaderHandler return fmt.Errorf("%w, received header without leader signature after flag activation", process.ErrInvalidHeader) } - return nil + return hsv.VerifyHeaderProof(previousProof) } func (hsv *HeaderSigVerifier) verifyConsensusSize(consensusPubKeys []string, header data.HeaderHandler, bitmap []byte) error { diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index dd361ca8f7c..88927ba3784 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -722,7 +722,8 @@ func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { args := createHeaderSigVerifierArgs() args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag + return flag == common.EquivalentMessagesFlag || + flag == common.FixedOrderInConsensusFlag }, } diff --git a/process/interceptors/processor/argHdrInterceptorProcessor.go b/process/interceptors/processor/argHdrInterceptorProcessor.go index 53e79b731b7..818982406f4 100644 --- a/process/interceptors/processor/argHdrInterceptorProcessor.go +++ b/process/interceptors/processor/argHdrInterceptorProcessor.go @@ -8,5 +8,6 @@ import ( // ArgHdrInterceptorProcessor is the argument for the interceptor processor used for headers (shard, meta and so on) type ArgHdrInterceptorProcessor struct { Headers dataRetriever.HeadersPool + Proofs dataRetriever.ProofsPool BlockBlackList process.TimeCacher } diff --git a/process/interceptors/processor/hdrInterceptorProcessor.go b/process/interceptors/processor/hdrInterceptorProcessor.go index b71d5b73e59..d87c49bead2 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor.go +++ b/process/interceptors/processor/hdrInterceptorProcessor.go @@ -16,6 +16,7 @@ var _ process.InterceptorProcessor = (*HdrInterceptorProcessor)(nil) // (shard headers, meta headers) structs which satisfy HeaderHandler interface. type HdrInterceptorProcessor struct { headers dataRetriever.HeadersPool + proofs dataRetriever.ProofsPool blackList process.TimeCacher registeredHandlers []func(topic string, hash []byte, data interface{}) mutHandlers sync.RWMutex @@ -29,12 +30,16 @@ func NewHdrInterceptorProcessor(argument *ArgHdrInterceptorProcessor) (*HdrInter if check.IfNil(argument.Headers) { return nil, process.ErrNilCacher } + if check.IfNil(argument.Proofs) { + return nil, process.ErrNilEquivalentProofsPool + } if check.IfNil(argument.BlockBlackList) { return nil, process.ErrNilBlackListCacher } return &HdrInterceptorProcessor{ headers: argument.Headers, + proofs: argument.Proofs, blackList: argument.BlockBlackList, registeredHandlers: make([]func(topic string, hash []byte, data interface{}), 0), }, nil @@ -68,6 +73,8 @@ func (hip *HdrInterceptorProcessor) Save(data process.InterceptedData, _ core.Pe hip.headers.AddHeader(interceptedHdr.Hash(), interceptedHdr.HeaderHandler()) + _ = hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) + return nil } diff --git a/process/interceptors/processor/hdrInterceptorProcessor_test.go b/process/interceptors/processor/hdrInterceptorProcessor_test.go index 87fe3521ff7..c856d2d5c4b 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor_test.go +++ b/process/interceptors/processor/hdrInterceptorProcessor_test.go @@ -10,12 +10,14 @@ import ( "github.com/multiversx/mx-chain-go/process/interceptors/processor" "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/testscommon" + "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/stretchr/testify/assert" ) func createMockHdrArgument() *processor.ArgHdrInterceptorProcessor { arg := &processor.ArgHdrInterceptorProcessor{ Headers: &mock.HeadersCacherStub{}, + Proofs: &dataRetriever.ProofsPoolMock{}, BlockBlackList: &testscommon.TimeCacheStub{}, } @@ -166,6 +168,14 @@ func TestHdrInterceptorProcessor_SaveShouldWork(t *testing.T) { }, } + wasAddedProofs := false + arg.Proofs = &dataRetriever.ProofsPoolMock{ + AddProofCalled: func(headerProof data.HeaderProofHandler) error { + wasAddedProofs = true + return nil + }, + } + hip, _ := processor.NewHdrInterceptorProcessor(arg) chanCalled := make(chan struct{}, 1) hip.RegisterHandler(func(topic string, hash []byte, data interface{}) { @@ -176,6 +186,7 @@ func TestHdrInterceptorProcessor_SaveShouldWork(t *testing.T) { assert.Nil(t, err) assert.True(t, wasAddedHeaders) + assert.True(t, wasAddedProofs) timeout := time.Second * 2 select { From 712e0da0aa79bb374163f14f7b58fdb19ec3cb25 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 25 Sep 2024 20:54:04 +0300 Subject: [PATCH 02/29] wait for confirmation block in epoch start block syncer --- .../bootstrap/epochStartMetaBlockProcessor.go | 168 +++++++++++++++--- epochStart/bootstrap/interface.go | 1 + 2 files changed, 146 insertions(+), 23 deletions(-) diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor.go b/epochStart/bootstrap/epochStartMetaBlockProcessor.go index ff1a4370ad7..5077cbcf054 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor.go @@ -2,6 +2,7 @@ package bootstrap import ( "context" + "fmt" "math" "sync" "time" @@ -26,14 +27,21 @@ const minNumConnectedPeers = 1 var _ process.InterceptorProcessor = (*epochStartMetaBlockProcessor)(nil) type epochStartMetaBlockProcessor struct { - messenger Messenger - requestHandler RequestHandler - marshalizer marshal.Marshalizer - hasher hashing.Hasher - mutReceivedMetaBlocks sync.RWMutex - mapReceivedMetaBlocks map[string]data.MetaHeaderHandler - mapMetaBlocksFromPeers map[string][]core.PeerID + messenger Messenger + requestHandler RequestHandler + marshalizer marshal.Marshalizer + hasher hashing.Hasher + mutReceivedMetaBlocks sync.RWMutex + mapReceivedMetaBlocks map[string]data.MetaHeaderHandler + mapMetaBlocksFromPeers map[string][]core.PeerID + + mutReceivedConfMetaBlocks sync.RWMutex + mapReceivedConfMetaBlocks map[string]data.MetaHeaderHandler + mapConfMetaBlocksFromPeers map[string][]core.PeerID + chanConsensusReached chan bool + chanMetaBlockReached chan bool + chanConfMetaBlockReached chan bool metaBlock data.MetaHeaderHandler peerCountTarget int minNumConnectedPeers int @@ -82,6 +90,8 @@ func NewEpochStartMetaBlockProcessor( mutReceivedMetaBlocks: sync.RWMutex{}, mapReceivedMetaBlocks: make(map[string]data.MetaHeaderHandler), mapMetaBlocksFromPeers: make(map[string][]core.PeerID), + mapReceivedConfMetaBlocks: make(map[string]data.MetaHeaderHandler), + mapConfMetaBlocksFromPeers: make(map[string][]core.PeerID), chanConsensusReached: make(chan bool, 1), } @@ -136,22 +146,45 @@ func (e *epochStartMetaBlockProcessor) Save(data process.InterceptedData, fromCo return nil } - if !metaBlock.IsStartOfEpochBlock() { - log.Debug("received metablock is not of type epoch start", "error", epochStart.ErrNotEpochStartBlock) + mbHash := interceptedHdr.Hash() + + if metaBlock.IsStartOfEpochBlock() { + log.Debug("received epoch start meta", "epoch", metaBlock.GetEpoch(), "from peer", fromConnectedPeer.Pretty()) + e.mutReceivedMetaBlocks.Lock() + e.mapReceivedMetaBlocks[string(mbHash)] = metaBlock + e.addToPeerList(string(mbHash), fromConnectedPeer) + e.mutReceivedMetaBlocks.Unlock() + return nil } - mbHash := interceptedHdr.Hash() + if e.isEpochStartConfirmationBlock(metaBlock) { + log.Debug("received epoch start confirmation meta", "epoch", metaBlock.GetEpoch(), "from peer", fromConnectedPeer.Pretty()) + e.mutReceivedConfMetaBlocks.Lock() + e.mapReceivedConfMetaBlocks[string(mbHash)] = metaBlock + e.addToConfPeerList(string(mbHash), fromConnectedPeer) + e.mutReceivedConfMetaBlocks.Unlock() - log.Debug("received epoch start meta", "epoch", metaBlock.GetEpoch(), "from peer", fromConnectedPeer.Pretty()) - e.mutReceivedMetaBlocks.Lock() - e.mapReceivedMetaBlocks[string(mbHash)] = metaBlock - e.addToPeerList(string(mbHash), fromConnectedPeer) - e.mutReceivedMetaBlocks.Unlock() + return nil + } + log.Debug("received metablock is not of type epoch start", "error", epochStart.ErrNotEpochStartBlock) return nil } +func (e *epochStartMetaBlockProcessor) isEpochStartConfirmationBlock(metaBlock data.HeaderHandler) bool { + startOfEpochMetaBlock, err := e.getMostReceivedMetaBlock() + if err != nil { + return false + } + + if startOfEpochMetaBlock.GetNonce() != metaBlock.GetNonce()-1 { + return false + } + + return true +} + // this func should be called under mutex protection func (e *epochStartMetaBlockProcessor) addToPeerList(hash string, peer core.PeerID) { peersListForHash := e.mapMetaBlocksFromPeers[hash] @@ -163,6 +196,16 @@ func (e *epochStartMetaBlockProcessor) addToPeerList(hash string, peer core.Peer e.mapMetaBlocksFromPeers[hash] = append(e.mapMetaBlocksFromPeers[hash], peer) } +func (e *epochStartMetaBlockProcessor) addToConfPeerList(hash string, peer core.PeerID) { + peersListForHash := e.mapConfMetaBlocksFromPeers[hash] + for _, pid := range peersListForHash { + if pid == peer { + return + } + } + e.mapConfMetaBlocksFromPeers[hash] = append(e.mapConfMetaBlocksFromPeers[hash], peer) +} + // GetEpochStartMetaBlock will return the metablock after it is confirmed or an error if the number of tries was exceeded // This is a blocking method which will end after the consensus for the meta block is obtained or the context is done func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Context) (data.MetaHeaderHandler, error) { @@ -180,7 +223,16 @@ func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Contex } }() - err = e.requestMetaBlock() + err = e.waitForMetaBlock(ctx) + if err != nil { + return nil, err + } + + if check.IfNil(e.metaBlock) { + return nil, epochStart.ErrNilMetaBlock + } + + err = e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) if err != nil { return nil, err } @@ -194,7 +246,7 @@ func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Contex case <-ctx.Done(): return e.getMostReceivedMetaBlock() case <-chanRequests: - err = e.requestMetaBlock() + err = e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) if err != nil { return nil, err } @@ -206,6 +258,34 @@ func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Contex } } +func (e *epochStartMetaBlockProcessor) waitForMetaBlock(ctx context.Context) error { + err := e.requestMetaBlock() + if err != nil { + return err + } + + chanRequests := time.After(durationBetweenReRequests) + chanCheckMaps := time.After(durationBetweenChecks) + + for { + select { + case <-e.chanMetaBlockReached: + return nil + case <-ctx.Done(): + return fmt.Errorf("did not received epoch start meta block") + case <-chanRequests: + err = e.requestMetaBlock() + if err != nil { + return err + } + chanRequests = time.After(durationBetweenReRequests) + case <-chanCheckMaps: + e.checkMetaBlockMaps() + chanCheckMaps = time.After(durationBetweenChecks) + } + } +} + func (e *epochStartMetaBlockProcessor) getMostReceivedMetaBlock() (data.MetaHeaderHandler, error) { e.mutReceivedMetaBlocks.RLock() defer e.mutReceivedMetaBlocks.RUnlock() @@ -238,27 +318,69 @@ func (e *epochStartMetaBlockProcessor) requestMetaBlock() error { return nil } -func (e *epochStartMetaBlockProcessor) checkMaps() { +func (e *epochStartMetaBlockProcessor) requestConfirmationMetaBlock(nonce uint64) error { + numConnectedPeers := len(e.messenger.ConnectedPeers()) + err := e.requestHandler.SetNumPeersToQuery(factory.MetachainBlocksTopic, numConnectedPeers, numConnectedPeers) + if err != nil { + return err + } + + e.requestHandler.RequestMetaHeaderByNonce(nonce) + + return nil +} + +func (e *epochStartMetaBlockProcessor) checkMetaBlockMaps() { e.mutReceivedMetaBlocks.RLock() defer e.mutReceivedMetaBlocks.RUnlock() for hash, peersList := range e.mapMetaBlocksFromPeers { log.Debug("metablock from peers", "num peers", len(peersList), "target", e.peerCountTarget, "hash", []byte(hash)) - found := e.processEntry(peersList, hash) - if found { + metaBlockFound := e.processMetaBlockEntry(peersList, hash) + if metaBlockFound { + e.metaBlock = e.mapReceivedMetaBlocks[hash] + e.chanMetaBlockReached <- true break } } } -func (e *epochStartMetaBlockProcessor) processEntry( +func (e *epochStartMetaBlockProcessor) checkMaps() { + e.mutReceivedMetaBlocks.RLock() + defer e.mutReceivedMetaBlocks.RUnlock() + + metaBlockFound := e.checkReceivedMetaBlock(e.mapMetaBlocksFromPeers) + confMetaBlockFound := e.checkReceivedMetaBlock(e.mapConfMetaBlocksFromPeers) + + // no need to check proof here since it is check in interceptor + if metaBlockFound && confMetaBlockFound { + e.chanConsensusReached <- true + } +} + +func (e *epochStartMetaBlockProcessor) checkReceivedMetaBlock(blocksFromPeers map[string][]core.PeerID) bool { + for hash, peersList := range blocksFromPeers { + log.Debug("metablock from peers", "num peers", len(peersList), "target", e.peerCountTarget, "hash", []byte(hash)) + + metaBlockFound := e.processMetaBlockEntry(peersList, hash) + if metaBlockFound { + return true + } + } + + return false +} + +func (e *epochStartMetaBlockProcessor) checkMetaBlockProof() bool { + return true +} + +func (e *epochStartMetaBlockProcessor) processMetaBlockEntry( peersList []core.PeerID, hash string, ) bool { if len(peersList) >= e.peerCountTarget { log.Info("got consensus for epoch start metablock", "len", len(peersList)) - e.metaBlock = e.mapReceivedMetaBlocks[hash] - e.chanConsensusReached <- true return true } diff --git a/epochStart/bootstrap/interface.go b/epochStart/bootstrap/interface.go index bfc293032ee..7a128098059 100644 --- a/epochStart/bootstrap/interface.go +++ b/epochStart/bootstrap/interface.go @@ -49,6 +49,7 @@ type Messenger interface { // RequestHandler defines which methods a request handler should implement type RequestHandler interface { RequestStartOfEpochMetaBlock(epoch uint32) + RequestMetaHeaderByNonce(nonce uint64) SetNumPeersToQuery(topic string, intra int, cross int) error GetNumPeersToQuery(topic string) (int, int, error) IsInterfaceNil() bool From 4bddfce54e383872e5f503a28e0c91b4260b5afa Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 25 Sep 2024 21:40:39 +0300 Subject: [PATCH 03/29] fix epoch start meta block syncer tests --- .../bootstrap/epochStartMetaBlockProcessor.go | 6 +-- .../epochStartMetaBlockProcessor_test.go | 37 ++++++++++++++++++- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor.go b/epochStart/bootstrap/epochStartMetaBlockProcessor.go index 5077cbcf054..a5b3845c5d1 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor.go @@ -2,7 +2,6 @@ package bootstrap import ( "context" - "fmt" "math" "sync" "time" @@ -41,7 +40,6 @@ type epochStartMetaBlockProcessor struct { chanConsensusReached chan bool chanMetaBlockReached chan bool - chanConfMetaBlockReached chan bool metaBlock data.MetaHeaderHandler peerCountTarget int minNumConnectedPeers int @@ -93,6 +91,7 @@ func NewEpochStartMetaBlockProcessor( mapReceivedConfMetaBlocks: make(map[string]data.MetaHeaderHandler), mapConfMetaBlocksFromPeers: make(map[string][]core.PeerID), chanConsensusReached: make(chan bool, 1), + chanMetaBlockReached: make(chan bool, 1), } processor.waitForEnoughNumConnectedPeers(messenger) @@ -239,6 +238,7 @@ func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Contex chanRequests := time.After(durationBetweenReRequests) chanCheckMaps := time.After(durationBetweenChecks) + for { select { case <-e.chanConsensusReached: @@ -272,7 +272,7 @@ func (e *epochStartMetaBlockProcessor) waitForMetaBlock(ctx context.Context) err case <-e.chanMetaBlockReached: return nil case <-ctx.Done(): - return fmt.Errorf("did not received epoch start meta block") + return epochStart.ErrTimeoutWaitingForMetaBlock case <-chanRequests: err = e.requestMetaBlock() if err != nil { diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go b/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go index 1741c63a25c..03ce113299b 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go @@ -264,21 +264,29 @@ func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldReturnMostRece &hashingMocks.HasherMock{}, 99, 3, - 3, + 5, ) expectedMetaBlock := &block.MetaBlock{ Nonce: 10, EpochStart: block.EpochStart{LastFinalizedHeaders: []block.EpochStartShardData{{Round: 1}}}, } + confirmationMetaBlock := &block.MetaBlock{ + Nonce: 11, + } intData := mock.NewInterceptedMetaBlockMock(expectedMetaBlock, []byte("hash")) + intData2 := mock.NewInterceptedMetaBlockMock(confirmationMetaBlock, []byte("hash2")) for i := 0; i < esmbp.minNumOfPeersToConsiderBlockValid; i++ { _ = esmbp.Save(intData, core.PeerID(fmt.Sprintf("peer_%d", i)), "") } + for i := 0; i < esmbp.minNumOfPeersToConsiderBlockValid; i++ { + _ = esmbp.Save(intData2, core.PeerID(fmt.Sprintf("peer_%d", i)), "") + } + // we need a slightly more time than 1 second in order to also properly test the select branches - timeout := time.Second + time.Millisecond*500 + timeout := 2*time.Second + time.Millisecond*500 ctx, cancel := context.WithTimeout(context.Background(), timeout) mb, err := esmbp.GetEpochStartMetaBlock(ctx) cancel() @@ -307,12 +315,20 @@ func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldWorkFromFirstT Nonce: 10, EpochStart: block.EpochStart{LastFinalizedHeaders: []block.EpochStartShardData{{Round: 1}}}, } + confirmationMetaBlock := &block.MetaBlock{ + Nonce: 11, + } intData := mock.NewInterceptedMetaBlockMock(expectedMetaBlock, []byte("hash")) + intData2 := mock.NewInterceptedMetaBlockMock(confirmationMetaBlock, []byte("hash2")) for i := 0; i < 6; i++ { _ = esmbp.Save(intData, core.PeerID(fmt.Sprintf("peer_%d", i)), "") } + for i := 0; i < 6; i++ { + _ = esmbp.Save(intData2, core.PeerID(fmt.Sprintf("peer_%d", i)), "") + } + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) mb, err := esmbp.GetEpochStartMetaBlock(ctx) cancel() @@ -351,6 +367,12 @@ func testEpochStartMbIsReceivedWithSleepBetweenReceivedMessages(t *testing.T, tt EpochStart: block.EpochStart{LastFinalizedHeaders: []block.EpochStartShardData{{Round: 1}}}, } intData := mock.NewInterceptedMetaBlockMock(expectedMetaBlock, []byte("hash")) + + confirmationMetaBlock := &block.MetaBlock{ + Nonce: 11, + } + intData2 := mock.NewInterceptedMetaBlockMock(confirmationMetaBlock, []byte("hash2")) + go func() { index := 0 for { @@ -360,6 +382,17 @@ func testEpochStartMbIsReceivedWithSleepBetweenReceivedMessages(t *testing.T, tt index += 2 } }() + + go func() { + index := 0 + for { + time.Sleep(tts) + _ = esmbp.Save(intData2, core.PeerID(fmt.Sprintf("peer_%d", index)), "") + _ = esmbp.Save(intData2, core.PeerID(fmt.Sprintf("peer_%d", index+1)), "") + index += 2 + } + }() + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) mb, err := esmbp.GetEpochStartMetaBlock(ctx) cancel() From 66316b2f00d91ba2cd43830356ba9e72e6aeb15d Mon Sep 17 00:00:00 2001 From: ssd04 Date: Thu, 3 Oct 2024 22:35:45 +0300 Subject: [PATCH 04/29] added proofs pool in process sync --- epochStart/bootstrap/common.go | 3 ++ epochStart/bootstrap/process.go | 4 ++ epochStart/bootstrap/process_test.go | 1 + factory/bootstrap/bootstrapComponents.go | 1 + factory/consensus/consensusComponents.go | 1 + .../startInEpoch/startInEpoch_test.go | 2 + integrationTests/testSyncNode.go | 1 + process/errors.go | 3 ++ process/sync/argBootstrapper.go | 2 + process/sync/baseSync.go | 49 +++++++++++++++---- process/sync/metablock.go | 5 ++ process/sync/metablock_test.go | 2 + process/sync/shardblock.go | 4 ++ process/sync/shardblock_test.go | 30 +++++++++++- 14 files changed, 96 insertions(+), 12 deletions(-) diff --git a/epochStart/bootstrap/common.go b/epochStart/bootstrap/common.go index da6e99fda1b..a6621f86ed8 100644 --- a/epochStart/bootstrap/common.go +++ b/epochStart/bootstrap/common.go @@ -123,6 +123,9 @@ func checkArguments(args ArgsEpochStartBootstrap) error { if check.IfNil(args.NodesCoordinatorRegistryFactory) { return fmt.Errorf("%s: %w", baseErrorMessage, nodesCoordinator.ErrNilNodesCoordinatorRegistryFactory) } + if check.IfNil(args.EnableEpochsHandler) { + return fmt.Errorf("%s: %w", baseErrorMessage, epochStart.ErrNilEnableEpochsHandler) + } return nil } diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index d8fef964e6a..9c0d530fcdc 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -121,6 +121,8 @@ type epochStartBootstrap struct { nodeProcessingMode common.NodeProcessingMode nodeOperationMode common.NodeOperation stateStatsHandler common.StateStatisticsHandler + enableEpochsHandler common.EnableEpochsHandler + // created components requestHandler process.RequestHandler mainInterceptorContainer process.InterceptorsContainer @@ -190,6 +192,7 @@ type ArgsEpochStartBootstrap struct { NodeProcessingMode common.NodeProcessingMode StateStatsHandler common.StateStatisticsHandler NodesCoordinatorRegistryFactory nodesCoordinator.NodesCoordinatorRegistryFactory + EnableEpochsHandler common.EnableEpochsHandler } type dataToSync struct { @@ -242,6 +245,7 @@ func NewEpochStartBootstrap(args ArgsEpochStartBootstrap) (*epochStartBootstrap, stateStatsHandler: args.StateStatsHandler, startEpoch: args.GeneralConfig.EpochStartConfig.GenesisEpoch, nodesCoordinatorRegistryFactory: args.NodesCoordinatorRegistryFactory, + enableEpochsHandler: args.EnableEpochsHandler, } if epochStartProvider.prefsConfig.FullArchive { diff --git a/epochStart/bootstrap/process_test.go b/epochStart/bootstrap/process_test.go index 7878f3842be..616d30c2389 100644 --- a/epochStart/bootstrap/process_test.go +++ b/epochStart/bootstrap/process_test.go @@ -253,6 +253,7 @@ func createMockEpochStartBootstrapArgs( }, TrieSyncStatisticsProvider: &testscommon.SizeSyncStatisticsHandlerStub{}, StateStatsHandler: disabledStatistics.NewStateStatistics(), + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, } } diff --git a/factory/bootstrap/bootstrapComponents.go b/factory/bootstrap/bootstrapComponents.go index a9ef7851ccb..efd1c4f0e4a 100644 --- a/factory/bootstrap/bootstrapComponents.go +++ b/factory/bootstrap/bootstrapComponents.go @@ -224,6 +224,7 @@ func (bcf *bootstrapComponentsFactory) Create() (*bootstrapComponents, error) { NodeProcessingMode: common.GetNodeProcessingMode(&bcf.importDbConfig), StateStatsHandler: bcf.statusCoreComponents.StateStatsHandler(), NodesCoordinatorRegistryFactory: nodesCoordinatorRegistryFactory, + EnableEpochsHandler: bcf.coreComponents.EnableEpochsHandler(), } var epochStartBootstrapper factory.EpochStartBootstrapper diff --git a/factory/consensus/consensusComponents.go b/factory/consensus/consensusComponents.go index d824f80ea64..8614abcf5e3 100644 --- a/factory/consensus/consensusComponents.go +++ b/factory/consensus/consensusComponents.go @@ -629,6 +629,7 @@ func (ccf *consensusComponentsFactory) createMetaChainBootstrapper() (process.Bo ScheduledTxsExecutionHandler: ccf.processComponents.ScheduledTxsExecutionHandler(), ProcessWaitTime: time.Duration(ccf.config.GeneralSettings.SyncProcessTimeInMillis) * time.Millisecond, RepopulateTokensSupplies: ccf.flagsConfig.RepopulateTokensSupplies, + EnableEpochsHandler: ccf.coreComponents.EnableEpochsHandler(), } argsMetaBootstrapper := sync.ArgMetaBootstrapper{ diff --git a/integrationTests/multiShard/endOfEpoch/startInEpoch/startInEpoch_test.go b/integrationTests/multiShard/endOfEpoch/startInEpoch/startInEpoch_test.go index 13dab2a87a2..2157e1e55a4 100644 --- a/integrationTests/multiShard/endOfEpoch/startInEpoch/startInEpoch_test.go +++ b/integrationTests/multiShard/endOfEpoch/startInEpoch/startInEpoch_test.go @@ -34,6 +34,7 @@ import ( "github.com/multiversx/mx-chain-go/storage/storageunit" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/chainParameters" + "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" epochNotifierMock "github.com/multiversx/mx-chain-go/testscommon/epochNotifier" "github.com/multiversx/mx-chain-go/testscommon/genericMocks" "github.com/multiversx/mx-chain-go/testscommon/genesisMocks" @@ -284,6 +285,7 @@ func testNodeStartsInEpoch(t *testing.T, shardID uint32, expectedHighestRound ui }, TrieSyncStatisticsProvider: &testscommon.SizeSyncStatisticsHandlerStub{}, StateStatsHandler: disabled.NewStateStatistics(), + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, } epochStartBootstrap, err := bootstrap.NewEpochStartBootstrap(argsBootstrapHandler) diff --git a/integrationTests/testSyncNode.go b/integrationTests/testSyncNode.go index b28d5e3f953..e0b2753496e 100644 --- a/integrationTests/testSyncNode.go +++ b/integrationTests/testSyncNode.go @@ -222,6 +222,7 @@ func (tpn *TestProcessorNode) createMetaChainBootstrapper() (TestBootstrapper, e ScheduledTxsExecutionHandler: &testscommon.ScheduledTxsExecutionStub{}, ProcessWaitTime: tpn.RoundHandler.TimeDuration(), RepopulateTokensSupplies: false, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, } argsMetaBootstrapper := sync.ArgMetaBootstrapper{ diff --git a/process/errors.go b/process/errors.go index 8edf7342ada..83dca59c437 100644 --- a/process/errors.go +++ b/process/errors.go @@ -239,6 +239,9 @@ var ErrNilMiniBlockPool = errors.New("nil mini block pool") // ErrNilMetaBlocksPool signals that a nil meta blocks pool was used var ErrNilMetaBlocksPool = errors.New("nil meta blocks pool") +// ErrNilProofsPool signals that a nil proofs pool was used +var ErrNilProofsPool = errors.New("nil proofs pool") + // ErrNilTxProcessor signals that a nil transactions processor was used var ErrNilTxProcessor = errors.New("nil transactions processor") diff --git a/process/sync/argBootstrapper.go b/process/sync/argBootstrapper.go index ec3f64a58d8..587ecedd258 100644 --- a/process/sync/argBootstrapper.go +++ b/process/sync/argBootstrapper.go @@ -8,6 +8,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data/typeConverters" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/consensus" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/dblookupext" @@ -48,6 +49,7 @@ type ArgBaseBootstrapper struct { ScheduledTxsExecutionHandler process.ScheduledTxsExecutionHandler ProcessWaitTime time.Duration RepopulateTokensSupplies bool + EnableEpochsHandler common.EnableEpochsHandler } // ArgShardBootstrapper holds all dependencies required by the bootstrap data factory in order to create diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index aa43d8cecc1..203418f0e7e 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -57,21 +57,23 @@ type notarizedInfo struct { type baseBootstrap struct { historyRepo dblookupext.HistoryRepository headers dataRetriever.HeadersPool + proofs dataRetriever.ProofsPool chainHandler data.ChainHandler blockProcessor process.BlockProcessor store dataRetriever.StorageService - roundHandler consensus.RoundHandler - hasher hashing.Hasher - marshalizer marshal.Marshalizer - epochHandler dataRetriever.EpochHandler - forkDetector process.ForkDetector - requestHandler process.RequestHandler - shardCoordinator sharding.Coordinator - accounts state.AccountsAdapter - blockBootstrapper blockBootstrapper - blackListHandler process.TimeCacher + roundHandler consensus.RoundHandler + hasher hashing.Hasher + marshalizer marshal.Marshalizer + epochHandler dataRetriever.EpochHandler + forkDetector process.ForkDetector + requestHandler process.RequestHandler + shardCoordinator sharding.Coordinator + accounts state.AccountsAdapter + blockBootstrapper blockBootstrapper + blackListHandler process.TimeCacher + enableEpochsHandler common.EnableEpochsHandler mutHeader sync.RWMutex headerNonce *uint64 @@ -491,6 +493,9 @@ func checkBaseBootstrapParameters(arguments ArgBaseBootstrapper) error { if arguments.ProcessWaitTime < minimumProcessWaitTime { return fmt.Errorf("%w, minimum is %v, provided is %v", process.ErrInvalidProcessWaitTime, minimumProcessWaitTime, arguments.ProcessWaitTime) } + if check.IfNil(arguments.EnableEpochsHandler) { + return process.ErrNilEnableEpochsHandler + } return nil } @@ -635,6 +640,13 @@ func (boot *baseBootstrap) syncBlock() error { return err } + if boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { + err = boot.proofs.AddProof(header.GetPreviousProof()) + if err != nil { + log.Warn("failed to add proof to pool", "header nonce", header.GetNonce()) + } + } + go boot.requestHeadersFromNonceIfMissing(header.GetNonce() + 1) body, err = boot.blockBootstrapper.getBlockBodyRequestingIfMissing(header) @@ -687,6 +699,7 @@ func (boot *baseBootstrap) syncBlock() error { ) boot.cleanNoncesSyncedWithErrorsBehindFinal() + boot.cleanProofsBehindFinal(header) return nil } @@ -715,6 +728,22 @@ func (boot *baseBootstrap) cleanNoncesSyncedWithErrorsBehindFinal() { } } +func (boot *baseBootstrap) cleanProofsBehindFinal(header data.HeaderHandler) { + if !boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { + return + } + + finalNonce := boot.forkDetector.GetHighestFinalBlockNonce() + + err := boot.proofs.CleanupProofsBehindNonce(header.GetShardID(), finalNonce) + if err != nil { + log.Warn("failed to cleanup notarized proofs behind nonce", + "nonce", finalNonce, + "shardID", header.GetShardID(), + "error", err) + } +} + // rollBack decides if rollBackOneBlock must be called func (boot *baseBootstrap) rollBack(revertUsingForkNonce bool) error { var roleBackOneBlockExecuted bool diff --git a/process/sync/metablock.go b/process/sync/metablock.go index 1b3c69c7386..aeec4d46ead 100644 --- a/process/sync/metablock.go +++ b/process/sync/metablock.go @@ -31,6 +31,9 @@ func NewMetaBootstrap(arguments ArgMetaBootstrapper) (*MetaBootstrap, error) { if check.IfNil(arguments.PoolsHolder.Headers()) { return nil, process.ErrNilMetaBlocksPool } + if check.IfNil(arguments.PoolsHolder.Proofs()) { + return nil, process.ErrNilProofsPool + } if check.IfNil(arguments.EpochBootstrapper) { return nil, process.ErrNilEpochStartTrigger } @@ -54,6 +57,7 @@ func NewMetaBootstrap(arguments ArgMetaBootstrapper) (*MetaBootstrap, error) { blockProcessor: arguments.BlockProcessor, store: arguments.Store, headers: arguments.PoolsHolder.Headers(), + proofs: arguments.PoolsHolder.Proofs(), roundHandler: arguments.RoundHandler, waitTime: arguments.WaitTime, hasher: arguments.Hasher, @@ -78,6 +82,7 @@ func NewMetaBootstrap(arguments ArgMetaBootstrapper) (*MetaBootstrap, error) { historyRepo: arguments.HistoryRepo, scheduledTxsExecutionHandler: arguments.ScheduledTxsExecutionHandler, processWaitTime: arguments.ProcessWaitTime, + enableEpochsHandler: arguments.EnableEpochsHandler, } if base.isInImportMode { diff --git a/process/sync/metablock_test.go b/process/sync/metablock_test.go index 8835041848c..f66cc89a36e 100644 --- a/process/sync/metablock_test.go +++ b/process/sync/metablock_test.go @@ -29,6 +29,7 @@ import ( "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/cache" "github.com/multiversx/mx-chain-go/testscommon/dblookupext" + "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/outport" stateMock "github.com/multiversx/mx-chain-go/testscommon/state" @@ -94,6 +95,7 @@ func CreateMetaBootstrapMockArguments() sync.ArgMetaBootstrapper { ScheduledTxsExecutionHandler: &testscommon.ScheduledTxsExecutionStub{}, ProcessWaitTime: testProcessWaitTime, RepopulateTokensSupplies: false, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, } argsMetaBootstrapper := sync.ArgMetaBootstrapper{ diff --git a/process/sync/shardblock.go b/process/sync/shardblock.go index 8cca3954ef0..0701e2bdffb 100644 --- a/process/sync/shardblock.go +++ b/process/sync/shardblock.go @@ -27,6 +27,9 @@ func NewShardBootstrap(arguments ArgShardBootstrapper) (*ShardBootstrap, error) if check.IfNil(arguments.PoolsHolder.Headers()) { return nil, process.ErrNilHeadersDataPool } + if check.IfNil(arguments.PoolsHolder.Proofs()) { + return nil, process.ErrNilProofsPool + } if check.IfNil(arguments.PoolsHolder.MiniBlocks()) { return nil, process.ErrNilTxBlockBody } @@ -41,6 +44,7 @@ func NewShardBootstrap(arguments ArgShardBootstrapper) (*ShardBootstrap, error) blockProcessor: arguments.BlockProcessor, store: arguments.Store, headers: arguments.PoolsHolder.Headers(), + proofs: arguments.PoolsHolder.Proofs(), roundHandler: arguments.RoundHandler, waitTime: arguments.WaitTime, hasher: arguments.Hasher, diff --git a/process/sync/shardblock_test.go b/process/sync/shardblock_test.go index b6d1d292174..f3d946c9255 100644 --- a/process/sync/shardblock_test.go +++ b/process/sync/shardblock_test.go @@ -34,6 +34,7 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/cache" dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/dblookupext" + "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/outport" stateMock "github.com/multiversx/mx-chain-go/testscommon/state" @@ -65,6 +66,9 @@ func createMockPools() *dataRetrieverMock.PoolsHolderStub { } return cs } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } return pools } @@ -221,6 +225,7 @@ func CreateShardBootstrapMockArguments() sync.ArgShardBootstrapper { ScheduledTxsExecutionHandler: &testscommon.ScheduledTxsExecutionStub{}, ProcessWaitTime: testProcessWaitTime, RepopulateTokensSupplies: false, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, } argsShardBootstrapper := sync.ArgShardBootstrapper{ @@ -500,6 +505,10 @@ func TestNewShardBootstrap_OkValsShouldWork(t *testing.T) { return cs } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } + args.PoolsHolder = pools args.IsInImportMode = true bs, err := sync.NewShardBootstrap(args) @@ -723,6 +732,10 @@ func TestBootstrap_SyncShouldSyncOneBlock(t *testing.T) { return cs } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } + args.PoolsHolder = pools forkDetector := &mock.ForkDetectorMock{} @@ -818,6 +831,9 @@ func TestBootstrap_ShouldReturnNilErr(t *testing.T) { return cs } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } args.PoolsHolder = pools forkDetector := &mock.ForkDetectorMock{} @@ -900,6 +916,9 @@ func TestBootstrap_SyncBlockShouldReturnErrorWhenProcessBlockFailed(t *testing.T return cs } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } args.PoolsHolder = pools forkDetector := &mock.ForkDetectorMock{} @@ -1882,6 +1901,9 @@ func TestShardBootstrap_RequestMiniBlocksFromHeaderWithNonceIfMissing(t *testing return cs } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } args.PoolsHolder = pools blkc := initBlockchain() @@ -2108,6 +2130,9 @@ func TestShardBootstrap_SyncBlockGetNodeDBErrorShouldSync(t *testing.T) { return cs } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } args.PoolsHolder = pools forkDetector := &mock.ForkDetectorMock{} @@ -2146,9 +2171,10 @@ func TestShardBootstrap_SyncBlockGetNodeDBErrorShouldSync(t *testing.T) { return []byte("roothash"), nil }} - bs, _ := sync.NewShardBootstrap(args) + bs, err := sync.NewShardBootstrap(args) + require.Nil(t, err) - err := bs.SyncBlock(context.Background()) + err = bs.SyncBlock(context.Background()) assert.Equal(t, errGetNodeFromDB, err) assert.True(t, syncCalled) } From 225945f3dd978a488ec677636145a136a0be67f4 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 4 Oct 2024 17:35:48 +0300 Subject: [PATCH 05/29] integrate proofs pool in interceptors factory --- factory/consensus/consensusComponents.go | 1 + integrationTests/testSyncNode.go | 1 + .../baseInterceptorsContainerFactory.go | 5 ++-- .../metaInterceptorsContainerFactory.go | 1 + .../metaInterceptorsContainerFactory_test.go | 8 +++-- .../shardInterceptorsContainerFactory.go | 3 ++ .../shardInterceptorsContainerFactory_test.go | 7 ++++- .../equivalentProofsInterceptorProcessor.go | 7 +++-- ...uivalentProofsInterceptorProcessor_test.go | 9 +++--- process/interceptors/processor/interface.go | 6 ++-- process/sync/shardblock.go | 1 + .../processMocks/equivalentProofsPoolMock.go | 29 ------------------- update/factory/fullSyncInterceptors.go | 2 ++ 13 files changed, 37 insertions(+), 43 deletions(-) delete mode 100644 testscommon/processMocks/equivalentProofsPoolMock.go diff --git a/factory/consensus/consensusComponents.go b/factory/consensus/consensusComponents.go index 8614abcf5e3..170638a7268 100644 --- a/factory/consensus/consensusComponents.go +++ b/factory/consensus/consensusComponents.go @@ -499,6 +499,7 @@ func (ccf *consensusComponentsFactory) createShardBootstrapper() (process.Bootst ScheduledTxsExecutionHandler: ccf.processComponents.ScheduledTxsExecutionHandler(), ProcessWaitTime: time.Duration(ccf.config.GeneralSettings.SyncProcessTimeInMillis) * time.Millisecond, RepopulateTokensSupplies: ccf.flagsConfig.RepopulateTokensSupplies, + EnableEpochsHandler: ccf.coreComponents.EnableEpochsHandler(), } argsShardBootstrapper := sync.ArgShardBootstrapper{ diff --git a/integrationTests/testSyncNode.go b/integrationTests/testSyncNode.go index e0b2753496e..31c2ac46111 100644 --- a/integrationTests/testSyncNode.go +++ b/integrationTests/testSyncNode.go @@ -176,6 +176,7 @@ func (tpn *TestProcessorNode) createShardBootstrapper() (TestBootstrapper, error ScheduledTxsExecutionHandler: &testscommon.ScheduledTxsExecutionStub{}, ProcessWaitTime: tpn.RoundHandler.TimeDuration(), RepopulateTokensSupplies: false, + EnableEpochsHandler: tpn.EnableEpochsHandler, } argsShardBootstrapper := sync.ArgShardBootstrapper{ diff --git a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go index aaccb8de44e..fe22361fadd 100644 --- a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go @@ -20,7 +20,6 @@ import ( "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/storage" - "github.com/multiversx/mx-chain-go/testscommon/processMocks" ) const ( @@ -406,6 +405,7 @@ func (bicf *baseInterceptorsContainerFactory) generateHeaderInterceptors() error argProcessor := &processor.ArgHdrInterceptorProcessor{ Headers: bicf.dataPool.Headers(), BlockBlackList: bicf.blockBlackList, + Proofs: bicf.dataPool.Proofs(), } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { @@ -536,6 +536,7 @@ func (bicf *baseInterceptorsContainerFactory) generateMetachainHeaderInterceptor argProcessor := &processor.ArgHdrInterceptorProcessor{ Headers: bicf.dataPool.Headers(), BlockBlackList: bicf.blockBlackList, + Proofs: bicf.dataPool.Proofs(), } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { @@ -845,7 +846,7 @@ func (bicf *baseInterceptorsContainerFactory) createOneShardEquivalentProofsInte marshaller := bicf.argInterceptorFactory.CoreComponents.InternalMarshalizer() argProcessor := processor.ArgEquivalentProofsInterceptorProcessor{ - EquivalentProofsPool: &processMocks.EquivalentProofsPoolMock{}, // TODO: pass the real implementation when is done + EquivalentProofsPool: bicf.dataPool.Proofs(), Marshaller: marshaller, } equivalentProofsProcessor, err := processor.NewEquivalentProofsInterceptorProcessor(argProcessor) diff --git a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go index 3fee1b05430..24791587e34 100644 --- a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go @@ -261,6 +261,7 @@ func (micf *metaInterceptorsContainerFactory) createOneShardHeaderInterceptor(to argProcessor := &processor.ArgHdrInterceptorProcessor{ Headers: micf.dataPool.Headers(), BlockBlackList: micf.blockBlackList, + Proofs: micf.dataPool.Proofs(), } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { diff --git a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go index c27d0607452..15d11cf7394 100644 --- a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go +++ b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory_test.go @@ -80,6 +80,9 @@ func createMetaDataPools() dataRetriever.PoolsHolder { RewardTransactionsCalled: func() dataRetriever.ShardedDataCacherNotifier { return testscommon.NewShardedDataStub() }, + ProofsCalled: func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + }, } return pools @@ -561,13 +564,14 @@ func TestMetaInterceptorsContainerFactory_CreateShouldWork(t *testing.T) { coreComp, cryptoComp := createMockComponentHolders() args := getArgumentsMeta(coreComp, cryptoComp) - icf, _ := interceptorscontainer.NewMetaInterceptorsContainerFactory(args) + icf, err := interceptorscontainer.NewMetaInterceptorsContainerFactory(args) + require.Nil(t, err) mainContainer, fullArchiveContainer, err := icf.Create() + require.Nil(t, err) assert.NotNil(t, mainContainer) assert.NotNil(t, fullArchiveContainer) - assert.Nil(t, err) } func TestMetaInterceptorsContainerFactory_With4ShardsShouldWork(t *testing.T) { diff --git a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go index c0f3551d472..e89b415b067 100644 --- a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go @@ -1,6 +1,8 @@ package interceptorscontainer import ( + "runtime/debug" + "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/core/throttler" @@ -197,6 +199,7 @@ func (sicf *shardInterceptorsContainerFactory) Create() (process.InterceptorsCon err = sicf.generateEquivalentProofsInterceptor() if err != nil { + debug.PrintStack() return nil, nil, err } diff --git a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go index 549f1fdc15a..3d091819c9f 100644 --- a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go +++ b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory_test.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/versioning" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" @@ -90,6 +91,10 @@ func createShardDataPools() dataRetriever.PoolsHolder { pools.CurrBlockTxsCalled = func() dataRetriever.TransactionCacher { return &mock.TxForCurrentBlockStub{} } + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + } + return pools } @@ -567,10 +572,10 @@ func TestShardInterceptorsContainerFactory_CreateShouldWork(t *testing.T) { icf, _ := interceptorscontainer.NewShardInterceptorsContainerFactory(args) mainContainer, fullArchiveContainer, err := icf.Create() + require.Nil(t, err) assert.NotNil(t, mainContainer) assert.NotNil(t, fullArchiveContainer) - assert.Nil(t, err) } func TestShardInterceptorsContainerFactory_With4ShardsShouldWork(t *testing.T) { diff --git a/process/interceptors/processor/equivalentProofsInterceptorProcessor.go b/process/interceptors/processor/equivalentProofsInterceptorProcessor.go index 8ce7f1c1e15..32ea66bf523 100644 --- a/process/interceptors/processor/equivalentProofsInterceptorProcessor.go +++ b/process/interceptors/processor/equivalentProofsInterceptorProcessor.go @@ -1,6 +1,8 @@ package processor import ( + "runtime/debug" + "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" @@ -34,6 +36,7 @@ func NewEquivalentProofsInterceptorProcessor(args ArgEquivalentProofsInterceptor func checkArgsEquivalentProofs(args ArgEquivalentProofsInterceptorProcessor) error { if check.IfNil(args.EquivalentProofsPool) { + debug.PrintStack() return process.ErrNilEquivalentProofsPool } if check.IfNil(args.Marshaller) { @@ -56,9 +59,7 @@ func (epip *equivalentProofsInterceptorProcessor) Save(data process.InterceptedD return process.ErrWrongTypeAssertion } - epip.equivalentProofsPool.AddNotarizedProof(interceptedProof.GetProof()) - - return nil + return epip.equivalentProofsPool.AddProof(interceptedProof.GetProof()) } // RegisterHandler registers a callback function to be notified of incoming equivalent proofs diff --git a/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go b/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go index 0f5bcbc0d9a..78f815a67b8 100644 --- a/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go +++ b/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go @@ -10,14 +10,14 @@ import ( "github.com/multiversx/mx-chain-go/process/block/interceptedBlocks" "github.com/multiversx/mx-chain-go/process/transaction" "github.com/multiversx/mx-chain-go/testscommon/consensus" + "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" - "github.com/multiversx/mx-chain-go/testscommon/processMocks" "github.com/stretchr/testify/require" ) func createMockArgEquivalentProofsInterceptorProcessor() ArgEquivalentProofsInterceptorProcessor { return ArgEquivalentProofsInterceptorProcessor{ - EquivalentProofsPool: &processMocks.EquivalentProofsPoolMock{}, + EquivalentProofsPool: &dataRetriever.ProofsPoolMock{}, Marshaller: &marshallerMock.MarshalizerMock{}, } } @@ -91,9 +91,10 @@ func TestEquivalentProofsInterceptorProcessor_Save(t *testing.T) { wasCalled := false args := createMockArgEquivalentProofsInterceptorProcessor() - args.EquivalentProofsPool = &processMocks.EquivalentProofsPoolMock{ - AddNotarizedProofCalled: func(notarizedProof data.HeaderProofHandler) { + args.EquivalentProofsPool = &dataRetriever.ProofsPoolMock{ + AddProofCalled: func(notarizedProof data.HeaderProofHandler) error { wasCalled = true + return nil }, } epip, err := NewEquivalentProofsInterceptorProcessor(args) diff --git a/process/interceptors/processor/interface.go b/process/interceptors/processor/interface.go index fc48ade3db4..14c0ae73bd6 100644 --- a/process/interceptors/processor/interface.go +++ b/process/interceptors/processor/interface.go @@ -33,7 +33,9 @@ type interceptedEquivalentProof interface { // EquivalentProofsPool defines the behaviour of a proofs pool components type EquivalentProofsPool interface { - AddNotarizedProof(headerProof data.HeaderProofHandler) - GetNotarizedProof(shardID uint32, headerHash []byte) (data.HeaderProofHandler, error) + AddProof(headerProof data.HeaderProofHandler) error + CleanupProofsBehindNonce(shardID uint32, nonce uint64) error + GetProof(shardID uint32, headerHash []byte) (data.HeaderProofHandler, error) + HasProof(shardID uint32, headerHash []byte) bool IsInterfaceNil() bool } diff --git a/process/sync/shardblock.go b/process/sync/shardblock.go index 0701e2bdffb..6a181e844a7 100644 --- a/process/sync/shardblock.go +++ b/process/sync/shardblock.go @@ -70,6 +70,7 @@ func NewShardBootstrap(arguments ArgShardBootstrapper) (*ShardBootstrap, error) scheduledTxsExecutionHandler: arguments.ScheduledTxsExecutionHandler, processWaitTime: arguments.ProcessWaitTime, repopulateTokensSupplies: arguments.RepopulateTokensSupplies, + enableEpochsHandler: arguments.EnableEpochsHandler, } if base.isInImportMode { diff --git a/testscommon/processMocks/equivalentProofsPoolMock.go b/testscommon/processMocks/equivalentProofsPoolMock.go deleted file mode 100644 index 9a2c73da584..00000000000 --- a/testscommon/processMocks/equivalentProofsPoolMock.go +++ /dev/null @@ -1,29 +0,0 @@ -package processMocks - -import "github.com/multiversx/mx-chain-core-go/data" - -// EquivalentProofsPoolMock - -type EquivalentProofsPoolMock struct { - AddNotarizedProofCalled func(headerProof data.HeaderProofHandler) - GetNotarizedProofCalled func(shardID uint32, headerHash []byte) (data.HeaderProofHandler, error) -} - -// AddNotarizedProof - -func (mock *EquivalentProofsPoolMock) AddNotarizedProof(headerProof data.HeaderProofHandler) { - if mock.AddNotarizedProofCalled != nil { - mock.AddNotarizedProofCalled(headerProof) - } -} - -// GetNotarizedProof - -func (mock *EquivalentProofsPoolMock) GetNotarizedProof(shardID uint32, headerHash []byte) (data.HeaderProofHandler, error) { - if mock.GetNotarizedProofCalled != nil { - return mock.GetNotarizedProofCalled(shardID, headerHash) - } - return nil, nil -} - -// IsInterfaceNil - -func (mock *EquivalentProofsPoolMock) IsInterfaceNil() bool { - return mock == nil -} diff --git a/update/factory/fullSyncInterceptors.go b/update/factory/fullSyncInterceptors.go index 0fe0298c4d6..95cc25f9449 100644 --- a/update/factory/fullSyncInterceptors.go +++ b/update/factory/fullSyncInterceptors.go @@ -343,6 +343,7 @@ func (ficf *fullSyncInterceptorsContainerFactory) createOneShardHeaderIntercepto argProcessor := &processor.ArgHdrInterceptorProcessor{ Headers: ficf.dataPool.Headers(), BlockBlackList: ficf.blockBlackList, + Proofs: ficf.dataPool.Proofs(), } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { @@ -727,6 +728,7 @@ func (ficf *fullSyncInterceptorsContainerFactory) generateMetachainHeaderInterce argProcessor := &processor.ArgHdrInterceptorProcessor{ Headers: ficf.dataPool.Headers(), BlockBlackList: ficf.blockBlackList, + Proofs: ficf.dataPool.Proofs(), } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { From c244eca2089155cd0a82b1b3ad824b94ceea1347 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 4 Oct 2024 18:32:45 +0300 Subject: [PATCH 06/29] fix epoch start bootstrap process tests --- epochStart/bootstrap/process_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/epochStart/bootstrap/process_test.go b/epochStart/bootstrap/process_test.go index 7baae9ecabf..e38737a7a3e 100644 --- a/epochStart/bootstrap/process_test.go +++ b/epochStart/bootstrap/process_test.go @@ -992,6 +992,9 @@ func TestCreateSyncers(t *testing.T) { HeartbeatsCalled: func() storage.Cacher { return cache.NewCacherStub() }, + ProofsCalled: func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + }, } epochStartProvider.whiteListHandler = &testscommon.WhiteListHandlerStub{} epochStartProvider.whiteListerVerifiedTxs = &testscommon.WhiteListHandlerStub{} @@ -2408,6 +2411,9 @@ func TestSyncSetGuardianTransaction(t *testing.T) { HeartbeatsCalled: func() storage.Cacher { return cache.NewCacherStub() }, + ProofsCalled: func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{} + }, } epochStartProvider.whiteListHandler = &testscommon.WhiteListHandlerStub{ IsWhiteListedCalled: func(interceptedData process.InterceptedData) bool { From d2598ff89b24ad56af791b32a9f1fed0a2b7e201 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Sat, 5 Oct 2024 22:32:54 +0300 Subject: [PATCH 07/29] refactor to use flag activation in epoch start meta block processor --- .../bootstrap/epochStartMetaBlockProcessor.go | 121 ++++++++++++------ .../epochStartMetaBlockProcessor_test.go | 15 +++ epochStart/bootstrap/process.go | 1 + 3 files changed, 101 insertions(+), 36 deletions(-) diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor.go b/epochStart/bootstrap/epochStartMetaBlockProcessor.go index a5b3845c5d1..ffc3b95edb0 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor.go @@ -12,6 +12,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/common" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/factory" @@ -26,10 +27,12 @@ const minNumConnectedPeers = 1 var _ process.InterceptorProcessor = (*epochStartMetaBlockProcessor)(nil) type epochStartMetaBlockProcessor struct { - messenger Messenger - requestHandler RequestHandler - marshalizer marshal.Marshalizer - hasher hashing.Hasher + messenger Messenger + requestHandler RequestHandler + marshalizer marshal.Marshalizer + hasher hashing.Hasher + enableEpochsHandler common.EnableEpochsHandler + mutReceivedMetaBlocks sync.RWMutex mapReceivedMetaBlocks map[string]data.MetaHeaderHandler mapMetaBlocksFromPeers map[string][]core.PeerID @@ -40,6 +43,7 @@ type epochStartMetaBlockProcessor struct { chanConsensusReached chan bool chanMetaBlockReached chan bool + chanConfMetaBlockReached chan bool metaBlock data.MetaHeaderHandler peerCountTarget int minNumConnectedPeers int @@ -55,6 +59,7 @@ func NewEpochStartMetaBlockProcessor( consensusPercentage uint8, minNumConnectedPeersConfig int, minNumOfPeersToConsiderBlockValidConfig int, + enableEpochsHandler common.EnableEpochsHandler, ) (*epochStartMetaBlockProcessor, error) { if check.IfNil(messenger) { return nil, epochStart.ErrNilMessenger @@ -77,6 +82,9 @@ func NewEpochStartMetaBlockProcessor( if minNumOfPeersToConsiderBlockValidConfig < minNumPeersToConsiderMetaBlockValid { return nil, epochStart.ErrNotEnoughNumOfPeersToConsiderBlockValid } + if check.IfNil(enableEpochsHandler) { + return nil, epochStart.ErrNilEnableEpochsHandler + } processor := &epochStartMetaBlockProcessor{ messenger: messenger, @@ -85,6 +93,7 @@ func NewEpochStartMetaBlockProcessor( hasher: hasher, minNumConnectedPeers: minNumConnectedPeersConfig, minNumOfPeersToConsiderBlockValid: minNumOfPeersToConsiderBlockValidConfig, + enableEpochsHandler: enableEpochsHandler, mutReceivedMetaBlocks: sync.RWMutex{}, mapReceivedMetaBlocks: make(map[string]data.MetaHeaderHandler), mapMetaBlocksFromPeers: make(map[string][]core.PeerID), @@ -92,6 +101,7 @@ func NewEpochStartMetaBlockProcessor( mapConfMetaBlocksFromPeers: make(map[string][]core.PeerID), chanConsensusReached: make(chan bool, 1), chanMetaBlockReached: make(chan bool, 1), + chanConfMetaBlockReached: make(chan bool, 1), } processor.waitForEnoughNumConnectedPeers(messenger) @@ -168,10 +178,15 @@ func (e *epochStartMetaBlockProcessor) Save(data process.InterceptedData, fromCo } log.Debug("received metablock is not of type epoch start", "error", epochStart.ErrNotEpochStartBlock) + return nil } func (e *epochStartMetaBlockProcessor) isEpochStartConfirmationBlock(metaBlock data.HeaderHandler) bool { + if !e.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, metaBlock.GetEpoch()) { + return false + } + startOfEpochMetaBlock, err := e.getMostReceivedMetaBlock() if err != nil { return false @@ -227,16 +242,11 @@ func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Contex return nil, err } - if check.IfNil(e.metaBlock) { - return nil, epochStart.ErrNilMetaBlock - } - - err = e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) + err = e.waitForConfMetaBlock(ctx) if err != nil { return nil, err } - chanRequests := time.After(durationBetweenReRequests) chanCheckMaps := time.After(durationBetweenChecks) for { @@ -245,12 +255,6 @@ func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Contex return e.metaBlock, nil case <-ctx.Done(): return e.getMostReceivedMetaBlock() - case <-chanRequests: - err = e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) - if err != nil { - return nil, err - } - chanRequests = time.After(durationBetweenReRequests) case <-chanCheckMaps: e.checkMaps() chanCheckMaps = time.After(durationBetweenChecks) @@ -286,6 +290,42 @@ func (e *epochStartMetaBlockProcessor) waitForMetaBlock(ctx context.Context) err } } +func (e *epochStartMetaBlockProcessor) waitForConfMetaBlock(ctx context.Context) error { + if check.IfNil(e.metaBlock) { + return epochStart.ErrNilMetaBlock + } + + if !e.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, e.metaBlock.GetEpoch()) { + return nil + } + + err := e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) + if err != nil { + return err + } + + chanRequests := time.After(durationBetweenReRequests) + chanCheckMaps := time.After(durationBetweenChecks) + + for { + select { + case <-e.chanConfMetaBlockReached: + return nil + case <-ctx.Done(): + return epochStart.ErrTimeoutWaitingForMetaBlock + case <-chanRequests: + err = e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) + if err != nil { + return err + } + chanRequests = time.After(durationBetweenReRequests) + case <-chanCheckMaps: + e.checkConfMetaBlockMaps() + chanCheckMaps = time.After(durationBetweenChecks) + } + } +} + func (e *epochStartMetaBlockProcessor) getMostReceivedMetaBlock() (data.MetaHeaderHandler, error) { e.mutReceivedMetaBlocks.RLock() defer e.mutReceivedMetaBlocks.RUnlock() @@ -334,45 +374,54 @@ func (e *epochStartMetaBlockProcessor) checkMetaBlockMaps() { e.mutReceivedMetaBlocks.RLock() defer e.mutReceivedMetaBlocks.RUnlock() - for hash, peersList := range e.mapMetaBlocksFromPeers { - log.Debug("metablock from peers", "num peers", len(peersList), "target", e.peerCountTarget, "hash", []byte(hash)) - metaBlockFound := e.processMetaBlockEntry(peersList, hash) - if metaBlockFound { - e.metaBlock = e.mapReceivedMetaBlocks[hash] - e.chanMetaBlockReached <- true - break - } + hash, metaBlockFound := e.checkReceivedMetaBlock(e.mapMetaBlocksFromPeers) + if metaBlockFound { + e.metaBlock = e.mapReceivedMetaBlocks[hash] + e.chanMetaBlockReached <- true + } +} + +func (e *epochStartMetaBlockProcessor) checkConfMetaBlockMaps() { + e.mutReceivedConfMetaBlocks.RLock() + defer e.mutReceivedConfMetaBlocks.RUnlock() + + _, confMetaBlockFound := e.checkReceivedMetaBlock(e.mapConfMetaBlocksFromPeers) + if confMetaBlockFound { + e.chanConfMetaBlockReached <- true } } func (e *epochStartMetaBlockProcessor) checkMaps() { e.mutReceivedMetaBlocks.RLock() - defer e.mutReceivedMetaBlocks.RUnlock() + _, metaBlockFound := e.checkReceivedMetaBlock(e.mapMetaBlocksFromPeers) + e.mutReceivedMetaBlocks.RUnlock() + + consensusReached := metaBlockFound + if e.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, e.metaBlock.GetEpoch()) { + e.mutReceivedConfMetaBlocks.RLock() + _, confMetaBlockFound := e.checkReceivedMetaBlock(e.mapConfMetaBlocksFromPeers) + e.mutReceivedConfMetaBlocks.RUnlock() - metaBlockFound := e.checkReceivedMetaBlock(e.mapMetaBlocksFromPeers) - confMetaBlockFound := e.checkReceivedMetaBlock(e.mapConfMetaBlocksFromPeers) + consensusReached = metaBlockFound && confMetaBlockFound + } - // no need to check proof here since it is check in interceptor - if metaBlockFound && confMetaBlockFound { + // no need to check proof here since it is checked in interceptor + if consensusReached { e.chanConsensusReached <- true } } -func (e *epochStartMetaBlockProcessor) checkReceivedMetaBlock(blocksFromPeers map[string][]core.PeerID) bool { +func (e *epochStartMetaBlockProcessor) checkReceivedMetaBlock(blocksFromPeers map[string][]core.PeerID) (string, bool) { for hash, peersList := range blocksFromPeers { log.Debug("metablock from peers", "num peers", len(peersList), "target", e.peerCountTarget, "hash", []byte(hash)) metaBlockFound := e.processMetaBlockEntry(peersList, hash) if metaBlockFound { - return true + return hash, true } } - return false -} - -func (e *epochStartMetaBlockProcessor) checkMetaBlockProof() bool { - return true + return "", false } func (e *epochStartMetaBlockProcessor) processMetaBlockEntry( diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go b/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go index 03ce113299b..ef0222c5817 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go @@ -12,6 +12,7 @@ import ( "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/epochStart/mock" "github.com/multiversx/mx-chain-go/testscommon" + "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/p2pmocks" "github.com/stretchr/testify/assert" @@ -28,6 +29,7 @@ func TestNewEpochStartMetaBlockProcessor_NilMessengerShouldErr(t *testing.T) { 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.Equal(t, epochStart.ErrNilMessenger, err) @@ -45,6 +47,7 @@ func TestNewEpochStartMetaBlockProcessor_NilRequestHandlerShouldErr(t *testing.T 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.Equal(t, epochStart.ErrNilRequestHandler, err) @@ -62,6 +65,7 @@ func TestNewEpochStartMetaBlockProcessor_NilMarshalizerShouldErr(t *testing.T) { 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.Equal(t, epochStart.ErrNilMarshalizer, err) @@ -79,6 +83,7 @@ func TestNewEpochStartMetaBlockProcessor_NilHasherShouldErr(t *testing.T) { 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.Equal(t, epochStart.ErrNilHasher, err) @@ -96,6 +101,7 @@ func TestNewEpochStartMetaBlockProcessor_InvalidConsensusPercentageShouldErr(t * 101, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.Equal(t, epochStart.ErrInvalidConsensusThreshold, err) @@ -116,6 +122,7 @@ func TestNewEpochStartMetaBlockProcessorOkValsShouldWork(t *testing.T) { 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.NoError(t, err) @@ -152,6 +159,7 @@ func TestNewEpochStartMetaBlockProcessorOkValsShouldWorkAfterMoreTriesWaitingFor 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.NoError(t, err) @@ -172,6 +180,7 @@ func TestEpochStartMetaBlockProcessor_Validate(t *testing.T) { 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.Nil(t, esmbp.Validate(nil, "")) @@ -191,6 +200,7 @@ func TestEpochStartMetaBlockProcessor_SaveNilInterceptedDataShouldNotReturnError 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) err := esmbp.Save(nil, "peer0", "") @@ -212,6 +222,7 @@ func TestEpochStartMetaBlockProcessor_SaveOkInterceptedDataShouldWork(t *testing 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) assert.Zero(t, len(esmbp.GetMapMetaBlock())) @@ -241,6 +252,7 @@ func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldTimeOut(t *tes 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) @@ -265,6 +277,7 @@ func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldReturnMostRece 99, 3, 5, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) expectedMetaBlock := &block.MetaBlock{ @@ -309,6 +322,7 @@ func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldWorkFromFirstT 50, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) expectedMetaBlock := &block.MetaBlock{ @@ -361,6 +375,7 @@ func testEpochStartMbIsReceivedWithSleepBetweenReceivedMessages(t *testing.T, tt 64, 3, 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, ) expectedMetaBlock := &block.MetaBlock{ Nonce: 10, diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 995a6e189b6..a2935721d38 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -556,6 +556,7 @@ func (e *epochStartBootstrap) prepareComponentsToSyncFromNetwork() error { thresholdForConsideringMetaBlockCorrect, epochStartConfig.MinNumConnectedPeersToStart, epochStartConfig.MinNumOfPeersToConsiderBlockValid, + e.enableEpochsHandler, ) if err != nil { return err From d4886f47dfd240bc12fcc493056bf9f9260df4c4 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Sat, 5 Oct 2024 22:36:55 +0300 Subject: [PATCH 08/29] add todo for meta block sync duplicated code --- epochStart/bootstrap/epochStartMetaBlockProcessor.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor.go b/epochStart/bootstrap/epochStartMetaBlockProcessor.go index ffc3b95edb0..b446e1d8a95 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor.go @@ -37,6 +37,8 @@ type epochStartMetaBlockProcessor struct { mapReceivedMetaBlocks map[string]data.MetaHeaderHandler mapMetaBlocksFromPeers map[string][]core.PeerID + // TODO: refactor to use a separate component for meta block sync handling + // for epoch start metablock and epoch start confirmation block mutReceivedConfMetaBlocks sync.RWMutex mapReceivedConfMetaBlocks map[string]data.MetaHeaderHandler mapConfMetaBlocksFromPeers map[string][]core.PeerID From 58eeb1eb3e27726d3c16601b7bd73478c437fad1 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 7 Oct 2024 09:32:07 +0300 Subject: [PATCH 09/29] unit tests for flow with equivalent proofs --- .../epochStartMetaBlockProcessor_test.go | 53 ++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go b/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go index ef0222c5817..200c3f408a3 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor_test.go @@ -9,6 +9,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/data/block" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/epochStart/mock" "github.com/multiversx/mx-chain-go/testscommon" @@ -350,19 +351,53 @@ func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldWorkFromFirstT assert.Equal(t, expectedMetaBlock, mb) } -func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldWorkAfterMultipleTries(t *testing.T) { +func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlock_BeforeEquivalentMessages(t *testing.T) { t.Parallel() - testEpochStartMbIsReceivedWithSleepBetweenReceivedMessages(t, durationBetweenChecks-10*time.Millisecond) + tts := durationBetweenChecks - 10*time.Millisecond + + esmbp, _ := NewEpochStartMetaBlockProcessor( + &p2pmocks.MessengerStub{ + ConnectedPeersCalled: func() []core.PeerID { + return []core.PeerID{"peer_0", "peer_1", "peer_2", "peer_3", "peer_4", "peer_5"} + }, + }, + &testscommon.RequestHandlerStub{}, + &mock.MarshalizerMock{}, + &hashingMocks.HasherMock{}, + 64, + 3, + 3, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + ) + expectedMetaBlock := &block.MetaBlock{ + Nonce: 10, + EpochStart: block.EpochStart{LastFinalizedHeaders: []block.EpochStartShardData{{Round: 1}}}, + } + intData := mock.NewInterceptedMetaBlockMock(expectedMetaBlock, []byte("hash")) + + go func() { + index := 0 + for { + time.Sleep(tts) + _ = esmbp.Save(intData, core.PeerID(fmt.Sprintf("peer_%d", index)), "") + _ = esmbp.Save(intData, core.PeerID(fmt.Sprintf("peer_%d", index+1)), "") + index += 2 + } + }() + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + mb, err := esmbp.GetEpochStartMetaBlock(ctx) + cancel() + assert.NoError(t, err) + assert.Equal(t, expectedMetaBlock, mb) } -func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlockShouldWorkAfterMultipleRequests(t *testing.T) { +func TestEpochStartMetaBlockProcessor_GetEpochStartMetaBlock_AfterEquivalentMessages(t *testing.T) { t.Parallel() - testEpochStartMbIsReceivedWithSleepBetweenReceivedMessages(t, durationBetweenChecks-10*time.Millisecond) -} + tts := durationBetweenChecks - 10*time.Millisecond -func testEpochStartMbIsReceivedWithSleepBetweenReceivedMessages(t *testing.T, tts time.Duration) { esmbp, _ := NewEpochStartMetaBlockProcessor( &p2pmocks.MessengerStub{ ConnectedPeersCalled: func() []core.PeerID { @@ -375,7 +410,11 @@ func testEpochStartMbIsReceivedWithSleepBetweenReceivedMessages(t *testing.T, tt 64, 3, 3, - &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.EquivalentMessagesFlag + }, + }, ) expectedMetaBlock := &block.MetaBlock{ Nonce: 10, From 3813ce89e8f09cfc1de7426ddc6cc8084fc04387 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 7 Oct 2024 09:32:37 +0300 Subject: [PATCH 10/29] process block only if there is a proof --- process/sync/baseSync.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index 203418f0e7e..f3aca1de7f6 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -640,15 +640,16 @@ func (boot *baseBootstrap) syncBlock() error { return err } + go boot.requestHeadersFromNonceIfMissing(header.GetNonce() + 1) + if boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { - err = boot.proofs.AddProof(header.GetPreviousProof()) - if err != nil { - log.Warn("failed to add proof to pool", "header nonce", header.GetNonce()) + // process block only if there is a proof for it + hasProof := boot.proofs.HasProof(header.GetShardID(), header.GetPrevHash()) + if !hasProof { + return fmt.Errorf("process sync: did not have proof for header") } } - go boot.requestHeadersFromNonceIfMissing(header.GetNonce() + 1) - body, err = boot.blockBootstrapper.getBlockBodyRequestingIfMissing(header) if err != nil { return err From ed9fbba78f8c6c9c2fce2aa40299e4414ec2893a Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 14 Oct 2024 10:30:57 +0300 Subject: [PATCH 11/29] fix comment --- epochStart/bootstrap/process.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index a2935721d38..91d40db1a8d 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -678,7 +678,7 @@ func (e *epochStartBootstrap) syncHeadersFrom(meta data.MetaHeaderHandler) (map[ return syncedHeaders, nil } -// Bootstrap will handle requesting and receiving the needed information the node will bootstrap from +// requestAndProcessing will handle requesting and receiving the needed information the node will bootstrap from func (e *epochStartBootstrap) requestAndProcessing() (Parameters, error) { var err error e.baseData.numberOfShards = uint32(len(e.epochStartMeta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers())) From 4b03649e8692499c5a47026f69f473c74f0a1ce2 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 21 Oct 2024 17:26:00 +0300 Subject: [PATCH 12/29] add log trace check on display --- process/peer/process.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/process/peer/process.go b/process/peer/process.go index ccbd46dda83..3e7bb30b8ac 100644 --- a/process/peer/process.go +++ b/process/peer/process.go @@ -1175,6 +1175,11 @@ func (vs *validatorStatistics) getTempRating(s string) uint32 { } func (vs *validatorStatistics) display(validatorKey string) { + if log.GetLevel() != logger.LogTrace { + // do not need to load peer account if not log level trace + return + } + peerAcc, err := vs.loadPeerAccount([]byte(validatorKey)) if err != nil { log.Trace("display peer acc", "error", err) From 80f1ca340238e01becdf438e5ee45417ac7409d7 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 21 Oct 2024 21:02:44 +0300 Subject: [PATCH 13/29] remove debug prints --- .../interceptorscontainer/shardInterceptorsContainerFactory.go | 3 --- .../processor/equivalentProofsInterceptorProcessor.go | 3 --- 2 files changed, 6 deletions(-) diff --git a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go index 5a70349ca33..7acd6d87e59 100644 --- a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go @@ -1,8 +1,6 @@ package interceptorscontainer import ( - "runtime/debug" - "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/core/throttler" @@ -205,7 +203,6 @@ func (sicf *shardInterceptorsContainerFactory) Create() (process.InterceptorsCon err = sicf.generateEquivalentProofsInterceptor() if err != nil { - debug.PrintStack() return nil, nil, err } diff --git a/process/interceptors/processor/equivalentProofsInterceptorProcessor.go b/process/interceptors/processor/equivalentProofsInterceptorProcessor.go index 32ea66bf523..0f66cbc3100 100644 --- a/process/interceptors/processor/equivalentProofsInterceptorProcessor.go +++ b/process/interceptors/processor/equivalentProofsInterceptorProcessor.go @@ -1,8 +1,6 @@ package processor import ( - "runtime/debug" - "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" @@ -36,7 +34,6 @@ func NewEquivalentProofsInterceptorProcessor(args ArgEquivalentProofsInterceptor func checkArgsEquivalentProofs(args ArgEquivalentProofsInterceptorProcessor) error { if check.IfNil(args.EquivalentProofsPool) { - debug.PrintStack() return process.ErrNilEquivalentProofsPool } if check.IfNil(args.Marshaller) { From 12d156aecaeeb9a57dc94dd6357b17b08d0b2c0e Mon Sep 17 00:00:00 2001 From: ssd04 Date: Thu, 24 Oct 2024 21:59:47 +0300 Subject: [PATCH 14/29] add proofs pool subscribers --- .../dataPool/proofsCache/proofsPool.go | 32 +++++++++++++++++-- .../dataPool/proofsCache/proofsPool_test.go | 29 ++++++++++++++++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/dataRetriever/dataPool/proofsCache/proofsPool.go b/dataRetriever/dataPool/proofsCache/proofsPool.go index b0de8e005cd..936c17dfbe0 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool.go @@ -13,12 +13,16 @@ var log = logger.GetOrCreate("dataRetriever/proofscache") type proofsPool struct { mutCache sync.RWMutex cache map[uint32]*proofsCache + + mutAddedProofHandlers sync.RWMutex + addedProofHandlers []func(headerProof data.HeaderProofHandler) } // NewProofsPool creates a new proofs pool component func NewProofsPool() *proofsPool { return &proofsPool{ - cache: make(map[uint32]*proofsCache), + cache: make(map[uint32]*proofsCache), + addedProofHandlers: make([]func(headerProof data.HeaderProofHandler), 0), } } @@ -35,8 +39,7 @@ func (pp *proofsPool) AddProof( hasProof := pp.HasProof(shardID, headerHash) if hasProof { - log.Trace("there was already a valid proof for header, headerHash: %s", headerHash) - return nil + return fmt.Errorf("there was already a valid proof for header, headerHash: %s", headerHash) } pp.mutCache.Lock() @@ -58,9 +61,20 @@ func (pp *proofsPool) AddProof( proofsPerShard.addProof(headerProof) + pp.callAddedProofHandlers(headerProof) + return nil } +func (pp *proofsPool) callAddedProofHandlers(headerProof data.HeaderProofHandler) { + pp.mutAddedProofHandlers.RLock() + defer pp.mutAddedProofHandlers.RUnlock() + + for _, handler := range pp.addedProofHandlers { + go handler(headerProof) + } +} + // CleanupProofsBehindNonce will cleanup proofs from pool based on nonce func (pp *proofsPool) CleanupProofsBehindNonce(shardID uint32, nonce uint64) error { if nonce == 0 { @@ -119,6 +133,18 @@ func (pp *proofsPool) HasProof( return err == nil } +// RegisterHandler registers a new handler to be called when a new data is added +func (pp *proofsPool) RegisterHandler(handler func(headerProof data.HeaderProofHandler)) { + if handler == nil { + log.Error("attempt to register a nil handler to proofs pool") + return + } + + pp.mutAddedProofHandlers.Lock() + pp.addedProofHandlers = append(pp.addedProofHandlers, handler) + pp.mutAddedProofHandlers.Unlock() +} + // IsInterfaceNil returns true if there is no value under the interface func (pp *proofsPool) IsInterfaceNil() bool { return pp == nil diff --git a/dataRetriever/dataPool/proofsCache/proofsPool_test.go b/dataRetriever/dataPool/proofsCache/proofsPool_test.go index cbdcb63a19a..517957360bd 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool_test.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool_test.go @@ -8,6 +8,7 @@ import ( "sync/atomic" "testing" + "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" proofscache "github.com/multiversx/mx-chain-go/dataRetriever/dataPool/proofsCache" "github.com/stretchr/testify/assert" @@ -81,6 +82,28 @@ func TestProofsPool_ShouldWork(t *testing.T) { require.Equal(t, proof4, proof) } +func TestProofsPool_RegisterHandler(t *testing.T) { + t.Parallel() + + pp := proofscache.NewProofsPool() + + wasCalled := false + wg := sync.WaitGroup{} + wg.Add(1) + handler := func(proof data.HeaderProofHandler) { + wasCalled = true + wg.Done() + } + pp.RegisterHandler(nil) + pp.RegisterHandler(handler) + + pp.AddProof(generateProof()) + + wg.Wait() + + assert.True(t, wasCalled) +} + func TestProofsPool_Concurrency(t *testing.T) { t.Parallel() @@ -95,7 +118,7 @@ func TestProofsPool_Concurrency(t *testing.T) { for i := 0; i < numOperations; i++ { go func(idx int) { - switch idx % 5 { + switch idx % 6 { case 0, 1, 2: _ = pp.AddProof(generateProof()) case 3: @@ -105,6 +128,10 @@ func TestProofsPool_Concurrency(t *testing.T) { } case 4: _ = pp.CleanupProofsBehindNonce(generateRandomShardID(), generateRandomNonce()) + case 5: + handler := func(proof data.HeaderProofHandler) { + } + pp.RegisterHandler(handler) default: assert.Fail(t, "should have not beed called") } From 176e9a9549c72f6de817d4c599bc2725787f1970 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Thu, 24 Oct 2024 22:53:23 +0300 Subject: [PATCH 15/29] fix linter issue --- dataRetriever/dataPool/proofsCache/proofsPool_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dataRetriever/dataPool/proofsCache/proofsPool_test.go b/dataRetriever/dataPool/proofsCache/proofsPool_test.go index 517957360bd..b2e4ffdcecc 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool_test.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool_test.go @@ -97,7 +97,7 @@ func TestProofsPool_RegisterHandler(t *testing.T) { pp.RegisterHandler(nil) pp.RegisterHandler(handler) - pp.AddProof(generateProof()) + _ = pp.AddProof(generateProof()) wg.Wait() From fd736e6af7828eb991d29dec869ba71cd0f225d7 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Thu, 24 Oct 2024 23:00:05 +0300 Subject: [PATCH 16/29] added nil check unit tests --- .../processor/hdrInterceptorProcessor_test.go | 11 +++++++++++ process/sync/metablock_test.go | 16 ++++++++++++++++ process/sync/shardblock_test.go | 16 ++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/process/interceptors/processor/hdrInterceptorProcessor_test.go b/process/interceptors/processor/hdrInterceptorProcessor_test.go index c856d2d5c4b..b1e28b56769 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor_test.go +++ b/process/interceptors/processor/hdrInterceptorProcessor_test.go @@ -57,6 +57,17 @@ func TestNewHdrInterceptorProcessor_NilBlackListHandlerShouldErr(t *testing.T) { assert.Equal(t, process.ErrNilBlackListCacher, err) } +func TestNewHdrInterceptorProcessor_NilProofsPoolShouldErr(t *testing.T) { + t.Parallel() + + arg := createMockHdrArgument() + arg.Proofs = nil + hip, err := processor.NewHdrInterceptorProcessor(arg) + + assert.Nil(t, hip) + assert.Equal(t, process.ErrNilEquivalentProofsPool, err) +} + func TestNewHdrInterceptorProcessor_ShouldWork(t *testing.T) { t.Parallel() diff --git a/process/sync/metablock_test.go b/process/sync/metablock_test.go index f66cc89a36e..9329634d032 100644 --- a/process/sync/metablock_test.go +++ b/process/sync/metablock_test.go @@ -174,6 +174,22 @@ func TestNewMetaBootstrap_PoolsHolderRetNilOnHeadersShouldErr(t *testing.T) { assert.Equal(t, process.ErrNilMetaBlocksPool, err) } +func TestNewMetaBootstrap_NilProofsPool(t *testing.T) { + t.Parallel() + + args := CreateMetaBootstrapMockArguments() + pools := createMockPools() + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return nil + } + args.PoolsHolder = pools + + bs, err := sync.NewMetaBootstrap(args) + + assert.True(t, check.IfNil(bs)) + assert.Equal(t, process.ErrNilProofsPool, err) +} + func TestNewMetaBootstrap_NilStoreShouldErr(t *testing.T) { t.Parallel() diff --git a/process/sync/shardblock_test.go b/process/sync/shardblock_test.go index f3d946c9255..339fbb0db36 100644 --- a/process/sync/shardblock_test.go +++ b/process/sync/shardblock_test.go @@ -277,6 +277,22 @@ func TestNewShardBootstrap_PoolsHolderRetNilOnHeadersShouldErr(t *testing.T) { assert.Equal(t, process.ErrNilHeadersDataPool, err) } +func TestNewShardBootstrap_NilProofsPool(t *testing.T) { + t.Parallel() + + args := CreateShardBootstrapMockArguments() + pools := createMockPools() + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return nil + } + args.PoolsHolder = pools + + bs, err := sync.NewShardBootstrap(args) + + assert.True(t, check.IfNil(bs)) + assert.Equal(t, process.ErrNilProofsPool, err) +} + func TestNewShardBootstrap_PoolsHolderRetNilOnTxBlockBodyShouldErr(t *testing.T) { t.Parallel() From 20ea2ff0f5950f42e579992ffcee7fa289b87bdb Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 22 Nov 2024 12:49:46 +0200 Subject: [PATCH 17/29] handle equivalent proof separatelly --- .../dataPool/proofsCache/proofsPool.go | 3 +- .../processor/hdrInterceptorProcessor.go | 8 ++- process/sync/baseSync.go | 62 ++++++++++++++++--- process/sync/interface.go | 2 +- process/sync/metablock.go | 12 ++-- process/sync/shardblock.go | 12 ++-- 6 files changed, 75 insertions(+), 24 deletions(-) diff --git a/dataRetriever/dataPool/proofsCache/proofsPool.go b/dataRetriever/dataPool/proofsCache/proofsPool.go index 936c17dfbe0..f519788e630 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool.go @@ -1,6 +1,7 @@ package proofscache import ( + "encoding/hex" "fmt" "sync" @@ -39,7 +40,7 @@ func (pp *proofsPool) AddProof( hasProof := pp.HasProof(shardID, headerHash) if hasProof { - return fmt.Errorf("there was already a valid proof for header, headerHash: %s", headerHash) + return fmt.Errorf("there was already a valid proof for header, headerHash: %s", hex.EncodeToString(headerHash)) } pp.mutCache.Lock() diff --git a/process/interceptors/processor/hdrInterceptorProcessor.go b/process/interceptors/processor/hdrInterceptorProcessor.go index d87c49bead2..d3639cba18b 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor.go +++ b/process/interceptors/processor/hdrInterceptorProcessor.go @@ -73,7 +73,13 @@ func (hip *HdrInterceptorProcessor) Save(data process.InterceptedData, _ core.Pe hip.headers.AddHeader(interceptedHdr.Hash(), interceptedHdr.HeaderHandler()) - _ = hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) + // TODO: check for equivalent flag + err := hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) + if err != nil { + log.Error("failed to add proof", "error", err, "headerHash", interceptedHdr.Hash()) + } else { + log.Debug("HdrInterceptorProcessor: added proof", "headerHash", interceptedHdr.HeaderHandler().GetPreviousProof().GetHeaderHash()) + } return nil } diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index f3aca1de7f6..460202285e7 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -3,6 +3,7 @@ package sync import ( "bytes" "context" + "encoding/hex" "fmt" "math" "sync" @@ -635,19 +636,16 @@ func (boot *baseBootstrap) syncBlock() error { } }() - header, err = boot.getNextHeaderRequestingIfMissing() + header, headerHash, err := boot.getNextHeaderRequestingIfMissing() if err != nil { return err } go boot.requestHeadersFromNonceIfMissing(header.GetNonce() + 1) - if boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { - // process block only if there is a proof for it - hasProof := boot.proofs.HasProof(header.GetShardID(), header.GetPrevHash()) - if !hasProof { - return fmt.Errorf("process sync: did not have proof for header") - } + err = boot.handleEquivalentProof(header, headerHash) + if err != nil { + return err } body, err = boot.blockBootstrapper.getBlockBodyRequestingIfMissing(header) @@ -705,6 +703,51 @@ func (boot *baseBootstrap) syncBlock() error { return nil } +func (boot *baseBootstrap) handleEquivalentProof( + header data.HeaderHandler, + headerHash []byte, +) error { + if header.GetNonce() == 1 { + return nil + } + + if !boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { + return nil + } + + prevHeader, err := boot.blockBootstrapper.getHeaderWithHashRequestingIfMissing(header.GetPrevHash()) + if err != nil { + return err + } + + if !boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, prevHeader.GetEpoch()) { + // no need to check proof for first block + log.Info("no need to check first activation blockk") + return nil + } + // process block only if there is a proof for it + hasProof := boot.proofs.HasProof(header.GetShardID(), headerHash) + if hasProof { + log.Error("F HAS proof for header", "headerHash", headerHash) + return nil + } + + log.Error("process sync: did not have proof for header, will try again", "headerHash", headerHash) + + // wait also for next header + _, _, err = boot.blockBootstrapper.getHeaderWithNonceRequestingIfMissing(header.GetNonce() + 1) + if err != nil { + return err + } + + hasProof = boot.proofs.HasProof(header.GetShardID(), headerHash) + if !hasProof { + return fmt.Errorf("process sync: did not have proof for header, headerHash %s", hex.EncodeToString(headerHash)) + } + + return nil +} + func (boot *baseBootstrap) handleTrieSyncError(err error, ctx context.Context) { shouldOutputLog := err != nil && !common.IsContextDone(ctx) if shouldOutputLog { @@ -965,7 +1008,7 @@ func (boot *baseBootstrap) getRootHashFromBlock(hdr data.HeaderHandler, hdrHash return hdrRootHash } -func (boot *baseBootstrap) getNextHeaderRequestingIfMissing() (data.HeaderHandler, error) { +func (boot *baseBootstrap) getNextHeaderRequestingIfMissing() (data.HeaderHandler, []byte, error) { nonce := boot.getNonceForNextBlock() boot.setRequestedHeaderHash(nil) @@ -977,7 +1020,8 @@ func (boot *baseBootstrap) getNextHeaderRequestingIfMissing() (data.HeaderHandle } if hash != nil { - return boot.blockBootstrapper.getHeaderWithHashRequestingIfMissing(hash) + header, err := boot.blockBootstrapper.getHeaderWithHashRequestingIfMissing(hash) + return header, hash, err } return boot.blockBootstrapper.getHeaderWithNonceRequestingIfMissing(nonce) diff --git a/process/sync/interface.go b/process/sync/interface.go index 88f644df160..d672cafb88b 100644 --- a/process/sync/interface.go +++ b/process/sync/interface.go @@ -13,7 +13,7 @@ type blockBootstrapper interface { getPrevHeader(data.HeaderHandler, storage.Storer) (data.HeaderHandler, error) getBlockBody(headerHandler data.HeaderHandler) (data.BodyHandler, error) getHeaderWithHashRequestingIfMissing(hash []byte) (data.HeaderHandler, error) - getHeaderWithNonceRequestingIfMissing(nonce uint64) (data.HeaderHandler, error) + getHeaderWithNonceRequestingIfMissing(nonce uint64) (data.HeaderHandler, []byte, error) haveHeaderInPoolWithNonce(nonce uint64) bool getBlockBodyRequestingIfMissing(headerHandler data.HeaderHandler) (data.BodyHandler, error) isForkTriggeredByMeta() bool diff --git a/process/sync/metablock.go b/process/sync/metablock.go index aeec4d46ead..72fc8a8688b 100644 --- a/process/sync/metablock.go +++ b/process/sync/metablock.go @@ -248,8 +248,8 @@ func (boot *MetaBootstrap) requestHeaderWithHash(hash []byte) { // getHeaderWithNonceRequestingIfMissing method gets the header with a given nonce from pool. If it is not found there, it will // be requested from network -func (boot *MetaBootstrap) getHeaderWithNonceRequestingIfMissing(nonce uint64) (data.HeaderHandler, error) { - hdr, _, err := process.GetMetaHeaderFromPoolWithNonce( +func (boot *MetaBootstrap) getHeaderWithNonceRequestingIfMissing(nonce uint64) (data.HeaderHandler, []byte, error) { + hdr, hash, err := process.GetMetaHeaderFromPoolWithNonce( nonce, boot.headers) if err != nil { @@ -257,18 +257,18 @@ func (boot *MetaBootstrap) getHeaderWithNonceRequestingIfMissing(nonce uint64) ( boot.requestHeaderWithNonce(nonce) err = boot.waitForHeaderNonce() if err != nil { - return nil, err + return nil, nil, err } - hdr, _, err = process.GetMetaHeaderFromPoolWithNonce( + hdr, hash, err = process.GetMetaHeaderFromPoolWithNonce( nonce, boot.headers) if err != nil { - return nil, err + return nil, nil, err } } - return hdr, nil + return hdr, hash, nil } // getHeaderWithHashRequestingIfMissing method gets the header with a given hash from pool. If it is not found there, diff --git a/process/sync/shardblock.go b/process/sync/shardblock.go index 6a181e844a7..10a3492d024 100644 --- a/process/sync/shardblock.go +++ b/process/sync/shardblock.go @@ -201,8 +201,8 @@ func (boot *ShardBootstrap) requestHeaderWithHash(hash []byte) { // getHeaderWithNonceRequestingIfMissing method gets the header with a given nonce from pool. If it is not found there, it will // be requested from network -func (boot *ShardBootstrap) getHeaderWithNonceRequestingIfMissing(nonce uint64) (data.HeaderHandler, error) { - hdr, _, err := process.GetShardHeaderFromPoolWithNonce( +func (boot *ShardBootstrap) getHeaderWithNonceRequestingIfMissing(nonce uint64) (data.HeaderHandler, []byte, error) { + hdr, hash, err := process.GetShardHeaderFromPoolWithNonce( nonce, boot.shardCoordinator.SelfId(), boot.headers) @@ -211,19 +211,19 @@ func (boot *ShardBootstrap) getHeaderWithNonceRequestingIfMissing(nonce uint64) boot.requestHeaderWithNonce(nonce) err = boot.waitForHeaderNonce() if err != nil { - return nil, err + return nil, nil, err } - hdr, _, err = process.GetShardHeaderFromPoolWithNonce( + hdr, hash, err = process.GetShardHeaderFromPoolWithNonce( nonce, boot.shardCoordinator.SelfId(), boot.headers) if err != nil { - return nil, err + return nil, nil, err } } - return hdr, nil + return hdr, hash, nil } // getHeaderWithHashRequestingIfMissing method gets the header with a given hash from pool. If it is not found there, From ba15d49066a63fe226d5d1be0ea2e13856e8ad7c Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 22 Nov 2024 12:50:13 +0200 Subject: [PATCH 18/29] integration test for sync with equivalent proofs --- .../sync/basicSync/basicSync_test.go | 77 +++++++++++++++++++ integrationTests/testProcessorNode.go | 20 ++++- testscommon/dataRetriever/poolFactory.go | 26 ++++++- 3 files changed, 120 insertions(+), 3 deletions(-) diff --git a/integrationTests/sync/basicSync/basicSync_test.go b/integrationTests/sync/basicSync/basicSync_test.go index ebdd4a2599d..3a2e0b0ae15 100644 --- a/integrationTests/sync/basicSync/basicSync_test.go +++ b/integrationTests/sync/basicSync/basicSync_test.go @@ -198,3 +198,80 @@ func testAllNodesHaveSameLastBlock(t *testing.T, nodes []*integrationTests.TestP assert.Equal(t, 1, len(mapBlocksByHash)) } + +func TestSyncWorksInShard_EmptyBlocksNoForks_With_EquivalentProofs(t *testing.T) { + if testing.Short() { + t.Skip("this is not a short test") + } + + logger.SetLogLevel("*:DEBUG") + + maxShards := uint32(1) + shardId := uint32(0) + numNodesPerShard := 3 + + enableEpochs := integrationTests.CreateEnableEpochsConfig() + enableEpochs.EquivalentMessagesEnableEpoch = uint32(0) + + nodes := make([]*integrationTests.TestProcessorNode, numNodesPerShard+1) + connectableNodes := make([]integrationTests.Connectable, 0) + for i := 0; i < numNodesPerShard; i++ { + nodes[i] = integrationTests.NewTestProcessorNode(integrationTests.ArgTestProcessorNode{ + MaxShards: maxShards, + NodeShardId: shardId, + TxSignPrivKeyShardId: shardId, + WithSync: true, + EpochsConfig: &enableEpochs, + }) + connectableNodes = append(connectableNodes, nodes[i]) + } + + metachainNode := integrationTests.NewTestProcessorNode(integrationTests.ArgTestProcessorNode{ + MaxShards: maxShards, + NodeShardId: core.MetachainShardId, + TxSignPrivKeyShardId: shardId, + WithSync: true, + }) + idxProposerMeta := numNodesPerShard + nodes[idxProposerMeta] = metachainNode + connectableNodes = append(connectableNodes, metachainNode) + + idxProposerShard0 := 0 + leaders := []*integrationTests.TestProcessorNode{nodes[idxProposerShard0], nodes[idxProposerMeta]} + + integrationTests.ConnectNodes(connectableNodes) + + defer func() { + for _, n := range nodes { + n.Close() + } + }() + + for _, n := range nodes { + _ = n.StartSync() + } + + fmt.Println("Delaying for nodes p2p bootstrap...") + time.Sleep(integrationTests.P2pBootstrapDelay) + + round := uint64(0) + nonce := uint64(0) + round = integrationTests.IncrementAndPrintRound(round) + integrationTests.UpdateRound(nodes, round) + nonce++ + + numRoundsToTest := 5 + for i := 0; i < numRoundsToTest; i++ { + integrationTests.ProposeBlock(nodes, leaders, round, nonce) + + time.Sleep(integrationTests.SyncDelay) + + round = integrationTests.IncrementAndPrintRound(round) + integrationTests.UpdateRound(nodes, round) + nonce++ + } + + time.Sleep(integrationTests.SyncDelay) + + testAllNodesHaveTheSameBlockHeightInBlockchain(t, nodes) +} diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index ca97602217e..651e5b6a068 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -46,6 +46,7 @@ import ( "github.com/multiversx/mx-chain-go/consensus/spos/sposFactory" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/dataRetriever/blockchain" + proofscache "github.com/multiversx/mx-chain-go/dataRetriever/dataPool/proofsCache" "github.com/multiversx/mx-chain-go/dataRetriever/factory/containers" requesterscontainer "github.com/multiversx/mx-chain-go/dataRetriever/factory/requestersContainer" "github.com/multiversx/mx-chain-go/dataRetriever/factory/resolverscontainer" @@ -308,6 +309,7 @@ type ArgTestProcessorNode struct { StatusMetrics external.StatusMetricsHandler WithPeersRatingHandler bool NodeOperationMode common.NodeOperation + Proofs dataRetriever.ProofsPool } // TestProcessorNode represents a container type of class used in integration tests @@ -334,6 +336,7 @@ type TestProcessorNode struct { TrieContainer common.TriesHolder BlockChain data.ChainHandler GenesisBlocks map[uint32]data.HeaderHandler + ProofsPool dataRetriever.ProofsPool EconomicsData *economics.TestEconomicsData RatingsData *rating.RatingsData @@ -1087,7 +1090,8 @@ func (tpn *TestProcessorNode) InitializeProcessors(gasMap map[string]map[string] } func (tpn *TestProcessorNode) initDataPools() { - tpn.DataPool = dataRetrieverMock.CreatePoolsHolder(1, tpn.ShardCoordinator.SelfId()) + tpn.ProofsPool = proofscache.NewProofsPool() + tpn.DataPool = dataRetrieverMock.CreatePoolsHolderWithProofsPool(1, tpn.ShardCoordinator.SelfId(), tpn.ProofsPool) cacherCfg := storageunit.CacheConfig{Capacity: 10000, Type: storageunit.LRUCache, Shards: 1} suCache, _ := storageunit.NewCache(cacherCfg) tpn.WhiteListHandler, _ = interceptors.NewWhiteListDataVerifier(suCache) @@ -2757,6 +2761,20 @@ func (tpn *TestProcessorNode) ProposeBlock(round uint64, nonce uint64) (data.Bod return nil, nil, nil } + previousProof := &dataBlock.HeaderProof{ + PubKeysBitmap: []byte{1}, + AggregatedSignature: sig, + HeaderHash: currHdrHash, + HeaderEpoch: currHdr.GetEpoch(), + HeaderNonce: currHdr.GetNonce(), + HeaderShardId: currHdr.GetShardID(), + } + blockHeader.SetPreviousProof(previousProof) + + tpn.ProofsPool.AddProof(previousProof) + + log.Error("added proof", "currHdrHash", currHdrHash, "node", tpn.OwnAccount.Address) + genesisRound := tpn.BlockChain.GetGenesisHeader().GetRound() err = blockHeader.SetTimeStamp((round - genesisRound) * uint64(tpn.RoundHandler.TimeDuration().Seconds())) if err != nil { diff --git a/testscommon/dataRetriever/poolFactory.go b/testscommon/dataRetriever/poolFactory.go index 54214ceedd0..43aaeb3e78f 100644 --- a/testscommon/dataRetriever/poolFactory.go +++ b/testscommon/dataRetriever/poolFactory.go @@ -51,8 +51,7 @@ func CreateTxPool(numShards uint32, selfShard uint32) (dataRetriever.ShardedData ) } -// CreatePoolsHolder - -func CreatePoolsHolder(numShards uint32, selfShard uint32) dataRetriever.PoolsHolder { +func createPoolHolderArgs(numShards uint32, selfShard uint32) dataPool.DataPoolArgs { var err error txPool, err := CreateTxPool(numShards, selfShard) @@ -160,12 +159,35 @@ func CreatePoolsHolder(numShards uint32, selfShard uint32) dataRetriever.PoolsHo ValidatorsInfo: validatorsInfo, Proofs: proofsPool, } + + return dataPoolArgs +} + +// CreatePoolsHolder - +func CreatePoolsHolder(numShards uint32, selfShard uint32) dataRetriever.PoolsHolder { + + dataPoolArgs := createPoolHolderArgs(numShards, selfShard) + holder, err := dataPool.NewDataPool(dataPoolArgs) panicIfError("CreatePoolsHolder", err) return holder } +// CreatePoolsHolderWithProofsPool - +func CreatePoolsHolderWithProofsPool( + numShards uint32, selfShard uint32, + proofsPool dataRetriever.ProofsPool, +) dataRetriever.PoolsHolder { + dataPoolArgs := createPoolHolderArgs(numShards, selfShard) + dataPoolArgs.Proofs = proofsPool + + holder, err := dataPool.NewDataPool(dataPoolArgs) + panicIfError("CreatePoolsHolderWithProofsPool", err) + + return holder +} + // CreatePoolsHolderWithTxPool - func CreatePoolsHolderWithTxPool(txPool dataRetriever.ShardedDataCacherNotifier) dataRetriever.PoolsHolder { var err error From d7d94abc59cdc047ecf552b938d33a832a41493a Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 25 Nov 2024 17:04:34 +0200 Subject: [PATCH 19/29] update check on sync with equivalent proofs test --- .../sync/basicSync/basicSync_test.go | 16 ++++++++++++---- integrationTests/testProcessorNode.go | 6 +++++- .../processor/hdrInterceptorProcessor.go | 3 ++- process/sync/baseSync.go | 18 ++++++++---------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/integrationTests/sync/basicSync/basicSync_test.go b/integrationTests/sync/basicSync/basicSync_test.go index 3a2e0b0ae15..1dfb82dcf80 100644 --- a/integrationTests/sync/basicSync/basicSync_test.go +++ b/integrationTests/sync/basicSync/basicSync_test.go @@ -20,7 +20,6 @@ func TestSyncWorksInShard_EmptyBlocksNoForks(t *testing.T) { if testing.Short() { t.Skip("this is not a short test") } - maxShards := uint32(1) shardId := uint32(0) numNodesPerShard := 6 @@ -204,8 +203,6 @@ func TestSyncWorksInShard_EmptyBlocksNoForks_With_EquivalentProofs(t *testing.T) t.Skip("this is not a short test") } - logger.SetLogLevel("*:DEBUG") - maxShards := uint32(1) shardId := uint32(0) numNodesPerShard := 3 @@ -273,5 +270,16 @@ func TestSyncWorksInShard_EmptyBlocksNoForks_With_EquivalentProofs(t *testing.T) time.Sleep(integrationTests.SyncDelay) - testAllNodesHaveTheSameBlockHeightInBlockchain(t, nodes) + expectedNonce := nodes[0].BlockChain.GetCurrentBlockHeader().GetNonce() + for i := 1; i < len(nodes); i++ { + if check.IfNil(nodes[i].BlockChain.GetCurrentBlockHeader()) { + assert.Fail(t, fmt.Sprintf("Node with idx %d does not have a current block", i)) + } else { + if i == idxProposerMeta { // metachain node has highest nonce since it's single node and it did not synced the header + assert.Equal(t, expectedNonce, nodes[i].BlockChain.GetCurrentBlockHeader().GetNonce()) + } else { // shard nodes have not managed to sync last header since there is no proof for it; in the complete flow, when nodes will be fully sinced they will get current header directly from consensus, so they will receive the proof for header + assert.Equal(t, expectedNonce-1, nodes[i].BlockChain.GetCurrentBlockHeader().GetNonce()) + } + } + } } diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index 651e5b6a068..ecae083543b 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -3447,7 +3447,11 @@ func GetDefaultStatusComponents() *mock.StatusComponentsStub { func getDefaultBootstrapComponents(shardCoordinator sharding.Coordinator) *mainFactoryMocks.BootstrapComponentsStub { var versionedHeaderFactory nodeFactory.VersionedHeaderFactory - headerVersionHandler := &testscommon.HeaderVersionHandlerStub{} + headerVersionHandler := &testscommon.HeaderVersionHandlerStub{ + GetVersionCalled: func(epoch uint32) string { + return "2" + }, + } versionedHeaderFactory, _ = hdrFactory.NewShardHeaderFactory(headerVersionHandler) if shardCoordinator.SelfId() == core.MetachainShardId { versionedHeaderFactory, _ = hdrFactory.NewMetaHeaderFactory(headerVersionHandler) diff --git a/process/interceptors/processor/hdrInterceptorProcessor.go b/process/interceptors/processor/hdrInterceptorProcessor.go index d3639cba18b..490c3dbc1ba 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor.go +++ b/process/interceptors/processor/hdrInterceptorProcessor.go @@ -1,6 +1,7 @@ package processor import ( + "reflect" "sync" "github.com/multiversx/mx-chain-core-go/core" @@ -76,7 +77,7 @@ func (hip *HdrInterceptorProcessor) Save(data process.InterceptedData, _ core.Pe // TODO: check for equivalent flag err := hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) if err != nil { - log.Error("failed to add proof", "error", err, "headerHash", interceptedHdr.Hash()) + log.Error("failed to add proof", "error", err, "intercepted header hash", interceptedHdr.Hash(), "header type", reflect.TypeOf(interceptedHdr.HeaderHandler())) } else { log.Debug("HdrInterceptorProcessor: added proof", "headerHash", interceptedHdr.HeaderHandler().GetPreviousProof().GetHeaderHash()) } diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index 460202285e7..9ac8925161c 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -707,10 +707,6 @@ func (boot *baseBootstrap) handleEquivalentProof( header data.HeaderHandler, headerHash []byte, ) error { - if header.GetNonce() == 1 { - return nil - } - if !boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) { return nil } @@ -721,20 +717,20 @@ func (boot *baseBootstrap) handleEquivalentProof( } if !boot.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, prevHeader.GetEpoch()) { - // no need to check proof for first block - log.Info("no need to check first activation blockk") + // no need to check proof for first block after activation + log.Info("handleEquivalentProof: no need to check equivalent proof for first activation block") return nil } + // process block only if there is a proof for it hasProof := boot.proofs.HasProof(header.GetShardID(), headerHash) if hasProof { - log.Error("F HAS proof for header", "headerHash", headerHash) return nil } - log.Error("process sync: did not have proof for header, will try again", "headerHash", headerHash) + log.Trace("baseBootstrap.handleEquivalentProof: did not have proof for header, will try again", "headerHash", headerHash) - // wait also for next header + // TODO: evaluate adding a wait here, or request for next header if missing _, _, err = boot.blockBootstrapper.getHeaderWithNonceRequestingIfMissing(header.GetNonce() + 1) if err != nil { return err @@ -742,7 +738,7 @@ func (boot *baseBootstrap) handleEquivalentProof( hasProof = boot.proofs.HasProof(header.GetShardID(), headerHash) if !hasProof { - return fmt.Errorf("process sync: did not have proof for header, headerHash %s", hex.EncodeToString(headerHash)) + return fmt.Errorf("baseBootstrap.handleEquivalentProof: did not have proof for header, headerHash %s", hex.EncodeToString(headerHash)) } return nil @@ -786,6 +782,8 @@ func (boot *baseBootstrap) cleanProofsBehindFinal(header data.HeaderHandler) { "shardID", header.GetShardID(), "error", err) } + + log.Trace("baseBootstrap.cleanProofsBehindFinal clenaup successfully", "finalNonce", finalNonce) } // rollBack decides if rollBackOneBlock must be called From a389ce3a7ae334623e5b580f7e514e97c67b2edf Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 25 Nov 2024 17:30:00 +0200 Subject: [PATCH 20/29] fix linter issue --- integrationTests/testProcessorNode.go | 2 +- process/interceptors/processor/hdrInterceptorProcessor.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index ecae083543b..983d2ecc8c0 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -2771,7 +2771,7 @@ func (tpn *TestProcessorNode) ProposeBlock(round uint64, nonce uint64) (data.Bod } blockHeader.SetPreviousProof(previousProof) - tpn.ProofsPool.AddProof(previousProof) + _ = tpn.ProofsPool.AddProof(previousProof) log.Error("added proof", "currHdrHash", currHdrHash, "node", tpn.OwnAccount.Address) diff --git a/process/interceptors/processor/hdrInterceptorProcessor.go b/process/interceptors/processor/hdrInterceptorProcessor.go index 490c3dbc1ba..02f496cb9df 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor.go +++ b/process/interceptors/processor/hdrInterceptorProcessor.go @@ -78,8 +78,6 @@ func (hip *HdrInterceptorProcessor) Save(data process.InterceptedData, _ core.Pe err := hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) if err != nil { log.Error("failed to add proof", "error", err, "intercepted header hash", interceptedHdr.Hash(), "header type", reflect.TypeOf(interceptedHdr.HeaderHandler())) - } else { - log.Debug("HdrInterceptorProcessor: added proof", "headerHash", interceptedHdr.HeaderHandler().GetPreviousProof().GetHeaderHash()) } return nil From c87d85505116e56ad42702a2d2d5bbf9646f855a Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 26 Nov 2024 17:20:58 +0200 Subject: [PATCH 21/29] added more unit tests for handling equivalent proof --- process/mock/forkDetectorMock.go | 38 ++++-- process/sync/baseSync.go | 2 +- process/sync/export_test.go | 8 ++ process/sync/metablock_test.go | 195 +++++++++++++++++++++++++++++++ 4 files changed, 235 insertions(+), 8 deletions(-) diff --git a/process/mock/forkDetectorMock.go b/process/mock/forkDetectorMock.go index a574e4724b1..51e79af246f 100644 --- a/process/mock/forkDetectorMock.go +++ b/process/mock/forkDetectorMock.go @@ -28,17 +28,27 @@ func (fdm *ForkDetectorMock) RestoreToGenesis() { // AddHeader - func (fdm *ForkDetectorMock) AddHeader(header data.HeaderHandler, hash []byte, state process.BlockHeaderState, selfNotarizedHeaders []data.HeaderHandler, selfNotarizedHeadersHashes [][]byte) error { - return fdm.AddHeaderCalled(header, hash, state, selfNotarizedHeaders, selfNotarizedHeadersHashes) + if fdm.AddHeaderCalled != nil { + return fdm.AddHeaderCalled(header, hash, state, selfNotarizedHeaders, selfNotarizedHeadersHashes) + } + + return nil } // RemoveHeader - func (fdm *ForkDetectorMock) RemoveHeader(nonce uint64, hash []byte) { - fdm.RemoveHeaderCalled(nonce, hash) + if fdm.RemoveHeaderCalled != nil { + fdm.RemoveHeaderCalled(nonce, hash) + } } // CheckFork - func (fdm *ForkDetectorMock) CheckFork() *process.ForkInfo { - return fdm.CheckForkCalled() + if fdm.CheckForkCalled != nil { + return fdm.CheckForkCalled() + } + + return nil } // GetHighestFinalBlockNonce - @@ -51,12 +61,20 @@ func (fdm *ForkDetectorMock) GetHighestFinalBlockNonce() uint64 { // GetHighestFinalBlockHash - func (fdm *ForkDetectorMock) GetHighestFinalBlockHash() []byte { - return fdm.GetHighestFinalBlockHashCalled() + if fdm.GetHighestFinalBlockHashCalled != nil { + return fdm.GetHighestFinalBlockHashCalled() + } + + return nil } // ProbableHighestNonce - func (fdm *ForkDetectorMock) ProbableHighestNonce() uint64 { - return fdm.ProbableHighestNonceCalled() + if fdm.ProbableHighestNonceCalled != nil { + return fdm.ProbableHighestNonceCalled() + } + + return 0 } // SetRollBackNonce - @@ -68,12 +86,18 @@ func (fdm *ForkDetectorMock) SetRollBackNonce(nonce uint64) { // ResetFork - func (fdm *ForkDetectorMock) ResetFork() { - fdm.ResetForkCalled() + if fdm.ResetForkCalled != nil { + fdm.ResetForkCalled() + } } // GetNotarizedHeaderHash - func (fdm *ForkDetectorMock) GetNotarizedHeaderHash(nonce uint64) []byte { - return fdm.GetNotarizedHeaderHashCalled(nonce) + if fdm.GetNotarizedHeaderHashCalled != nil { + return fdm.GetNotarizedHeaderHashCalled(nonce) + } + + return nil } // ResetProbableHighestNonce - diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index 9ac8925161c..88d47d37b1a 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -783,7 +783,7 @@ func (boot *baseBootstrap) cleanProofsBehindFinal(header data.HeaderHandler) { "error", err) } - log.Trace("baseBootstrap.cleanProofsBehindFinal clenaup successfully", "finalNonce", finalNonce) + log.Trace("baseBootstrap.cleanProofsBehindFinal cleanup successfully", "finalNonce", finalNonce) } // rollBack decides if rollBackOneBlock must be called diff --git a/process/sync/export_test.go b/process/sync/export_test.go index 719e7599f9f..16a91ead8b3 100644 --- a/process/sync/export_test.go +++ b/process/sync/export_test.go @@ -288,3 +288,11 @@ func (boot *baseBootstrap) IsInImportMode() bool { func (boot *baseBootstrap) ProcessWaitTime() time.Duration { return boot.processWaitTime } + +// HandleEquivalentProof - +func (boot *baseBootstrap) HandleEquivalentProof( + header data.HeaderHandler, + headerHash []byte, +) error { + return boot.handleEquivalentProof(header, headerHash) +} diff --git a/process/sync/metablock_test.go b/process/sync/metablock_test.go index 9329634d032..e77c5190995 100644 --- a/process/sync/metablock_test.go +++ b/process/sync/metablock_test.go @@ -28,6 +28,7 @@ import ( "github.com/multiversx/mx-chain-go/storage" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/cache" + dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/dblookupext" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" @@ -1830,3 +1831,197 @@ func TestMetaBootstrap_SyncAccountsDBs(t *testing.T) { require.True(t, accountsSyncCalled) }) } + +func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { + t.Parallel() + + prevHeaderHash1 := []byte("prevHeaderHash") + headerHash1 := []byte("headerHash") + + t.Run("flag no activated, should return direclty", func(t *testing.T) { + t.Parallel() + + header := &block.MetaBlock{ + Nonce: 11, + } + + args := CreateMetaBootstrapMockArguments() + args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return false + }, + } + + bs, err := sync.NewMetaBootstrap(args) + require.Nil(t, err) + + err = bs.HandleEquivalentProof(header, headerHash1) + require.Nil(t, err) + }) + + t.Run("should return nil if first block after activation", func(t *testing.T) { + t.Parallel() + + prevHeader := &block.MetaBlock{ + Epoch: 3, + Nonce: 10, + } + + header := &block.MetaBlock{ + Epoch: 4, + Nonce: 11, + PrevHash: prevHeaderHash1, + } + + args := CreateMetaBootstrapMockArguments() + args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + if epoch == 4 { + return flag == common.EquivalentMessagesFlag + } + + return false + }, + } + + pools := createMockPools() + pools.HeadersCalled = func() dataRetriever.HeadersPool { + sds := &mock.HeadersCacherStub{} + sds.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + if bytes.Equal(hash, prevHeaderHash1) { + return prevHeader, nil + } + + return prevHeader, nil + } + + return sds + } + + args.PoolsHolder = pools + + bs, err := sync.NewMetaBootstrap(args) + require.Nil(t, err) + + err = bs.HandleEquivalentProof(header, headerHash1) + require.Nil(t, err) + }) + + t.Run("should work, proof already in pool", func(t *testing.T) { + t.Parallel() + + prevHeader := &block.MetaBlock{ + Nonce: 10, + } + + header := &block.MetaBlock{ + Nonce: 11, + PrevHash: prevHeaderHash1, + } + + args := CreateMetaBootstrapMockArguments() + args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.EquivalentMessagesFlag + }, + } + + pools := createMockPools() + pools.HeadersCalled = func() dataRetriever.HeadersPool { + sds := &mock.HeadersCacherStub{} + sds.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + if bytes.Equal(hash, prevHeaderHash1) { + return prevHeader, nil + } + + return prevHeader, nil + } + + return sds + } + + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{ + HasProofCalled: func(shardID uint32, headerHash []byte) bool { + return true + }, + } + } + + args.PoolsHolder = pools + + bs, err := sync.NewMetaBootstrap(args) + require.Nil(t, err) + + err = bs.HandleEquivalentProof(header, headerHash1) + require.Nil(t, err) + }) + + t.Run("should work, by checking for next header", func(t *testing.T) { + t.Parallel() + + prevHeader := &block.MetaBlock{ + Nonce: 10, + } + + header := &block.MetaBlock{ + Nonce: 11, + PrevHash: prevHeaderHash1, + } + + nextHeader := &block.MetaBlock{ + Nonce: 12, + PrevHash: prevHeaderHash1, + } + + args := CreateMetaBootstrapMockArguments() + args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.EquivalentMessagesFlag + }, + } + + pools := createMockPools() + pools.HeadersCalled = func() dataRetriever.HeadersPool { + sds := &mock.HeadersCacherStub{} + sds.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + if bytes.Equal(hash, prevHeaderHash1) { + return prevHeader, nil + } + + return prevHeader, nil + } + sds.GetHeaderByNonceAndShardIdCalled = func(hdrNonce uint64, shardId uint32) ([]data.HeaderHandler, [][]byte, error) { + if hdrNonce == header.GetNonce()+1 { + return []data.HeaderHandler{nextHeader}, [][]byte{prevHeaderHash1}, nil + } + + return nil, nil, process.ErrMissingHeader + } + + return sds + } + + hasProofCalled := 0 + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{ + HasProofCalled: func(shardID uint32, headerHash []byte) bool { + if hasProofCalled == 0 { + hasProofCalled++ + return false + } + + return true + }, + } + } + + args.PoolsHolder = pools + + bs, err := sync.NewMetaBootstrap(args) + require.Nil(t, err) + + err = bs.HandleEquivalentProof(header, headerHash1) + require.Nil(t, err) + }) +} From 8a95e0500169818b1bd6e9b89fbf23531f147619 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 11:11:05 +0200 Subject: [PATCH 22/29] fix conflicts --- process/headerCheck/headerSignatureVerify.go | 62 ------------ .../headerCheck/headerSignatureVerify_test.go | 95 ------------------- 2 files changed, 157 deletions(-) diff --git a/process/headerCheck/headerSignatureVerify.go b/process/headerCheck/headerSignatureVerify.go index 06b0ffd33eb..50bc3ff42ac 100644 --- a/process/headerCheck/headerSignatureVerify.go +++ b/process/headerCheck/headerSignatureVerify.go @@ -303,67 +303,6 @@ func (hsv *HeaderSigVerifier) VerifyHeaderProof(proofHandler data.HeaderProofHan return multiSigVerifier.VerifyAggregatedSig(consensusPubKeys, proofHandler.GetHeaderHash(), proofHandler.GetAggregatedSignature()) } -<<<<<<< HEAD -func (hsv *HeaderSigVerifier) getPrevHeaderInfo(currentHeader data.HeaderHandler) (data.HeaderHandler, []byte, []byte, []byte, error) { - previousProof := currentHeader.GetPreviousProof() - - var sig, bitmap []byte - if previousProof != nil { - sig, bitmap = previousProof.GetAggregatedSignature(), previousProof.GetPubKeysBitmap() - } - - hash := currentHeader.GetPrevHash() - prevHeader, err := hsv.headersPool.GetHeaderByHash(hash) - if err != nil { - return nil, nil, nil, nil, err - } - - headerCopy, err := hsv.copyHeaderWithoutSig(prevHeader) - if err != nil { - return nil, nil, nil, nil, err - } - - hash, err = core.CalculateHash(hsv.marshalizer, hsv.hasher, headerCopy) - if err != nil { - return nil, nil, nil, nil, err - } - - return headerCopy, hash, sig, bitmap, nil -} - -// VerifyPreviousBlockProof verifies if the structure of the header matches the expected structure in regards with the consensus flag. -// It also verifies previous block proof singature -func (hsv *HeaderSigVerifier) VerifyPreviousBlockProof(header data.HeaderHandler) error { - previousProof := header.GetPreviousProof() - - hasProof := false - hasLeaderSignature := false - - if previousProof != nil { - previousAggregatedSignature, previousBitmap := previousProof.GetAggregatedSignature(), previousProof.GetPubKeysBitmap() - hasProof = len(previousAggregatedSignature) > 0 && len(previousBitmap) > 0 - - if len(previousBitmap) > 0 { - hasLeaderSignature = previousBitmap[0]&1 != 0 - } - } - - isFlagEnabled := hsv.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, header.GetEpoch()) - if isFlagEnabled && !hasProof { - return fmt.Errorf("%w, received header without proof after flag activation", process.ErrInvalidHeader) - } - if !isFlagEnabled && hasProof { - return fmt.Errorf("%w, received header with proof before flag activation", process.ErrInvalidHeader) - } - if isFlagEnabled && !hasLeaderSignature { - return fmt.Errorf("%w, received header without leader signature after flag activation", process.ErrInvalidHeader) - } - - return hsv.VerifyHeaderProof(previousProof) -} - -func (hsv *HeaderSigVerifier) verifyConsensusSize(consensusPubKeys []string, header data.HeaderHandler, bitmap []byte) error { -======= func (hsv *HeaderSigVerifier) verifyConsensusSize( consensusPubKeys []string, bitmap []byte, @@ -372,7 +311,6 @@ func (hsv *HeaderSigVerifier) verifyConsensusSize( round uint64, prevHash []byte, ) error { ->>>>>>> feat/equivalent-messages consensusSize := len(consensusPubKeys) expectedBitmapSize := consensusSize / 8 diff --git a/process/headerCheck/headerSignatureVerify_test.go b/process/headerCheck/headerSignatureVerify_test.go index 4178a0dfef6..adb372ba15c 100644 --- a/process/headerCheck/headerSignatureVerify_test.go +++ b/process/headerCheck/headerSignatureVerify_test.go @@ -707,100 +707,6 @@ func TestHeaderSigVerifier_VerifySignatureOkWhenFallbackThresholdCouldBeApplied( require.True(t, wasCalled) } -<<<<<<< HEAD -func TestCheckHeaderHandler_VerifyPreviousBlockProof(t *testing.T) { - t.Parallel() - - t.Run("flag enabled and no proof should error", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag - }, - } - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return nil - }, - } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) - assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header without proof after flag activation")) - }) - t.Run("flag not enabled and proof should error", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = enableEpochsHandlerMock.NewEnableEpochsHandlerStub() - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return &block.HeaderProof{ - AggregatedSignature: []byte("sig"), - PubKeysBitmap: []byte("bitmap"), - } - }, - } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) - assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header with proof before flag activation")) - }) - t.Run("flag enabled and no leader signature should error", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag - }, - } - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return &block.HeaderProof{ - AggregatedSignature: []byte("sig"), - PubKeysBitmap: []byte{0, 1, 1, 1}, - } - }, - } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) - assert.True(t, errors.Is(err, process.ErrInvalidHeader)) - assert.True(t, strings.Contains(err.Error(), "received header without leader signature after flag activation")) - }) - t.Run("should work, flag enabled with proof", func(t *testing.T) { - t.Parallel() - - args := createHeaderSigVerifierArgs() - args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ - IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { - return flag == common.EquivalentMessagesFlag || - flag == common.FixedOrderInConsensusFlag - }, - } - - hdrSigVerifier, _ := NewHeaderSigVerifier(args) - - hdr := &testscommon.HeaderHandlerStub{ - GetPreviousProofCalled: func() data.HeaderProofHandler { - return &block.HeaderProof{ - AggregatedSignature: []byte("sig"), - PubKeysBitmap: []byte{1, 1, 1, 1}, - } - }, - } - err := hdrSigVerifier.VerifyPreviousBlockProof(hdr) - assert.Nil(t, err) - }) -======= func getFilledHeader() data.HeaderHandler { return &dataBlock.Header{ PrevHash: []byte("prev hash"), @@ -809,7 +715,6 @@ func getFilledHeader() data.HeaderHandler { PubKeysBitmap: []byte{0xFF}, LeaderSignature: []byte("leader signature"), } ->>>>>>> feat/equivalent-messages } func TestHeaderSigVerifier_VerifyHeaderProof(t *testing.T) { From 89a246ee8f673b02011fd5f1e76a4390ff1fbb30 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 11:29:23 +0200 Subject: [PATCH 23/29] added flag for proofs check in header intercetor --- .../baseInterceptorsContainerFactory.go | 15 +++++---- .../metaInterceptorsContainerFactory.go | 8 +++-- .../shardInterceptorsContainerFactory.go | 1 + .../processor/argHdrInterceptorProcessor.go | 8 +++-- .../processor/hdrInterceptorProcessor.go | 33 +++++++++++-------- .../processor/hdrInterceptorProcessor_test.go | 26 +++++++++++++-- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go index 3732e9377f7..eab22fac66d 100644 --- a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go @@ -56,6 +56,7 @@ type baseInterceptorsContainerFactory struct { hardforkTrigger heartbeat.HardforkTrigger nodeOperationMode common.NodeOperation interceptedDataVerifierFactory process.InterceptedDataVerifierFactory + enableEpochsHandler common.EnableEpochsHandler } func checkBaseParams( @@ -423,9 +424,10 @@ func (bicf *baseInterceptorsContainerFactory) generateHeaderInterceptors() error } argProcessor := &processor.ArgHdrInterceptorProcessor{ - Headers: bicf.dataPool.Headers(), - BlockBlackList: bicf.blockBlackList, - Proofs: bicf.dataPool.Proofs(), + Headers: bicf.dataPool.Headers(), + BlockBlackList: bicf.blockBlackList, + Proofs: bicf.dataPool.Proofs(), + EnableEpochsHandler: bicf.enableEpochsHandler, } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { @@ -566,9 +568,10 @@ func (bicf *baseInterceptorsContainerFactory) generateMetachainHeaderInterceptor } argProcessor := &processor.ArgHdrInterceptorProcessor{ - Headers: bicf.dataPool.Headers(), - BlockBlackList: bicf.blockBlackList, - Proofs: bicf.dataPool.Proofs(), + Headers: bicf.dataPool.Headers(), + BlockBlackList: bicf.blockBlackList, + Proofs: bicf.dataPool.Proofs(), + EnableEpochsHandler: bicf.enableEpochsHandler, } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { diff --git a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go index 363042d3e73..e3c304b3f83 100644 --- a/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/metaInterceptorsContainerFactory.go @@ -130,6 +130,7 @@ func NewMetaInterceptorsContainerFactory( hardforkTrigger: args.HardforkTrigger, nodeOperationMode: args.NodeOperationMode, interceptedDataVerifierFactory: args.InterceptedDataVerifierFactory, + enableEpochsHandler: args.CoreComponents.EnableEpochsHandler(), } icf := &metaInterceptorsContainerFactory{ @@ -264,9 +265,10 @@ func (micf *metaInterceptorsContainerFactory) createOneShardHeaderInterceptor(to } argProcessor := &processor.ArgHdrInterceptorProcessor{ - Headers: micf.dataPool.Headers(), - BlockBlackList: micf.blockBlackList, - Proofs: micf.dataPool.Proofs(), + Headers: micf.dataPool.Headers(), + BlockBlackList: micf.blockBlackList, + Proofs: micf.dataPool.Proofs(), + EnableEpochsHandler: micf.enableEpochsHandler, } hdrProcessor, err := processor.NewHdrInterceptorProcessor(argProcessor) if err != nil { diff --git a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go index 7acd6d87e59..e3a4e639d5b 100644 --- a/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/shardInterceptorsContainerFactory.go @@ -130,6 +130,7 @@ func NewShardInterceptorsContainerFactory( hardforkTrigger: args.HardforkTrigger, nodeOperationMode: args.NodeOperationMode, interceptedDataVerifierFactory: args.InterceptedDataVerifierFactory, + enableEpochsHandler: args.CoreComponents.EnableEpochsHandler(), } icf := &shardInterceptorsContainerFactory{ diff --git a/process/interceptors/processor/argHdrInterceptorProcessor.go b/process/interceptors/processor/argHdrInterceptorProcessor.go index 818982406f4..0f9616fb2cf 100644 --- a/process/interceptors/processor/argHdrInterceptorProcessor.go +++ b/process/interceptors/processor/argHdrInterceptorProcessor.go @@ -1,13 +1,15 @@ package processor import ( + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/process" ) // ArgHdrInterceptorProcessor is the argument for the interceptor processor used for headers (shard, meta and so on) type ArgHdrInterceptorProcessor struct { - Headers dataRetriever.HeadersPool - Proofs dataRetriever.ProofsPool - BlockBlackList process.TimeCacher + Headers dataRetriever.HeadersPool + Proofs dataRetriever.ProofsPool + BlockBlackList process.TimeCacher + EnableEpochsHandler common.EnableEpochsHandler } diff --git a/process/interceptors/processor/hdrInterceptorProcessor.go b/process/interceptors/processor/hdrInterceptorProcessor.go index 02f496cb9df..015f465fd36 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor.go +++ b/process/interceptors/processor/hdrInterceptorProcessor.go @@ -7,6 +7,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/data" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/process" ) @@ -16,11 +17,12 @@ var _ process.InterceptorProcessor = (*HdrInterceptorProcessor)(nil) // HdrInterceptorProcessor is the processor used when intercepting headers // (shard headers, meta headers) structs which satisfy HeaderHandler interface. type HdrInterceptorProcessor struct { - headers dataRetriever.HeadersPool - proofs dataRetriever.ProofsPool - blackList process.TimeCacher - registeredHandlers []func(topic string, hash []byte, data interface{}) - mutHandlers sync.RWMutex + headers dataRetriever.HeadersPool + proofs dataRetriever.ProofsPool + blackList process.TimeCacher + enableEpochsHandler common.EnableEpochsHandler + registeredHandlers []func(topic string, hash []byte, data interface{}) + mutHandlers sync.RWMutex } // NewHdrInterceptorProcessor creates a new TxInterceptorProcessor instance @@ -37,12 +39,16 @@ func NewHdrInterceptorProcessor(argument *ArgHdrInterceptorProcessor) (*HdrInter if check.IfNil(argument.BlockBlackList) { return nil, process.ErrNilBlackListCacher } + if check.IfNil(argument.EnableEpochsHandler) { + return nil, process.ErrNilEnableEpochsHandler + } return &HdrInterceptorProcessor{ - headers: argument.Headers, - proofs: argument.Proofs, - blackList: argument.BlockBlackList, - registeredHandlers: make([]func(topic string, hash []byte, data interface{}), 0), + headers: argument.Headers, + proofs: argument.Proofs, + blackList: argument.BlockBlackList, + enableEpochsHandler: argument.EnableEpochsHandler, + registeredHandlers: make([]func(topic string, hash []byte, data interface{}), 0), }, nil } @@ -74,10 +80,11 @@ func (hip *HdrInterceptorProcessor) Save(data process.InterceptedData, _ core.Pe hip.headers.AddHeader(interceptedHdr.Hash(), interceptedHdr.HeaderHandler()) - // TODO: check for equivalent flag - err := hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) - if err != nil { - log.Error("failed to add proof", "error", err, "intercepted header hash", interceptedHdr.Hash(), "header type", reflect.TypeOf(interceptedHdr.HeaderHandler())) + if hip.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, interceptedHdr.HeaderHandler().GetEpoch()) { + err := hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) + if err != nil { + log.Error("failed to add proof", "error", err, "intercepted header hash", interceptedHdr.Hash(), "header type", reflect.TypeOf(interceptedHdr.HeaderHandler())) + } } return nil diff --git a/process/interceptors/processor/hdrInterceptorProcessor_test.go b/process/interceptors/processor/hdrInterceptorProcessor_test.go index b1e28b56769..74dd77d321e 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor_test.go +++ b/process/interceptors/processor/hdrInterceptorProcessor_test.go @@ -4,21 +4,25 @@ import ( "testing" "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-go/common" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/interceptors/processor" "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" + "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/stretchr/testify/assert" ) func createMockHdrArgument() *processor.ArgHdrInterceptorProcessor { arg := &processor.ArgHdrInterceptorProcessor{ - Headers: &mock.HeadersCacherStub{}, - Proofs: &dataRetriever.ProofsPoolMock{}, - BlockBlackList: &testscommon.TimeCacheStub{}, + Headers: &mock.HeadersCacherStub{}, + Proofs: &dataRetriever.ProofsPoolMock{}, + BlockBlackList: &testscommon.TimeCacheStub{}, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, } return arg @@ -68,6 +72,17 @@ func TestNewHdrInterceptorProcessor_NilProofsPoolShouldErr(t *testing.T) { assert.Equal(t, process.ErrNilEquivalentProofsPool, err) } +func TestNewHdrInterceptorProcessor_NilEnableEpochsHandlerShouldErr(t *testing.T) { + t.Parallel() + + arg := createMockHdrArgument() + arg.EnableEpochsHandler = nil + hip, err := processor.NewHdrInterceptorProcessor(arg) + + assert.Nil(t, hip) + assert.Equal(t, process.ErrNilEnableEpochsHandler, err) +} + func TestNewHdrInterceptorProcessor_ShouldWork(t *testing.T) { t.Parallel() @@ -178,6 +193,11 @@ func TestHdrInterceptorProcessor_SaveShouldWork(t *testing.T) { wasAddedHeaders = true }, } + arg.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.EquivalentMessagesFlag + }, + } wasAddedProofs := false arg.Proofs = &dataRetriever.ProofsPoolMock{ From cb82037e7252dbf0e5f98e80acc70b52669f7f46 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 11:33:06 +0200 Subject: [PATCH 24/29] remove todo in sync process for proofs --- process/sync/baseSync.go | 1 - 1 file changed, 1 deletion(-) diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index 88d47d37b1a..c7b6d61992a 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -730,7 +730,6 @@ func (boot *baseBootstrap) handleEquivalentProof( log.Trace("baseBootstrap.handleEquivalentProof: did not have proof for header, will try again", "headerHash", headerHash) - // TODO: evaluate adding a wait here, or request for next header if missing _, _, err = boot.blockBootstrapper.getHeaderWithNonceRequestingIfMissing(header.GetNonce() + 1) if err != nil { return err From 87a635e94c2df9023c768968cb8d7b9cb73ae3a5 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 13:53:58 +0200 Subject: [PATCH 25/29] remove accumulation maps for epoch start confirmation block --- .../bootstrap/epochStartMetaBlockProcessor.go | 111 ++++-------------- 1 file changed, 20 insertions(+), 91 deletions(-) diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor.go b/epochStart/bootstrap/epochStartMetaBlockProcessor.go index b446e1d8a95..b6e2e82ee52 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor.go @@ -37,15 +37,8 @@ type epochStartMetaBlockProcessor struct { mapReceivedMetaBlocks map[string]data.MetaHeaderHandler mapMetaBlocksFromPeers map[string][]core.PeerID - // TODO: refactor to use a separate component for meta block sync handling - // for epoch start metablock and epoch start confirmation block - mutReceivedConfMetaBlocks sync.RWMutex - mapReceivedConfMetaBlocks map[string]data.MetaHeaderHandler - mapConfMetaBlocksFromPeers map[string][]core.PeerID - chanConsensusReached chan bool chanMetaBlockReached chan bool - chanConfMetaBlockReached chan bool metaBlock data.MetaHeaderHandler peerCountTarget int minNumConnectedPeers int @@ -99,11 +92,8 @@ func NewEpochStartMetaBlockProcessor( mutReceivedMetaBlocks: sync.RWMutex{}, mapReceivedMetaBlocks: make(map[string]data.MetaHeaderHandler), mapMetaBlocksFromPeers: make(map[string][]core.PeerID), - mapReceivedConfMetaBlocks: make(map[string]data.MetaHeaderHandler), - mapConfMetaBlocksFromPeers: make(map[string][]core.PeerID), chanConsensusReached: make(chan bool, 1), chanMetaBlockReached: make(chan bool, 1), - chanConfMetaBlockReached: make(chan bool, 1), } processor.waitForEnoughNumConnectedPeers(messenger) @@ -169,12 +159,9 @@ func (e *epochStartMetaBlockProcessor) Save(data process.InterceptedData, fromCo return nil } - if e.isEpochStartConfirmationBlock(metaBlock) { + if e.isEpochStartConfirmationBlockWithEquivalentMessages(metaBlock) { log.Debug("received epoch start confirmation meta", "epoch", metaBlock.GetEpoch(), "from peer", fromConnectedPeer.Pretty()) - e.mutReceivedConfMetaBlocks.Lock() - e.mapReceivedConfMetaBlocks[string(mbHash)] = metaBlock - e.addToConfPeerList(string(mbHash), fromConnectedPeer) - e.mutReceivedConfMetaBlocks.Unlock() + e.chanConsensusReached <- true return nil } @@ -184,7 +171,7 @@ func (e *epochStartMetaBlockProcessor) Save(data process.InterceptedData, fromCo return nil } -func (e *epochStartMetaBlockProcessor) isEpochStartConfirmationBlock(metaBlock data.HeaderHandler) bool { +func (e *epochStartMetaBlockProcessor) isEpochStartConfirmationBlockWithEquivalentMessages(metaBlock data.HeaderHandler) bool { if !e.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, metaBlock.GetEpoch()) { return false } @@ -212,16 +199,6 @@ func (e *epochStartMetaBlockProcessor) addToPeerList(hash string, peer core.Peer e.mapMetaBlocksFromPeers[hash] = append(e.mapMetaBlocksFromPeers[hash], peer) } -func (e *epochStartMetaBlockProcessor) addToConfPeerList(hash string, peer core.PeerID) { - peersListForHash := e.mapConfMetaBlocksFromPeers[hash] - for _, pid := range peersListForHash { - if pid == peer { - return - } - } - e.mapConfMetaBlocksFromPeers[hash] = append(e.mapConfMetaBlocksFromPeers[hash], peer) -} - // GetEpochStartMetaBlock will return the metablock after it is confirmed or an error if the number of tries was exceeded // This is a blocking method which will end after the consensus for the meta block is obtained or the context is done func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Context) (data.MetaHeaderHandler, error) { @@ -239,35 +216,25 @@ func (e *epochStartMetaBlockProcessor) GetEpochStartMetaBlock(ctx context.Contex } }() - err = e.waitForMetaBlock(ctx) - if err != nil { - return nil, err - } - - err = e.waitForConfMetaBlock(ctx) + metaBlock, err := e.waitForMetaBlock(ctx) if err != nil { return nil, err } - chanCheckMaps := time.After(durationBetweenChecks) - - for { - select { - case <-e.chanConsensusReached: - return e.metaBlock, nil - case <-ctx.Done(): - return e.getMostReceivedMetaBlock() - case <-chanCheckMaps: - e.checkMaps() - chanCheckMaps = time.After(durationBetweenChecks) + if e.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, metaBlock.GetEpoch()) { + err = e.waitForConfMetaBlock(ctx, metaBlock) + if err != nil { + return nil, err } } + + return metaBlock, nil } -func (e *epochStartMetaBlockProcessor) waitForMetaBlock(ctx context.Context) error { +func (e *epochStartMetaBlockProcessor) waitForMetaBlock(ctx context.Context) (data.MetaHeaderHandler, error) { err := e.requestMetaBlock() if err != nil { - return err + return nil, err } chanRequests := time.After(durationBetweenReRequests) @@ -276,13 +243,13 @@ func (e *epochStartMetaBlockProcessor) waitForMetaBlock(ctx context.Context) err for { select { case <-e.chanMetaBlockReached: - return nil + return e.metaBlock, nil case <-ctx.Done(): - return epochStart.ErrTimeoutWaitingForMetaBlock + return e.getMostReceivedMetaBlock() case <-chanRequests: err = e.requestMetaBlock() if err != nil { - return err + return nil, err } chanRequests = time.After(durationBetweenReRequests) case <-chanCheckMaps: @@ -292,38 +259,30 @@ func (e *epochStartMetaBlockProcessor) waitForMetaBlock(ctx context.Context) err } } -func (e *epochStartMetaBlockProcessor) waitForConfMetaBlock(ctx context.Context) error { - if check.IfNil(e.metaBlock) { +func (e *epochStartMetaBlockProcessor) waitForConfMetaBlock(ctx context.Context, metaBlock data.MetaHeaderHandler) error { + if check.IfNil(metaBlock) { return epochStart.ErrNilMetaBlock } - if !e.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, e.metaBlock.GetEpoch()) { - return nil - } - - err := e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) + err := e.requestConfirmationMetaBlock(metaBlock.GetNonce()) if err != nil { return err } chanRequests := time.After(durationBetweenReRequests) - chanCheckMaps := time.After(durationBetweenChecks) for { select { - case <-e.chanConfMetaBlockReached: + case <-e.chanConsensusReached: return nil case <-ctx.Done(): return epochStart.ErrTimeoutWaitingForMetaBlock case <-chanRequests: - err = e.requestConfirmationMetaBlock(e.metaBlock.GetNonce()) + err = e.requestConfirmationMetaBlock(metaBlock.GetNonce()) if err != nil { return err } chanRequests = time.After(durationBetweenReRequests) - case <-chanCheckMaps: - e.checkConfMetaBlockMaps() - chanCheckMaps = time.After(durationBetweenChecks) } } } @@ -383,36 +342,6 @@ func (e *epochStartMetaBlockProcessor) checkMetaBlockMaps() { } } -func (e *epochStartMetaBlockProcessor) checkConfMetaBlockMaps() { - e.mutReceivedConfMetaBlocks.RLock() - defer e.mutReceivedConfMetaBlocks.RUnlock() - - _, confMetaBlockFound := e.checkReceivedMetaBlock(e.mapConfMetaBlocksFromPeers) - if confMetaBlockFound { - e.chanConfMetaBlockReached <- true - } -} - -func (e *epochStartMetaBlockProcessor) checkMaps() { - e.mutReceivedMetaBlocks.RLock() - _, metaBlockFound := e.checkReceivedMetaBlock(e.mapMetaBlocksFromPeers) - e.mutReceivedMetaBlocks.RUnlock() - - consensusReached := metaBlockFound - if e.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, e.metaBlock.GetEpoch()) { - e.mutReceivedConfMetaBlocks.RLock() - _, confMetaBlockFound := e.checkReceivedMetaBlock(e.mapConfMetaBlocksFromPeers) - e.mutReceivedConfMetaBlocks.RUnlock() - - consensusReached = metaBlockFound && confMetaBlockFound - } - - // no need to check proof here since it is checked in interceptor - if consensusReached { - e.chanConsensusReached <- true - } -} - func (e *epochStartMetaBlockProcessor) checkReceivedMetaBlock(blocksFromPeers map[string][]core.PeerID) (string, bool) { for hash, peersList := range blocksFromPeers { log.Debug("metablock from peers", "num peers", len(peersList), "target", e.peerCountTarget, "hash", []byte(hash)) From 44ab7fa4989b9a85c26bd001d9d15bf75c6cb318 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 13:58:34 +0200 Subject: [PATCH 26/29] rename chan --- epochStart/bootstrap/epochStartMetaBlockProcessor.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/epochStart/bootstrap/epochStartMetaBlockProcessor.go b/epochStart/bootstrap/epochStartMetaBlockProcessor.go index b6e2e82ee52..8ee40232287 100644 --- a/epochStart/bootstrap/epochStartMetaBlockProcessor.go +++ b/epochStart/bootstrap/epochStartMetaBlockProcessor.go @@ -37,7 +37,7 @@ type epochStartMetaBlockProcessor struct { mapReceivedMetaBlocks map[string]data.MetaHeaderHandler mapMetaBlocksFromPeers map[string][]core.PeerID - chanConsensusReached chan bool + chanConfMetaBlockReached chan bool chanMetaBlockReached chan bool metaBlock data.MetaHeaderHandler peerCountTarget int @@ -92,7 +92,7 @@ func NewEpochStartMetaBlockProcessor( mutReceivedMetaBlocks: sync.RWMutex{}, mapReceivedMetaBlocks: make(map[string]data.MetaHeaderHandler), mapMetaBlocksFromPeers: make(map[string][]core.PeerID), - chanConsensusReached: make(chan bool, 1), + chanConfMetaBlockReached: make(chan bool, 1), chanMetaBlockReached: make(chan bool, 1), } @@ -161,7 +161,7 @@ func (e *epochStartMetaBlockProcessor) Save(data process.InterceptedData, fromCo if e.isEpochStartConfirmationBlockWithEquivalentMessages(metaBlock) { log.Debug("received epoch start confirmation meta", "epoch", metaBlock.GetEpoch(), "from peer", fromConnectedPeer.Pretty()) - e.chanConsensusReached <- true + e.chanConfMetaBlockReached <- true return nil } @@ -273,7 +273,7 @@ func (e *epochStartMetaBlockProcessor) waitForConfMetaBlock(ctx context.Context, for { select { - case <-e.chanConsensusReached: + case <-e.chanConfMetaBlockReached: return nil case <-ctx.Done(): return epochStart.ErrTimeoutWaitingForMetaBlock From 555ea3df0aa9446338f044a062273717eb854fc9 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 14:49:39 +0200 Subject: [PATCH 27/29] more fixes after review --- .../dataPool/proofsCache/proofsPool.go | 24 ++++---- .../processor/hdrInterceptorProcessor.go | 2 +- process/sync/baseSync.go | 4 ++ process/sync/metablock_test.go | 59 ++++++++++++++----- process/sync/shardblock_test.go | 28 +++++++++ 5 files changed, 90 insertions(+), 27 deletions(-) diff --git a/dataRetriever/dataPool/proofsCache/proofsPool.go b/dataRetriever/dataPool/proofsCache/proofsPool.go index bce665020a0..6362f601928 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool.go @@ -16,15 +16,15 @@ type proofsPool struct { mutCache sync.RWMutex cache map[uint32]*proofsCache - mutAddedProofHandlers sync.RWMutex - addedProofHandlers []func(headerProof data.HeaderProofHandler) + mutAddedProofSubscribers sync.RWMutex + addedProofSubscribers []func(headerProof data.HeaderProofHandler) } // NewProofsPool creates a new proofs pool component func NewProofsPool() *proofsPool { return &proofsPool{ - cache: make(map[uint32]*proofsCache), - addedProofHandlers: make([]func(headerProof data.HeaderProofHandler), 0), + cache: make(map[uint32]*proofsCache), + addedProofSubscribers: make([]func(headerProof data.HeaderProofHandler), 0), } } @@ -63,16 +63,16 @@ func (pp *proofsPool) AddProof( proofsPerShard.addProof(headerProof) - pp.callAddedProofHandlers(headerProof) + pp.callAddedProofSubscribers(headerProof) return nil } -func (pp *proofsPool) callAddedProofHandlers(headerProof data.HeaderProofHandler) { - pp.mutAddedProofHandlers.RLock() - defer pp.mutAddedProofHandlers.RUnlock() +func (pp *proofsPool) callAddedProofSubscribers(headerProof data.HeaderProofHandler) { + pp.mutAddedProofSubscribers.RLock() + defer pp.mutAddedProofSubscribers.RUnlock() - for _, handler := range pp.addedProofHandlers { + for _, handler := range pp.addedProofSubscribers { go handler(headerProof) } } @@ -142,9 +142,9 @@ func (pp *proofsPool) RegisterHandler(handler func(headerProof data.HeaderProofH return } - pp.mutAddedProofHandlers.Lock() - pp.addedProofHandlers = append(pp.addedProofHandlers, handler) - pp.mutAddedProofHandlers.Unlock() + pp.mutAddedProofSubscribers.Lock() + pp.addedProofSubscribers = append(pp.addedProofSubscribers, handler) + pp.mutAddedProofSubscribers.Unlock() } // IsInterfaceNil returns true if there is no value under the interface diff --git a/process/interceptors/processor/hdrInterceptorProcessor.go b/process/interceptors/processor/hdrInterceptorProcessor.go index 015f465fd36..9743f0d2d47 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor.go +++ b/process/interceptors/processor/hdrInterceptorProcessor.go @@ -80,7 +80,7 @@ func (hip *HdrInterceptorProcessor) Save(data process.InterceptedData, _ core.Pe hip.headers.AddHeader(interceptedHdr.Hash(), interceptedHdr.HeaderHandler()) - if hip.enableEpochsHandler.IsFlagEnabledInEpoch(common.EquivalentMessagesFlag, interceptedHdr.HeaderHandler().GetEpoch()) { + if common.IsFlagEnabledAfterEpochsStartBlock(interceptedHdr.HeaderHandler(), hip.enableEpochsHandler, common.EquivalentMessagesFlag) { err := hip.proofs.AddProof(interceptedHdr.HeaderHandler().GetPreviousProof()) if err != nil { log.Error("failed to add proof", "error", err, "intercepted header hash", interceptedHdr.Hash(), "header type", reflect.TypeOf(interceptedHdr.HeaderHandler())) diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index c7b6d61992a..7245906fdad 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -497,6 +497,9 @@ func checkBaseBootstrapParameters(arguments ArgBaseBootstrapper) error { if check.IfNil(arguments.EnableEpochsHandler) { return process.ErrNilEnableEpochsHandler } + if check.IfNil(arguments.PoolsHolder.Proofs()) { + return process.ErrNilProofsPool + } return nil } @@ -772,6 +775,7 @@ func (boot *baseBootstrap) cleanProofsBehindFinal(header data.HeaderHandler) { return } + // TODO: analyse fork detection by proofs finalNonce := boot.forkDetector.GetHighestFinalBlockNonce() err := boot.proofs.CleanupProofsBehindNonce(header.GetShardID(), finalNonce) diff --git a/process/sync/metablock_test.go b/process/sync/metablock_test.go index e77c5190995..f53ebc9c957 100644 --- a/process/sync/metablock_test.go +++ b/process/sync/metablock_test.go @@ -407,6 +407,34 @@ func TestNewMetaBootstrap_InvalidProcessTimeShouldErr(t *testing.T) { assert.True(t, errors.Is(err, process.ErrInvalidProcessWaitTime)) } +func TestNewMetaBootstrap_NilEnableEpochsHandlerShouldErr(t *testing.T) { + t.Parallel() + + args := CreateMetaBootstrapMockArguments() + args.EnableEpochsHandler = nil + + bs, err := sync.NewMetaBootstrap(args) + + assert.True(t, check.IfNil(bs)) + assert.True(t, errors.Is(err, process.ErrNilEnableEpochsHandler)) +} + +func TestNewMetaBootstrap_PoolsHolderRetNilOnProofsShouldErr(t *testing.T) { + t.Parallel() + + args := CreateMetaBootstrapMockArguments() + pools := createMockPools() + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return nil + } + args.PoolsHolder = pools + + bs, err := sync.NewMetaBootstrap(args) + + assert.True(t, check.IfNil(bs)) + assert.Equal(t, process.ErrNilProofsPool, err) +} + func TestNewMetaBootstrap_MissingStorer(t *testing.T) { t.Parallel() @@ -1838,7 +1866,7 @@ func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { prevHeaderHash1 := []byte("prevHeaderHash") headerHash1 := []byte("headerHash") - t.Run("flag no activated, should return direclty", func(t *testing.T) { + t.Run("flag not activated, should return direclty", func(t *testing.T) { t.Parallel() header := &block.MetaBlock{ @@ -1892,7 +1920,7 @@ func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { return prevHeader, nil } - return prevHeader, nil + return nil, sync.ErrHeaderNotFound } return sds @@ -1934,7 +1962,7 @@ func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { return prevHeader, nil } - return prevHeader, nil + return nil, sync.ErrHeaderNotFound } return sds @@ -1960,18 +1988,21 @@ func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { t.Run("should work, by checking for next header", func(t *testing.T) { t.Parallel() - prevHeader := &block.MetaBlock{ + headerHash1 := []byte("headerHash1") + headerHash2 := []byte("headerHash2") + + header1 := &block.MetaBlock{ Nonce: 10, } - header := &block.MetaBlock{ + header2 := &block.MetaBlock{ Nonce: 11, - PrevHash: prevHeaderHash1, + PrevHash: headerHash1, } - nextHeader := &block.MetaBlock{ + header3 := &block.MetaBlock{ Nonce: 12, - PrevHash: prevHeaderHash1, + PrevHash: headerHash2, } args := CreateMetaBootstrapMockArguments() @@ -1985,15 +2016,15 @@ func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { pools.HeadersCalled = func() dataRetriever.HeadersPool { sds := &mock.HeadersCacherStub{} sds.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { - if bytes.Equal(hash, prevHeaderHash1) { - return prevHeader, nil + if bytes.Equal(hash, headerHash1) { + return header1, nil } - return prevHeader, nil + return nil, sync.ErrHeaderNotFound } sds.GetHeaderByNonceAndShardIdCalled = func(hdrNonce uint64, shardId uint32) ([]data.HeaderHandler, [][]byte, error) { - if hdrNonce == header.GetNonce()+1 { - return []data.HeaderHandler{nextHeader}, [][]byte{prevHeaderHash1}, nil + if hdrNonce == header2.GetNonce()+1 { + return []data.HeaderHandler{header3}, [][]byte{headerHash2}, nil } return nil, nil, process.ErrMissingHeader @@ -2021,7 +2052,7 @@ func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { bs, err := sync.NewMetaBootstrap(args) require.Nil(t, err) - err = bs.HandleEquivalentProof(header, headerHash1) + err = bs.HandleEquivalentProof(header2, headerHash2) require.Nil(t, err) }) } diff --git a/process/sync/shardblock_test.go b/process/sync/shardblock_test.go index 339fbb0db36..fbf974c1ee4 100644 --- a/process/sync/shardblock_test.go +++ b/process/sync/shardblock_test.go @@ -465,6 +465,34 @@ func TestNewShardBootstrap_InvalidProcessTimeShouldErr(t *testing.T) { assert.True(t, errors.Is(err, process.ErrInvalidProcessWaitTime)) } +func TestNewShardBootstrap_NilEnableEpochsHandlerShouldErr(t *testing.T) { + t.Parallel() + + args := CreateShardBootstrapMockArguments() + args.EnableEpochsHandler = nil + + bs, err := sync.NewShardBootstrap(args) + + assert.True(t, check.IfNil(bs)) + assert.True(t, errors.Is(err, process.ErrNilEnableEpochsHandler)) +} + +func TestNewShardBootstrap_PoolsHolderRetNilOnProofsShouldErr(t *testing.T) { + t.Parallel() + + args := CreateShardBootstrapMockArguments() + pools := createMockPools() + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return nil + } + args.PoolsHolder = pools + + bs, err := sync.NewShardBootstrap(args) + + assert.True(t, check.IfNil(bs)) + assert.Equal(t, process.ErrNilProofsPool, err) +} + func TestNewShardBootstrap_MissingStorer(t *testing.T) { t.Parallel() From ebb3fc3bb0e58e93b0d84c7b6242cbc9c6cfc8db Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 15:45:58 +0200 Subject: [PATCH 28/29] added more unit tests on handling equivalent proofs on sync --- process/sync/baseSync.go | 3 - process/sync/metablock_test.go | 133 +++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 3 deletions(-) diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index 7245906fdad..cf13638912f 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -497,9 +497,6 @@ func checkBaseBootstrapParameters(arguments ArgBaseBootstrapper) error { if check.IfNil(arguments.EnableEpochsHandler) { return process.ErrNilEnableEpochsHandler } - if check.IfNil(arguments.PoolsHolder.Proofs()) { - return process.ErrNilProofsPool - } return nil } diff --git a/process/sync/metablock_test.go b/process/sync/metablock_test.go index f53ebc9c957..73386a021f1 100644 --- a/process/sync/metablock_test.go +++ b/process/sync/metablock_test.go @@ -2055,4 +2055,137 @@ func TestMetaBootstrap_HandleEquivalentProof(t *testing.T) { err = bs.HandleEquivalentProof(header2, headerHash2) require.Nil(t, err) }) + + t.Run("should return err if failing to get proof after second request", func(t *testing.T) { + t.Parallel() + + headerHash1 := []byte("headerHash1") + headerHash2 := []byte("headerHash2") + + header1 := &block.MetaBlock{ + Nonce: 10, + } + + header2 := &block.MetaBlock{ + Nonce: 11, + PrevHash: headerHash1, + } + + header3 := &block.MetaBlock{ + Nonce: 12, + PrevHash: headerHash2, + } + + args := CreateMetaBootstrapMockArguments() + args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.EquivalentMessagesFlag + }, + } + + pools := createMockPools() + pools.HeadersCalled = func() dataRetriever.HeadersPool { + sds := &mock.HeadersCacherStub{} + sds.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + if bytes.Equal(hash, headerHash1) { + return header1, nil + } + + return nil, sync.ErrHeaderNotFound + } + sds.GetHeaderByNonceAndShardIdCalled = func(hdrNonce uint64, shardId uint32) ([]data.HeaderHandler, [][]byte, error) { + if hdrNonce == header2.GetNonce()+1 { + return []data.HeaderHandler{header3}, [][]byte{headerHash2}, nil + } + + return nil, nil, process.ErrMissingHeader + } + + return sds + } + + hasProofCalled := 0 + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{ + HasProofCalled: func(shardID uint32, headerHash []byte) bool { + if hasProofCalled < 2 { + hasProofCalled++ + return false + } + + return true + }, + } + } + + args.PoolsHolder = pools + + bs, err := sync.NewMetaBootstrap(args) + require.Nil(t, err) + + err = bs.HandleEquivalentProof(header2, headerHash2) + require.Error(t, err) + }) + + t.Run("should return err if failing to request next header", func(t *testing.T) { + t.Parallel() + + headerHash1 := []byte("headerHash1") + headerHash2 := []byte("headerHash2") + + header1 := &block.MetaBlock{ + Nonce: 10, + } + + header2 := &block.MetaBlock{ + Nonce: 11, + PrevHash: headerHash1, + } + + args := CreateMetaBootstrapMockArguments() + args.EnableEpochsHandler = &enableEpochsHandlerMock.EnableEpochsHandlerStub{ + IsFlagEnabledInEpochCalled: func(flag core.EnableEpochFlag, epoch uint32) bool { + return flag == common.EquivalentMessagesFlag + }, + } + + pools := createMockPools() + pools.HeadersCalled = func() dataRetriever.HeadersPool { + sds := &mock.HeadersCacherStub{} + sds.GetHeaderByHashCalled = func(hash []byte) (data.HeaderHandler, error) { + if bytes.Equal(hash, headerHash1) { + return header1, nil + } + + return nil, sync.ErrHeaderNotFound + } + sds.GetHeaderByNonceAndShardIdCalled = func(hdrNonce uint64, shardId uint32) ([]data.HeaderHandler, [][]byte, error) { + return nil, nil, process.ErrMissingHeader + } + + return sds + } + + hasProofCalled := 0 + pools.ProofsCalled = func() dataRetriever.ProofsPool { + return &dataRetrieverMock.ProofsPoolMock{ + HasProofCalled: func(shardID uint32, headerHash []byte) bool { + if hasProofCalled < 2 { + hasProofCalled++ + return false + } + + return true + }, + } + } + + args.PoolsHolder = pools + + bs, err := sync.NewMetaBootstrap(args) + require.Nil(t, err) + + err = bs.HandleEquivalentProof(header2, headerHash2) + require.Error(t, err) + }) } From 39af8f143d8d273edd6b4baf50bc22e2ad0eb73a Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 17 Dec 2024 16:54:26 +0200 Subject: [PATCH 29/29] check for already existing equivalent proof --- dataRetriever/dataPool/proofsCache/errors.go | 3 ++ .../dataPool/proofsCache/proofsPool.go | 2 +- .../dataPool/proofsCache/proofsPool_test.go | 3 ++ .../interceptedEquivalentProof.go | 13 ++++++++ .../interceptedEquivalentProof_test.go | 30 +++++++++++++++++++ process/errors.go | 3 -- .../baseInterceptorsContainerFactory.go | 2 +- .../interceptedEquivalentProofsFactory.go | 6 +++- ...interceptedEquivalentProofsFactory_test.go | 7 +++-- .../equivalentProofsInterceptorProcessor.go | 2 +- ...uivalentProofsInterceptorProcessor_test.go | 3 +- .../processor/hdrInterceptorProcessor.go | 2 +- .../processor/hdrInterceptorProcessor_test.go | 2 +- 13 files changed, 65 insertions(+), 13 deletions(-) diff --git a/dataRetriever/dataPool/proofsCache/errors.go b/dataRetriever/dataPool/proofsCache/errors.go index 63376ef0a92..630dd8cc394 100644 --- a/dataRetriever/dataPool/proofsCache/errors.go +++ b/dataRetriever/dataPool/proofsCache/errors.go @@ -7,3 +7,6 @@ var ErrMissingProof = errors.New("missing proof") // ErrNilProof signals that a nil proof has been provided var ErrNilProof = errors.New("nil proof provided") + +// ErrAlreadyExistingEquivalentProof signals that the provided proof was already exiting in the pool +var ErrAlreadyExistingEquivalentProof = errors.New("already existing equivalent proof") diff --git a/dataRetriever/dataPool/proofsCache/proofsPool.go b/dataRetriever/dataPool/proofsCache/proofsPool.go index 6362f601928..a412794a6db 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool.go @@ -41,7 +41,7 @@ func (pp *proofsPool) AddProof( hasProof := pp.HasProof(shardID, headerHash) if hasProof { - return fmt.Errorf("there was already a valid proof for header, headerHash: %s", hex.EncodeToString(headerHash)) + return fmt.Errorf("%w, headerHash: %s", ErrAlreadyExistingEquivalentProof, hex.EncodeToString(headerHash)) } pp.mutCache.Lock() diff --git a/dataRetriever/dataPool/proofsCache/proofsPool_test.go b/dataRetriever/dataPool/proofsCache/proofsPool_test.go index b2e4ffdcecc..c4e373eeba7 100644 --- a/dataRetriever/dataPool/proofsCache/proofsPool_test.go +++ b/dataRetriever/dataPool/proofsCache/proofsPool_test.go @@ -66,6 +66,9 @@ func TestProofsPool_ShouldWork(t *testing.T) { _ = pp.AddProof(proof3) _ = pp.AddProof(proof4) + err := pp.AddProof(proof4) + require.True(t, errors.Is(err, proofscache.ErrAlreadyExistingEquivalentProof)) + proof, err := pp.GetProof(shardID, []byte("hash3")) require.Nil(t, err) require.Equal(t, proof3, proof) diff --git a/process/block/interceptedBlocks/interceptedEquivalentProof.go b/process/block/interceptedBlocks/interceptedEquivalentProof.go index b1ddba19b67..a7937a5aef2 100644 --- a/process/block/interceptedBlocks/interceptedEquivalentProof.go +++ b/process/block/interceptedBlocks/interceptedEquivalentProof.go @@ -9,6 +9,8 @@ import ( "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/marshal" "github.com/multiversx/mx-chain-go/consensus" + "github.com/multiversx/mx-chain-go/dataRetriever" + proofscache "github.com/multiversx/mx-chain-go/dataRetriever/dataPool/proofsCache" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/sharding" logger "github.com/multiversx/mx-chain-logger-go" @@ -22,12 +24,14 @@ type ArgInterceptedEquivalentProof struct { Marshaller marshal.Marshalizer ShardCoordinator sharding.Coordinator HeaderSigVerifier consensus.HeaderSigVerifier + Proofs dataRetriever.ProofsPool } type interceptedEquivalentProof struct { proof *block.HeaderProof isForCurrentShard bool headerSigVerifier consensus.HeaderSigVerifier + proofsPool dataRetriever.ProofsPool } // NewInterceptedEquivalentProof returns a new instance of interceptedEquivalentProof @@ -46,6 +50,7 @@ func NewInterceptedEquivalentProof(args ArgInterceptedEquivalentProof) (*interce proof: equivalentProof, isForCurrentShard: extractIsForCurrentShard(args.ShardCoordinator, equivalentProof), headerSigVerifier: args.HeaderSigVerifier, + proofsPool: args.Proofs, }, nil } @@ -62,6 +67,9 @@ func checkArgInterceptedEquivalentProof(args ArgInterceptedEquivalentProof) erro if check.IfNil(args.HeaderSigVerifier) { return process.ErrNilHeaderSigVerifier } + if check.IfNil(args.Proofs) { + return process.ErrNilProofsPool + } return nil } @@ -101,6 +109,11 @@ func (iep *interceptedEquivalentProof) CheckValidity() error { return err } + ok := iep.proofsPool.HasProof(iep.proof.GetHeaderShardId(), iep.proof.GetHeaderHash()) + if ok { + return proofscache.ErrAlreadyExistingEquivalentProof + } + return iep.headerSigVerifier.VerifyHeaderProof(iep.proof) } diff --git a/process/block/interceptedBlocks/interceptedEquivalentProof_test.go b/process/block/interceptedBlocks/interceptedEquivalentProof_test.go index e46fa651634..b0a8cd6c9c9 100644 --- a/process/block/interceptedBlocks/interceptedEquivalentProof_test.go +++ b/process/block/interceptedBlocks/interceptedEquivalentProof_test.go @@ -9,8 +9,10 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-go/consensus/mock" + proofscache "github.com/multiversx/mx-chain-go/dataRetriever/dataPool/proofsCache" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/testscommon/consensus" + "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" logger "github.com/multiversx/mx-chain-logger-go" "github.com/stretchr/testify/require" @@ -41,6 +43,7 @@ func createMockArgInterceptedEquivalentProof() ArgInterceptedEquivalentProof { Marshaller: testMarshaller, ShardCoordinator: &mock.ShardCoordinatorMock{}, HeaderSigVerifier: &consensus.HeaderSigVerifierMock{}, + Proofs: &dataRetriever.ProofsPoolMock{}, } } @@ -93,6 +96,15 @@ func TestNewInterceptedEquivalentProof(t *testing.T) { require.Equal(t, process.ErrNilHeaderSigVerifier, err) require.Nil(t, iep) }) + t.Run("nil proofs pool should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgInterceptedEquivalentProof() + args.Proofs = nil + iep, err := NewInterceptedEquivalentProof(args) + require.Equal(t, process.ErrNilProofsPool, err) + require.Nil(t, iep) + }) t.Run("unmarshal error should error", func(t *testing.T) { t.Parallel() @@ -134,6 +146,24 @@ func TestInterceptedEquivalentProof_CheckValidity(t *testing.T) { err = iep.CheckValidity() require.Equal(t, ErrInvalidProof, err) }) + + t.Run("already exiting proof should error", func(t *testing.T) { + t.Parallel() + + args := createMockArgInterceptedEquivalentProof() + args.Proofs = &dataRetriever.ProofsPoolMock{ + HasProofCalled: func(shardID uint32, headerHash []byte) bool { + return true + }, + } + + iep, err := NewInterceptedEquivalentProof(args) + require.NoError(t, err) + + err = iep.CheckValidity() + require.Equal(t, proofscache.ErrAlreadyExistingEquivalentProof, err) + }) + t.Run("should work", func(t *testing.T) { t.Parallel() diff --git a/process/errors.go b/process/errors.go index c72948e190f..395ebf17620 100644 --- a/process/errors.go +++ b/process/errors.go @@ -1254,9 +1254,6 @@ var ErrNoMatchingConfigForProvidedEpoch = errors.New("no matching configuration" // ErrInvalidHeader is raised when header is invalid var ErrInvalidHeader = errors.New("header is invalid") -// ErrNilEquivalentProofsPool signals that a nil equivalent proofs pool has been provided -var ErrNilEquivalentProofsPool = errors.New("nil equivalent proofs pool") - // ErrNilHeaderProof signals that a nil header proof has been provided var ErrNilHeaderProof = errors.New("nil header proof") diff --git a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go index eab22fac66d..bc167e0dab5 100644 --- a/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go +++ b/process/factory/interceptorscontainer/baseInterceptorsContainerFactory.go @@ -913,7 +913,7 @@ func (bicf *baseInterceptorsContainerFactory) generateValidatorInfoInterceptor() } func (bicf *baseInterceptorsContainerFactory) createOneShardEquivalentProofsInterceptor(topic string) (process.Interceptor, error) { - equivalentProofsFactory := interceptorFactory.NewInterceptedEquivalentProofsFactory(*bicf.argInterceptorFactory) + equivalentProofsFactory := interceptorFactory.NewInterceptedEquivalentProofsFactory(*bicf.argInterceptorFactory, bicf.dataPool.Proofs()) marshaller := bicf.argInterceptorFactory.CoreComponents.InternalMarshalizer() argProcessor := processor.ArgEquivalentProofsInterceptorProcessor{ diff --git a/process/interceptors/factory/interceptedEquivalentProofsFactory.go b/process/interceptors/factory/interceptedEquivalentProofsFactory.go index 0a007fef3d6..4c5694d1e4d 100644 --- a/process/interceptors/factory/interceptedEquivalentProofsFactory.go +++ b/process/interceptors/factory/interceptedEquivalentProofsFactory.go @@ -3,6 +3,7 @@ package factory import ( "github.com/multiversx/mx-chain-core-go/marshal" "github.com/multiversx/mx-chain-go/consensus" + "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/block/interceptedBlocks" "github.com/multiversx/mx-chain-go/sharding" @@ -12,14 +13,16 @@ type interceptedEquivalentProofsFactory struct { marshaller marshal.Marshalizer shardCoordinator sharding.Coordinator headerSigVerifier consensus.HeaderSigVerifier + proofsPool dataRetriever.ProofsPool } // NewInterceptedEquivalentProofsFactory creates a new instance of interceptedEquivalentProofsFactory -func NewInterceptedEquivalentProofsFactory(args ArgInterceptedDataFactory) *interceptedEquivalentProofsFactory { +func NewInterceptedEquivalentProofsFactory(args ArgInterceptedDataFactory, proofsPool dataRetriever.ProofsPool) *interceptedEquivalentProofsFactory { return &interceptedEquivalentProofsFactory{ marshaller: args.CoreComponents.InternalMarshalizer(), shardCoordinator: args.ShardCoordinator, headerSigVerifier: args.HeaderSigVerifier, + proofsPool: proofsPool, } } @@ -30,6 +33,7 @@ func (factory *interceptedEquivalentProofsFactory) Create(buff []byte) (process. Marshaller: factory.marshaller, ShardCoordinator: factory.shardCoordinator, HeaderSigVerifier: factory.headerSigVerifier, + Proofs: factory.proofsPool, } return interceptedBlocks.NewInterceptedEquivalentProof(args) } diff --git a/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go b/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go index 9ee099b1c6a..c96ade9528b 100644 --- a/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go +++ b/process/interceptors/factory/interceptedEquivalentProofsFactory_test.go @@ -8,6 +8,7 @@ import ( "github.com/multiversx/mx-chain-go/consensus/mock" processMock "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/testscommon/consensus" + "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" "github.com/stretchr/testify/require" ) @@ -27,14 +28,14 @@ func TestInterceptedEquivalentProofsFactory_IsInterfaceNil(t *testing.T) { var factory *interceptedEquivalentProofsFactory require.True(t, factory.IsInterfaceNil()) - factory = NewInterceptedEquivalentProofsFactory(createMockArgInterceptedDataFactory()) + factory = NewInterceptedEquivalentProofsFactory(createMockArgInterceptedDataFactory(), &dataRetriever.ProofsPoolMock{}) require.False(t, factory.IsInterfaceNil()) } func TestNewInterceptedEquivalentProofsFactory(t *testing.T) { t.Parallel() - factory := NewInterceptedEquivalentProofsFactory(createMockArgInterceptedDataFactory()) + factory := NewInterceptedEquivalentProofsFactory(createMockArgInterceptedDataFactory(), &dataRetriever.ProofsPoolMock{}) require.NotNil(t, factory) } @@ -42,7 +43,7 @@ func TestInterceptedEquivalentProofsFactory_Create(t *testing.T) { t.Parallel() args := createMockArgInterceptedDataFactory() - factory := NewInterceptedEquivalentProofsFactory(args) + factory := NewInterceptedEquivalentProofsFactory(args, &dataRetriever.ProofsPoolMock{}) require.NotNil(t, factory) providedProof := &block.HeaderProof{ diff --git a/process/interceptors/processor/equivalentProofsInterceptorProcessor.go b/process/interceptors/processor/equivalentProofsInterceptorProcessor.go index 0f66cbc3100..ef8beff12af 100644 --- a/process/interceptors/processor/equivalentProofsInterceptorProcessor.go +++ b/process/interceptors/processor/equivalentProofsInterceptorProcessor.go @@ -34,7 +34,7 @@ func NewEquivalentProofsInterceptorProcessor(args ArgEquivalentProofsInterceptor func checkArgsEquivalentProofs(args ArgEquivalentProofsInterceptorProcessor) error { if check.IfNil(args.EquivalentProofsPool) { - return process.ErrNilEquivalentProofsPool + return process.ErrNilProofsPool } if check.IfNil(args.Marshaller) { return process.ErrNilMarshalizer diff --git a/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go b/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go index 78f815a67b8..b11eca03aec 100644 --- a/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go +++ b/process/interceptors/processor/equivalentProofsInterceptorProcessor_test.go @@ -42,7 +42,7 @@ func TestNewEquivalentProofsInterceptorProcessor(t *testing.T) { args.EquivalentProofsPool = nil epip, err := NewEquivalentProofsInterceptorProcessor(args) - require.Equal(t, process.ErrNilEquivalentProofsPool, err) + require.Equal(t, process.ErrNilProofsPool, err) require.Nil(t, epip) }) t.Run("nil Marshaller should error", func(t *testing.T) { @@ -104,6 +104,7 @@ func TestEquivalentProofsInterceptorProcessor_Save(t *testing.T) { Marshaller: args.Marshaller, ShardCoordinator: &mock.ShardCoordinatorMock{}, HeaderSigVerifier: &consensus.HeaderSigVerifierMock{}, + Proofs: &dataRetriever.ProofsPoolMock{}, } argInterceptedEquivalentProof.DataBuff, _ = argInterceptedEquivalentProof.Marshaller.Marshal(&block.HeaderProof{ PubKeysBitmap: []byte("bitmap"), diff --git a/process/interceptors/processor/hdrInterceptorProcessor.go b/process/interceptors/processor/hdrInterceptorProcessor.go index 9743f0d2d47..e60489c2ae5 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor.go +++ b/process/interceptors/processor/hdrInterceptorProcessor.go @@ -34,7 +34,7 @@ func NewHdrInterceptorProcessor(argument *ArgHdrInterceptorProcessor) (*HdrInter return nil, process.ErrNilCacher } if check.IfNil(argument.Proofs) { - return nil, process.ErrNilEquivalentProofsPool + return nil, process.ErrNilProofsPool } if check.IfNil(argument.BlockBlackList) { return nil, process.ErrNilBlackListCacher diff --git a/process/interceptors/processor/hdrInterceptorProcessor_test.go b/process/interceptors/processor/hdrInterceptorProcessor_test.go index 74dd77d321e..cc35b04d06b 100644 --- a/process/interceptors/processor/hdrInterceptorProcessor_test.go +++ b/process/interceptors/processor/hdrInterceptorProcessor_test.go @@ -69,7 +69,7 @@ func TestNewHdrInterceptorProcessor_NilProofsPoolShouldErr(t *testing.T) { hip, err := processor.NewHdrInterceptorProcessor(arg) assert.Nil(t, hip) - assert.Equal(t, process.ErrNilEquivalentProofsPool, err) + assert.Equal(t, process.ErrNilProofsPool, err) } func TestNewHdrInterceptorProcessor_NilEnableEpochsHandlerShouldErr(t *testing.T) {