diff --git a/cmd/node/config/external.toml b/cmd/node/config/external.toml index 6fbbbb195c6..73bc78bae55 100644 --- a/cmd/node/config/external.toml +++ b/cmd/node/config/external.toml @@ -12,8 +12,8 @@ Username = "" Password = "" # EnabledIndexes represents a slice of indexes that will be enabled for indexing. Full list is: - # ["rating", "transactions", "blocks", "validators", "miniblocks", "rounds", "accounts", "accountshistory", "receipts", "scresults", "accountsesdt", "accountsesdthistory", "epochinfo", "scdeploys", "tokens", "tags", "logs", "delegators", "operations", "esdts"] - EnabledIndexes = ["rating", "transactions", "blocks", "validators", "miniblocks", "rounds", "accounts", "accountshistory", "receipts", "scresults", "accountsesdt", "accountsesdthistory", "epochinfo", "scdeploys", "tokens", "tags", "logs", "delegators", "operations", "esdts"] + # ["rating", "transactions", "blocks", "validators", "miniblocks", "rounds", "accounts", "accountshistory", "receipts", "scresults", "accountsesdt", "accountsesdthistory", "epochinfo", "scdeploys", "tokens", "tags", "logs", "delegators", "operations", "esdts", "events"] + EnabledIndexes = ["rating", "transactions", "blocks", "validators", "miniblocks", "rounds", "accounts", "accountshistory", "receipts", "scresults", "accountsesdt", "accountsesdthistory", "epochinfo", "scdeploys", "tokens", "tags", "logs", "delegators", "operations", "esdts", "events"] # EventNotifierConnector defines settings needed to configure and launch the event notifier component # HTTP event notifier connector integration will be DEPRECATED in the following iterations diff --git a/integrationTests/chainSimulator/vm/esdtImprovements_test.go b/integrationTests/chainSimulator/vm/esdtImprovements_test.go index e0f23f1ce8c..8361feb4fee 100644 --- a/integrationTests/chainSimulator/vm/esdtImprovements_test.go +++ b/integrationTests/chainSimulator/vm/esdtImprovements_test.go @@ -3868,7 +3868,9 @@ func TestChainSimulator_CheckRolesWhichHasToBeSingular(t *testing.T) { } func TestChainSimulator_metaESDT_mergeMetaDataFromMultipleUpdates(t *testing.T) { - t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } baseIssuingCost := "1000" cs, _ := getTestChainSimulatorWithDynamicNFTEnabled(t, baseIssuingCost) @@ -4237,7 +4239,9 @@ func transferSpecialRoleToAddr( } func TestChainSimulator_dynamicNFT_mergeMetaDataFromMultipleUpdates(t *testing.T) { - t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } baseIssuingCost := "1000" cs, _ := getTestChainSimulatorWithDynamicNFTEnabled(t, baseIssuingCost) @@ -4385,7 +4389,9 @@ func TestChainSimulator_dynamicNFT_mergeMetaDataFromMultipleUpdates(t *testing.T } func TestChainSimulator_dynamicNFT_changeMetaDataForOneNFTShouldNotChangeOtherNonces(t *testing.T) { - t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } baseIssuingCost := "1000" cs, _ := getTestChainSimulatorWithDynamicNFTEnabled(t, baseIssuingCost) @@ -4498,7 +4504,9 @@ func TestChainSimulator_dynamicNFT_changeMetaDataForOneNFTShouldNotChangeOtherNo } func TestChainSimulator_dynamicNFT_updateBeforeCreateOnSameAccountShouldOverwrite(t *testing.T) { - t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } baseIssuingCost := "1000" cs, _ := getTestChainSimulatorWithDynamicNFTEnabled(t, baseIssuingCost) @@ -4595,7 +4603,9 @@ func TestChainSimulator_dynamicNFT_updateBeforeCreateOnSameAccountShouldOverwrit } func TestChainSimulator_dynamicNFT_updateBeforeCreateOnDifferentAccountsShouldMergeMetaDataWhenTransferred(t *testing.T) { - t.Parallel() + if testing.Short() { + t.Skip("this is not a short test") + } baseIssuingCost := "1000" cs, _ := getTestChainSimulatorWithDynamicNFTEnabled(t, baseIssuingCost) diff --git a/node/chainSimulator/chainSimulator.go b/node/chainSimulator/chainSimulator.go index 742d040c8c8..b8edc491eda 100644 --- a/node/chainSimulator/chainSimulator.go +++ b/node/chainSimulator/chainSimulator.go @@ -11,7 +11,9 @@ import ( "time" "github.com/multiversx/mx-chain-go/config" + "github.com/multiversx/mx-chain-go/factory" "github.com/multiversx/mx-chain-go/node/chainSimulator/components" + "github.com/multiversx/mx-chain-go/node/chainSimulator/components/heartbeat" "github.com/multiversx/mx-chain-go/node/chainSimulator/configs" "github.com/multiversx/mx-chain-go/node/chainSimulator/dtos" chainSimulatorErrors "github.com/multiversx/mx-chain-go/node/chainSimulator/errors" @@ -130,18 +132,20 @@ func (s *simulator) createChainHandlers(args ArgsBaseChainSimulator) error { return err } + monitor := heartbeat.NewHeartbeatMonitor() + for idx := -1; idx < int(args.NumOfShards); idx++ { shardIDStr := fmt.Sprintf("%d", idx) if idx == -1 { shardIDStr = "metachain" } - node, errCreate := s.createTestNode(*outputConfigs, args, shardIDStr) + node, errCreate := s.createTestNode(*outputConfigs, args, shardIDStr, monitor) if errCreate != nil { return errCreate } - chainHandler, errCreate := process.NewBlocksCreator(node) + chainHandler, errCreate := process.NewBlocksCreator(node, monitor) if errCreate != nil { return errCreate } @@ -195,7 +199,7 @@ func computeStartTimeBaseOnInitialRound(args ArgsChainSimulator) int64 { } func (s *simulator) createTestNode( - outputConfigs configs.ArgsConfigsSimulator, args ArgsBaseChainSimulator, shardIDStr string, + outputConfigs configs.ArgsConfigsSimulator, args ArgsBaseChainSimulator, shardIDStr string, monitor factory.HeartbeatV2Monitor, ) (process.NodeHandler, error) { argsTestOnlyProcessorNode := components.ArgsTestOnlyProcessingNode{ Configs: outputConfigs.Configs, @@ -214,6 +218,7 @@ func (s *simulator) createTestNode( MetaChainConsensusGroupSize: args.MetaChainConsensusGroupSize, RoundDurationInMillis: args.RoundDurationInMillis, VmQueryDelayAfterStartInMs: args.VmQueryDelayAfterStartInMs, + Monitor: monitor, } return components.NewTestOnlyProcessingNode(argsTestOnlyProcessorNode) diff --git a/node/chainSimulator/chainSimulator_test.go b/node/chainSimulator/chainSimulator_test.go index 18f54ccbfe9..2ba89205afe 100644 --- a/node/chainSimulator/chainSimulator_test.go +++ b/node/chainSimulator/chainSimulator_test.go @@ -82,13 +82,17 @@ func TestChainSimulator_GenerateBlocksShouldWork(t *testing.T) { }) require.Nil(t, err) require.NotNil(t, chainSimulator) - defer chainSimulator.Close() time.Sleep(time.Second) err = chainSimulator.GenerateBlocks(50) require.Nil(t, err) + + heartBeats, err := chainSimulator.GetNodeHandler(0).GetFacadeHandler().GetHeartbeats() + require.Nil(t, err) + require.Equal(t, 4, len(heartBeats)) + } func TestChainSimulator_GenerateBlocksAndEpochChangeShouldWork(t *testing.T) { diff --git a/node/chainSimulator/components/heartbeat/heartBeat.go b/node/chainSimulator/components/heartbeat/heartBeat.go new file mode 100644 index 00000000000..ffdd53b6961 --- /dev/null +++ b/node/chainSimulator/components/heartbeat/heartBeat.go @@ -0,0 +1,52 @@ +package heartbeat + +import ( + "github.com/multiversx/mx-chain-core-go/core/check" + "github.com/multiversx/mx-chain-go/factory" + "github.com/multiversx/mx-chain-go/heartbeat" +) + +type heartBeatComponents struct { + monitor factory.HeartbeatV2Monitor +} + +// NewSyncedHeartbeatComponents will create a new instance of heartbeat components +func NewSyncedHeartbeatComponents(monitor factory.HeartbeatV2Monitor) (factory.HeartbeatV2ComponentsHandler, error) { + if check.IfNil(monitor) { + return nil, heartbeat.ErrNilHeartbeatMonitor + } + + return &heartBeatComponents{ + monitor: monitor, + }, nil +} + +// Create will do nothing +func (h *heartBeatComponents) Create() error { + return nil +} + +// Close will do nothing +func (h *heartBeatComponents) Close() error { + return nil +} + +// CheckSubcomponents will do nothing +func (h *heartBeatComponents) CheckSubcomponents() error { + return nil +} + +// String will return a string +func (h *heartBeatComponents) String() string { + return "heartBeat" +} + +// Monitor will return the monitor +func (h *heartBeatComponents) Monitor() factory.HeartbeatV2Monitor { + return h.monitor +} + +// IsInterfaceNil returns true if there is no value under the interface +func (h *heartBeatComponents) IsInterfaceNil() bool { + return h == nil +} diff --git a/node/chainSimulator/components/heartbeat/monitor.go b/node/chainSimulator/components/heartbeat/monitor.go new file mode 100644 index 00000000000..9fda1a369f8 --- /dev/null +++ b/node/chainSimulator/components/heartbeat/monitor.go @@ -0,0 +1,39 @@ +package heartbeat + +import ( + "sync" + + "github.com/multiversx/mx-chain-go/heartbeat/data" +) + +type heartbeatMonitor struct { + heartbeats []data.PubKeyHeartbeat + mutex sync.RWMutex +} + +// NewHeartbeatMonitor will create a new instance of heartbeat monitor +func NewHeartbeatMonitor() *heartbeatMonitor { + return &heartbeatMonitor{ + heartbeats: make([]data.PubKeyHeartbeat, 0), + } +} + +// GetHeartbeats will return the heartbeats +func (hm *heartbeatMonitor) GetHeartbeats() []data.PubKeyHeartbeat { + hm.mutex.RLock() + defer hm.mutex.RUnlock() + + return hm.heartbeats +} + +// SetHeartbeats will set the provided heartbeats +func (hm *heartbeatMonitor) SetHeartbeats(heartbeats []data.PubKeyHeartbeat) { + hm.mutex.Lock() + hm.heartbeats = heartbeats + hm.mutex.Unlock() +} + +// IsInterfaceNil returns true if there is no value under the interface +func (hm *heartbeatMonitor) IsInterfaceNil() bool { + return nil == hm +} diff --git a/node/chainSimulator/components/nodeFacade.go b/node/chainSimulator/components/nodeFacade.go index d62814fdf03..24bdc3d1ada 100644 --- a/node/chainSimulator/components/nodeFacade.go +++ b/node/chainSimulator/components/nodeFacade.go @@ -12,13 +12,15 @@ import ( "github.com/multiversx/mx-chain-go/common/forking" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/facade" + "github.com/multiversx/mx-chain-go/factory" apiComp "github.com/multiversx/mx-chain-go/factory/api" nodePack "github.com/multiversx/mx-chain-go/node" + simulatorHeartbeat "github.com/multiversx/mx-chain-go/node/chainSimulator/components/heartbeat" "github.com/multiversx/mx-chain-go/node/metrics" "github.com/multiversx/mx-chain-go/process/mock" ) -func (node *testOnlyProcessingNode) createFacade(configs config.Configs, apiInterface APIConfigurator, vmQueryDelayAfterStartInMs uint64) error { +func (node *testOnlyProcessingNode) createFacade(configs config.Configs, apiInterface APIConfigurator, vmQueryDelayAfterStartInMs uint64, monitor factory.HeartbeatV2Monitor) error { log.Debug("creating api resolver structure") err := node.createMetrics(configs) @@ -73,6 +75,13 @@ func (node *testOnlyProcessingNode) createFacade(configs config.Configs, apiInte flagsConfig := configs.FlagsConfig + heartbeatComponents, err := simulatorHeartbeat.NewSyncedHeartbeatComponents(monitor) + if err != nil { + return err + } + + node.closeHandler.AddComponent(heartbeatComponents) + nd, err := nodePack.NewNode( nodePack.WithStatusCoreComponents(node.StatusCoreComponents), nodePack.WithCoreComponents(node.CoreComponentsHolder), @@ -95,6 +104,7 @@ func (node *testOnlyProcessingNode) createFacade(configs config.Configs, apiInte nodePack.WithNodeStopChannel(node.CoreComponentsHolder.ChanStopNodeProcess()), nodePack.WithImportMode(configs.ImportDbConfig.IsImportDBMode), nodePack.WithESDTNFTStorageHandler(node.ProcessComponentsHolder.ESDTDataStorageHandlerForAPI()), + nodePack.WithHeartbeatV2Components(heartbeatComponents), ) if err != nil { return errors.New("error creating node: " + err.Error()) diff --git a/node/chainSimulator/components/statusComponents.go b/node/chainSimulator/components/statusComponents.go index be094472fc1..ab561e25c2c 100644 --- a/node/chainSimulator/components/statusComponents.go +++ b/node/chainSimulator/components/statusComponents.go @@ -9,16 +9,22 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/appStatusPolling" "github.com/multiversx/mx-chain-core-go/core/check" + nodeData "github.com/multiversx/mx-chain-core-go/data" + outportCore "github.com/multiversx/mx-chain-core-go/data/outport" factoryMarshalizer "github.com/multiversx/mx-chain-core-go/marshal/factory" indexerFactory "github.com/multiversx/mx-chain-es-indexer-go/process/factory" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/statistics" "github.com/multiversx/mx-chain-go/config" + "github.com/multiversx/mx-chain-go/epochStart" + "github.com/multiversx/mx-chain-go/epochStart/notifier" "github.com/multiversx/mx-chain-go/errors" + "github.com/multiversx/mx-chain-go/factory" "github.com/multiversx/mx-chain-go/integrationTests/mock" "github.com/multiversx/mx-chain-go/outport" - "github.com/multiversx/mx-chain-go/outport/factory" + outportFactory "github.com/multiversx/mx-chain-go/outport/factory" "github.com/multiversx/mx-chain-go/process" + "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/testscommon" ) @@ -32,10 +38,11 @@ type statusComponentsHolder struct { statusPollingIntervalSec int cancelFunc func() mutex sync.RWMutex + nodesCoordinator nodesCoordinator.NodesCoordinator } // CreateStatusComponents will create a new instance of status components holder -func CreateStatusComponents(shardID uint32, appStatusHandler core.AppStatusHandler, statusPollingIntervalSec int, external config.ExternalConfig, coreComponents process.CoreComponentsHolder) (*statusComponentsHolder, error) { +func CreateStatusComponents(shardID uint32, appStatusHandler core.AppStatusHandler, statusPollingIntervalSec int, external config.ExternalConfig, coreComponents factory.CoreComponentsHandler) (*statusComponentsHolder, error) { if check.IfNil(appStatusHandler) { return nil, core.ErrNilAppStatusHandler } @@ -51,12 +58,12 @@ func CreateStatusComponents(shardID uint32, appStatusHandler core.AppStatusHandl if err != nil { return nil, err } - instance.outportHandler, err = factory.CreateOutport(&factory.OutportFactoryArgs{ + instance.outportHandler, err = outportFactory.CreateOutport(&outportFactory.OutportFactoryArgs{ IsImportDB: false, ShardID: shardID, RetrialInterval: time.Second, HostDriversArgs: hostDriverArgs, - EventNotifierFactoryArgs: &factory.EventNotifierFactoryArgs{}, + EventNotifierFactoryArgs: &outportFactory.EventNotifierFactoryArgs{}, ElasticIndexerFactoryArgs: makeElasticIndexerArgs(external, coreComponents), }) if err != nil { @@ -65,13 +72,45 @@ func CreateStatusComponents(shardID uint32, appStatusHandler core.AppStatusHandl instance.softwareVersionChecker = &mock.SoftwareVersionCheckerMock{} instance.managedPeerMonitor = &testscommon.ManagedPeersMonitorStub{} + if shardID == core.MetachainShardId { + coreComponents.EpochStartNotifierWithConfirm().RegisterHandler(instance.epochStartEventHandler()) + } + instance.collectClosableComponents() return instance, nil } -func makeHostDriversArgs(external config.ExternalConfig) ([]factory.ArgsHostDriverFactory, error) { - argsHostDriverFactorySlice := make([]factory.ArgsHostDriverFactory, 0, len(external.HostDriversConfig)) +// SetNodesCoordinator will set the nodes coordinator +func (s *statusComponentsHolder) SetNodesCoordinator(nodesCoordinator nodesCoordinator.NodesCoordinator) { + s.mutex.Lock() + s.nodesCoordinator = nodesCoordinator + s.mutex.Unlock() +} + +func (s *statusComponentsHolder) epochStartEventHandler() epochStart.ActionHandler { + subscribeHandler := notifier.NewHandlerForEpochStart(func(hdr nodeData.HeaderHandler) { + currentEpoch := hdr.GetEpoch() + validatorsPubKeys, err := s.nodesCoordinator.GetAllEligibleValidatorsPublicKeys(currentEpoch) + if err != nil { + log.Warn("s.nodesCoordinator.GetAllEligibleValidatorPublicKeys for current epoch failed", + "epoch", currentEpoch, + "error", err.Error()) + } + + s.outportHandler.SaveValidatorsPubKeys(&outportCore.ValidatorsPubKeys{ + ShardID: hdr.GetShardID(), + ShardValidatorsPubKeys: outportCore.ConvertPubKeys(validatorsPubKeys), + Epoch: currentEpoch, + }) + + }, func(_ nodeData.HeaderHandler) {}, common.IndexerOrder) + + return subscribeHandler +} + +func makeHostDriversArgs(external config.ExternalConfig) ([]outportFactory.ArgsHostDriverFactory, error) { + argsHostDriverFactorySlice := make([]outportFactory.ArgsHostDriverFactory, 0, len(external.HostDriversConfig)) for idx := 0; idx < len(external.HostDriversConfig); idx++ { hostConfig := external.HostDriversConfig[idx] if !hostConfig.Enabled { @@ -83,7 +122,7 @@ func makeHostDriversArgs(external config.ExternalConfig) ([]factory.ArgsHostDriv return argsHostDriverFactorySlice, err } - argsHostDriverFactorySlice = append(argsHostDriverFactorySlice, factory.ArgsHostDriverFactory{ + argsHostDriverFactorySlice = append(argsHostDriverFactorySlice, outportFactory.ArgsHostDriverFactory{ Marshaller: marshaller, HostConfig: hostConfig, }) diff --git a/node/chainSimulator/components/testOnlyProcessingNode.go b/node/chainSimulator/components/testOnlyProcessingNode.go index 28256c4820f..8bc542f432c 100644 --- a/node/chainSimulator/components/testOnlyProcessingNode.go +++ b/node/chainSimulator/components/testOnlyProcessingNode.go @@ -37,6 +37,7 @@ type ArgsTestOnlyProcessingNode struct { ChanStopNodeProcess chan endProcess.ArgEndProcess SyncedBroadcastNetwork SyncedBroadcastNetworkHandler + Monitor factory.HeartbeatV2Monitor InitialRound int64 InitialNonce uint64 @@ -148,7 +149,8 @@ func NewTestOnlyProcessingNode(args ArgsTestOnlyProcessingNode) (*testOnlyProces } selfShardID := instance.GetShardCoordinator().SelfId() - instance.StatusComponentsHolder, err = CreateStatusComponents( + + statusComponentsH, err := CreateStatusComponents( selfShardID, instance.StatusCoreComponents.AppStatusHandler(), args.Configs.GeneralConfig.GeneralSettings.StatusPollingIntervalSec, @@ -159,6 +161,8 @@ func NewTestOnlyProcessingNode(args ArgsTestOnlyProcessingNode) (*testOnlyProces return nil, err } + instance.StatusComponentsHolder = statusComponentsH + err = instance.createBlockChain(selfShardID) if err != nil { return nil, err @@ -184,6 +188,8 @@ func NewTestOnlyProcessingNode(args ArgsTestOnlyProcessingNode) (*testOnlyProces return nil, err } + statusComponentsH.SetNodesCoordinator(instance.NodesCoordinator) + instance.DataComponentsHolder, err = CreateDataComponents(ArgsDataComponentsHolder{ Chain: instance.ChainHandler, StorageService: instance.StoreService, @@ -235,7 +241,7 @@ func NewTestOnlyProcessingNode(args ArgsTestOnlyProcessingNode) (*testOnlyProces return nil, err } - err = instance.createFacade(args.Configs, args.APIInterface, args.VmQueryDelayAfterStartInMs) + err = instance.createFacade(args.Configs, args.APIInterface, args.VmQueryDelayAfterStartInMs, args.Monitor) if err != nil { return nil, err } diff --git a/node/chainSimulator/components/testOnlyProcessingNode_test.go b/node/chainSimulator/components/testOnlyProcessingNode_test.go index c363ca8019c..801c11585e9 100644 --- a/node/chainSimulator/components/testOnlyProcessingNode_test.go +++ b/node/chainSimulator/components/testOnlyProcessingNode_test.go @@ -2,6 +2,7 @@ package components import ( "errors" + "github.com/multiversx/mx-chain-go/node/chainSimulator/components/heartbeat" "math/big" "strings" "testing" @@ -44,6 +45,7 @@ func createMockArgsTestOnlyProcessingNode(t *testing.T) ArgsTestOnlyProcessingNo SyncedBroadcastNetwork: NewSyncedBroadcastNetwork(), ChanStopNodeProcess: make(chan endProcess.ArgEndProcess), APIInterface: api.NewNoApiInterface(), + Monitor: heartbeat.NewHeartbeatMonitor(), ShardIDStr: "0", RoundDurationInMillis: 6000, MinNodesMeta: 1, diff --git a/node/chainSimulator/process/interface.go b/node/chainSimulator/process/interface.go index 47f937fb97c..7ae2f07517e 100644 --- a/node/chainSimulator/process/interface.go +++ b/node/chainSimulator/process/interface.go @@ -5,6 +5,7 @@ import ( "github.com/multiversx/mx-chain-go/api/shared" "github.com/multiversx/mx-chain-go/consensus" "github.com/multiversx/mx-chain-go/factory" + "github.com/multiversx/mx-chain-go/heartbeat/data" "github.com/multiversx/mx-chain-go/node/chainSimulator/dtos" "github.com/multiversx/mx-chain-go/sharding" ) @@ -28,3 +29,9 @@ type NodeHandler interface { Close() error IsInterfaceNil() bool } + +// HeartbeatMonitorWithSet defines what a heartbeat monitor with set should be able to do +type HeartbeatMonitorWithSet interface { + SetHeartbeats(heartbeats []data.PubKeyHeartbeat) + IsInterfaceNil() bool +} diff --git a/node/chainSimulator/process/processor.go b/node/chainSimulator/process/processor.go index d8f225bfde8..1c9819e27f0 100644 --- a/node/chainSimulator/process/processor.go +++ b/node/chainSimulator/process/processor.go @@ -1,10 +1,13 @@ package process import ( + "time" + "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/consensus/spos" + heartbeatData "github.com/multiversx/mx-chain-go/heartbeat/data" "github.com/multiversx/mx-chain-go/node/chainSimulator/configs" logger "github.com/multiversx/mx-chain-logger-go" ) @@ -17,16 +20,18 @@ type manualRoundHandler interface { type blocksCreator struct { nodeHandler NodeHandler + monitor HeartbeatMonitorWithSet } // NewBlocksCreator will create a new instance of blocksCreator -func NewBlocksCreator(nodeHandler NodeHandler) (*blocksCreator, error) { +func NewBlocksCreator(nodeHandler NodeHandler, monitor HeartbeatMonitorWithSet) (*blocksCreator, error) { if check.IfNil(nodeHandler) { return nil, ErrNilNodeHandler } return &blocksCreator{ nodeHandler: nodeHandler, + monitor: monitor, }, nil } @@ -123,6 +128,11 @@ func (creator *blocksCreator) CreateNewBlock() error { return err } + err = creator.setHeartBeat(header) + if err != nil { + return err + } + miniBlocks, transactions, err := bp.MarshalizedDataToBroadcast(header, block) if err != nil { return err @@ -141,6 +151,32 @@ func (creator *blocksCreator) CreateNewBlock() error { return creator.nodeHandler.GetBroadcastMessenger().BroadcastTransactions(transactions, blsKey.PubKey()) } +func (creator *blocksCreator) setHeartBeat(header data.HeaderHandler) error { + if !header.IsStartOfEpochBlock() { + return nil + } + + validators := creator.nodeHandler.GetProcessComponents().ValidatorsProvider().GetLatestValidators() + + var heartbeats []heartbeatData.PubKeyHeartbeat + for key, validator := range validators { + heartbeats = append(heartbeats, heartbeatData.PubKeyHeartbeat{ + PublicKey: key, + TimeStamp: time.Now(), + IsActive: true, + NumInstances: 1, + ComputedShardID: creator.nodeHandler.GetShardCoordinator().SelfId(), + ReceivedShardID: validator.ShardId, + }) + } + + if len(heartbeats) > 0 { + creator.monitor.SetHeartbeats(heartbeats) + } + + return nil +} + func (creator *blocksCreator) getPreviousHeaderData() (nonce, round uint64, prevHash, prevRandSeed []byte, epoch uint32) { currentHeader := creator.nodeHandler.GetChainHandler().GetCurrentBlockHeader() diff --git a/node/chainSimulator/process/processor_test.go b/node/chainSimulator/process/processor_test.go index 80ffd568134..84a93eea028 100644 --- a/node/chainSimulator/process/processor_test.go +++ b/node/chainSimulator/process/processor_test.go @@ -14,6 +14,7 @@ import ( mockConsensus "github.com/multiversx/mx-chain-go/consensus/mock" "github.com/multiversx/mx-chain-go/factory" "github.com/multiversx/mx-chain-go/integrationTests/mock" + "github.com/multiversx/mx-chain-go/node/chainSimulator/components/heartbeat" chainSimulatorProcess "github.com/multiversx/mx-chain-go/node/chainSimulator/process" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/sharding" @@ -35,14 +36,14 @@ func TestNewBlocksCreator(t *testing.T) { t.Run("nil node handler should error", func(t *testing.T) { t.Parallel() - creator, err := chainSimulatorProcess.NewBlocksCreator(nil) + creator, err := chainSimulatorProcess.NewBlocksCreator(nil, heartbeat.NewHeartbeatMonitor()) require.Equal(t, chainSimulatorProcess.ErrNilNodeHandler, err) require.Nil(t, creator) }) t.Run("should work", func(t *testing.T) { t.Parallel() - creator, err := chainSimulatorProcess.NewBlocksCreator(&chainSimulator.NodeHandlerMock{}) + creator, err := chainSimulatorProcess.NewBlocksCreator(&chainSimulator.NodeHandlerMock{}, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) require.NotNil(t, creator) }) @@ -51,10 +52,10 @@ func TestNewBlocksCreator(t *testing.T) { func TestBlocksCreator_IsInterfaceNil(t *testing.T) { t.Parallel() - creator, _ := chainSimulatorProcess.NewBlocksCreator(nil) + creator, _ := chainSimulatorProcess.NewBlocksCreator(nil, heartbeat.NewHeartbeatMonitor()) require.True(t, creator.IsInterfaceNil()) - creator, _ = chainSimulatorProcess.NewBlocksCreator(&chainSimulator.NodeHandlerMock{}) + creator, _ = chainSimulatorProcess.NewBlocksCreator(&chainSimulator.NodeHandlerMock{}, heartbeat.NewHeartbeatMonitor()) require.False(t, creator.IsInterfaceNil()) } @@ -86,7 +87,7 @@ func TestBlocksCreator_IncrementRound(t *testing.T) { } }, } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) creator.IncrementRound() @@ -119,7 +120,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -227,7 +228,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -246,7 +247,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -267,7 +268,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -319,7 +320,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -340,7 +341,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -361,7 +362,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -382,7 +383,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -521,7 +522,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { }, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -530,7 +531,7 @@ func TestBlocksCreator_CreateNewBlock(t *testing.T) { t.Run("should work", func(t *testing.T) { t.Parallel() - creator, err := chainSimulatorProcess.NewBlocksCreator(getNodeHandler()) + creator, err := chainSimulatorProcess.NewBlocksCreator(getNodeHandler(), heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock() @@ -547,7 +548,7 @@ func testCreateNewBlock(t *testing.T, blockProcess process.BlockProcessor, expec NodesCoord: nc, } } - creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler) + creator, err := chainSimulatorProcess.NewBlocksCreator(nodeHandler, heartbeat.NewHeartbeatMonitor()) require.NoError(t, err) err = creator.CreateNewBlock()