From 51b3451d192ab24bb8f48ce42c04db23ffc7f37c Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 17 Dec 2025 16:31:12 +0200 Subject: [PATCH 01/26] save intermediate header to storage on bootstrap --- epochStart/bootstrap/metaStorageHandler.go | 21 +++++++ epochStart/bootstrap/process.go | 62 ++++++++++++++++--- epochStart/bootstrap/process_test.go | 9 ++- epochStart/bootstrap/shardStorageHandler.go | 13 +++- epochStart/bootstrap/startInEpochScheduled.go | 7 +++ process/block/metablockProposal.go | 6 ++ 6 files changed, 106 insertions(+), 12 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index 6c735aecd2d..6a420681a06 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -104,6 +104,11 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor return err } + err = msh.saveEpochStartMetaHdrs(components) + if err != nil { + return err + } + msh.saveMiniblocksFromComponents(components) miniBlocks, err := msh.groupMiniBlocksByShard(components.PendingMiniBlocks) @@ -163,6 +168,22 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor return nil } +func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeededForBootstrap) error { + for _, hdr := range components.Headers { + isForCurrentShard := hdr.GetShardID() == msh.shardCoordinator.SelfId() + if !isForCurrentShard { + continue + } + + _, err := msh.saveMetaHdrToStorage(hdr) + if err != nil { + return err + } + } + + return nil +} + func (msh *metaStorageHandler) saveLastCrossNotarizedHeaders( meta data.MetaHeaderHandler, mapHeaders map[string]data.HeaderHandler, diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 473820f478a..cdd0cb3d108 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -691,6 +691,19 @@ func (e *epochStartBootstrap) createSyncers() error { } func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (map[string]data.HeaderHandler, error) { + log.Debug("syncHeadersV3From meta", + "nonce", meta.GetNonce(), + ) + for _, epochStartData := range meta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { + log.Debug("syncHeadersV3From", + "headerHash", epochStartData.GetHeaderHash(), + "shardID", epochStartData.GetShardID(), + "round", epochStartData.GetRound(), + "nonce", epochStartData.GetNonce(), + "rootHash", epochStartData.GetRootHash(), + ) + } + syncedHeaders := make(map[string]data.HeaderHandler) for _, epochStartData := range meta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { err := e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetHeaderHash(), epochStartData.GetShardID()) @@ -718,19 +731,23 @@ func (e *epochStartBootstrap) syncEpochStartMetaHeaders( hashesToRequest [][]byte, shardIds []uint32, ) (map[string]data.HeaderHandler, error) { - if meta.GetEpoch() > e.startEpoch+1 { // no need to request genesis block - hashesToRequest = append(hashesToRequest, meta.GetEpochStartHandler().GetEconomicsHandler().GetPrevEpochStartHash()) - shardIds = append(shardIds, core.MetachainShardId) + epochStartMetaHash, err := core.CalculateHash(e.coreComponentsHolder.InternalMarshalizer(), e.coreComponentsHolder.Hasher(), meta) + if err != nil { + return nil, err } - epochStartMetaHash, err := core.CalculateHash(e.coreComponentsHolder.InternalMarshalizer(), e.coreComponentsHolder.Hasher(), meta) + // sync meta header with intermediate blocks up to last executed (for supernova) + syncedHeaders := make(map[string]data.HeaderHandler) + err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartMetaHash, meta.GetShardID()) if err != nil { return nil, err } - // add the epoch start meta hash to the list to sync its proof - hashesToRequest = append(hashesToRequest, epochStartMetaHash) - shardIds = append(shardIds, core.MetachainShardId) + // sync also the other meta related headers, as before supernova + if meta.GetEpoch() > e.startEpoch+1 { // no need to request genesis block + hashesToRequest = append(hashesToRequest, meta.GetEpochStartHandler().GetEconomicsHandler().GetPrevEpochStartHash()) + shardIds = append(shardIds, core.MetachainShardId) + } ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeToWaitForRequestedData) err = e.headersSyncer.SyncMissingHeadersByHash(shardIds, hashesToRequest, ctx) @@ -739,7 +756,7 @@ func (e *epochStartBootstrap) syncEpochStartMetaHeaders( return nil, err } - syncedHeaders, err := e.headersSyncer.GetHeaders() + syncedHeaders, err = e.headersSyncer.GetHeaders() if err != nil { return nil, err } @@ -795,6 +812,12 @@ func (e *epochStartBootstrap) requestIntermediateBlocksIfNeeded( baseHeaderNonce := header.GetNonce() lastExecutedNonce := lastExecutionResult.GetHeaderNonce() + log.Debug("requestIntermediateBlocksIfNeeded", + "headerHash", headerHash, + "lastExecutedNonce", lastExecutedNonce, + "baseHeaderNonce", baseHeaderNonce, + ) + if lastExecutedNonce >= baseHeaderNonce { return nil } @@ -802,6 +825,11 @@ func (e *epochStartBootstrap) requestIntermediateBlocksIfNeeded( headerHashToSync := header.GetPrevHash() currentNonce := baseHeaderNonce for currentNonce > lastExecutedNonce { + log.Debug("requestIntermediateBlocksIfNeeded", + "headerHashToSync", headerHashToSync, + "currentNonce", currentNonce, + ) + syncedHeader, err := e.syncOneHeader(headerHashToSync, shardID) if err != nil { return err @@ -852,6 +880,11 @@ func (e *epochStartBootstrap) requestAndProcessing() (Parameters, error) { } log.Debug("start in epoch bootstrap: got shard headers and previous epoch start meta block") + log.Debug("requestAndProcessing: syncedHeaders") + for hash := range e.syncedHeaders { + log.Debug("requestAndProcessing", "hash", hash) + } + prevEpochStartMetaHash := e.epochStartMeta.GetEpochStartHandler().GetEconomicsHandler().GetPrevEpochStartHash() prevEpochStartMeta, ok := e.syncedHeaders[string(prevEpochStartMetaHash)].(data.MetaHeaderHandler) if !ok { @@ -1130,6 +1163,12 @@ func (e *epochStartBootstrap) requestAndProcessForShard(peerMiniBlocks []*block. return err } + log.Debug("requestAndProcessForShard", + "headerHash", epochStartData.GetHeaderHash(), + "nonce", epochStartData.GetNonce(), + "rootHash", epochStartData.GetRootHash(), + ) + ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeToWaitForRequestedData) err = e.miniBlocksSyncer.SyncPendingMiniBlocks(epochStartData.GetPendingMiniBlockHeaderHandlers(), ctx) cancel() @@ -1266,6 +1305,13 @@ func (e *epochStartBootstrap) getDataToSync( epochStartData data.EpochStartShardDataHandler, shardNotarizedHeader data.ShardHeaderHandler, ) (*dataToSync, error) { + log.Debug("epochStartBootstrap.getDataToSync", + "epochStartData.HeaderHash", epochStartData.GetHeaderHash(), + "epochStartData.Nonce", epochStartData.GetNonce(), + "epochStartData.RootHash", epochStartData.GetRootHash(), + "shardNotarizedHeader.Nonce", shardNotarizedHeader.GetNonce(), + ) + var err error e.storerScheduledSCRs, err = e.storageOpenerHandler.OpenDB( e.generalConfig.ScheduledSCRsStorage.DB, diff --git a/epochStart/bootstrap/process_test.go b/epochStart/bootstrap/process_test.go index 8a6ac7d7871..fbda8b708ec 100644 --- a/epochStart/bootstrap/process_test.go +++ b/epochStart/bootstrap/process_test.go @@ -2878,9 +2878,10 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { hdrHash1 := []byte("hdrHash1") hdrHash2 := []byte("hdrHash2") + hdrHash3 := []byte("hdrHash3") header1 := &block.HeaderV3{ - Nonce: 11, + Nonce: 12, PrevHash: hdrHash2, LastExecutionResult: &block.ExecutionResultInfo{ ExecutionResult: &block.BaseExecutionResult{ @@ -2889,6 +2890,11 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { }, } header2 := &block.HeaderV3{ + Nonce: 11, + PrevHash: hdrHash3, + LastExecutionResult: &block.ExecutionResultInfo{}, + } + header3 := &block.HeaderV3{ Nonce: 10, LastExecutionResult: &block.ExecutionResultInfo{}, } @@ -2905,6 +2911,7 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { return map[string]data.HeaderHandler{ string(hdrHash1): header1, string(hdrHash2): header2, + string(hdrHash3): header3, }, nil }, } diff --git a/epochStart/bootstrap/shardStorageHandler.go b/epochStart/bootstrap/shardStorageHandler.go index a15ff743f16..400cc6934d5 100644 --- a/epochStart/bootstrap/shardStorageHandler.go +++ b/epochStart/bootstrap/shardStorageHandler.go @@ -83,6 +83,11 @@ func (ssh *shardStorageHandler) CloseStorageService() { // SaveDataToStorage will save the fetched data to storage, so it will be used by the storage bootstrap component func (ssh *shardStorageHandler) SaveDataToStorage(components *ComponentsNeededForBootstrap, notarizedShardHeader data.HeaderHandler, withScheduled bool, syncedMiniBlocks map[string]*block.MiniBlock) error { + log.Debug("SaveDataToStorage: syncedHeaders") + for hash := range components.Headers { + log.Debug("SaveDataToStorage", "hash", hash) + } + bootStorer, err := ssh.storageService.GetStorer(dataRetriever.BootstrapUnit) if err != nil { return err @@ -183,9 +188,11 @@ func (ssh *shardStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNee func (ssh *shardStorageHandler) saveEpochStartShardHdrs(components *ComponentsNeededForBootstrap) error { for _, hdr := range components.Headers { - if !hdr.IsStartOfEpochBlock() { - continue - } + // not only start of epoch header have to be saved at this point, we should save + // also intermediate headers up to last executed header + // if !hdr.IsStartOfEpochBlock() { + // continue + // } isForCurrentShard := hdr.GetShardID() == ssh.shardCoordinator.SelfId() if !isForCurrentShard { diff --git a/epochStart/bootstrap/startInEpochScheduled.go b/epochStart/bootstrap/startInEpochScheduled.go index 265cf4dcc72..7a5f3b05b87 100644 --- a/epochStart/bootstrap/startInEpochScheduled.go +++ b/epochStart/bootstrap/startInEpochScheduled.go @@ -90,6 +90,9 @@ func (ses *startInEpochWithScheduledDataSyncer) IsInterfaceNil() bool { func (ses *startInEpochWithScheduledDataSyncer) getRequiredHeaderByHash( notarizedShardHeader data.ShardHeaderHandler, ) (data.ShardHeaderHandler, map[string]data.HeaderHandler, error) { + // TODO: analize the requested headers in this func, after andromeda commited blocks are final + // it might not be needed to request based on prev header + shardIDs, hashesToRequest := getShardIDAndHashesForIncludedMetaBlocks(notarizedShardHeader) shardIDs = append(shardIDs, notarizedShardHeader.GetShardID()) @@ -145,6 +148,10 @@ func (ses *startInEpochWithScheduledDataSyncer) getRequiredHeaderByHash( } } + if notarizedShardHeader.IsHeaderV3() { + headerToBeProcessed = notarizedShardHeader + } + return headerToBeProcessed, headers, nil } diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index cbd523e882b..5b00f2a16f5 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -995,6 +995,12 @@ func (mp *metaProcessor) checkShardInfoValidity(metaHeaderHandler data.MetaHeade for i := 0; i < len(headerShardInfo); i++ { if !headerShardInfo[i].Equal(createdShardInfo[i]) { + log.Debug("checkShardInfoValidity", + "hsi hash", headerShardInfo[i].GetHeaderHash(), + "hsi nonce", headerShardInfo[i].GetNonce(), + "csi hash", createdShardInfo[i].GetHeaderHash(), + "csi nonce", createdShardInfo[i].GetNonce(), + ) return fmt.Errorf("%w for shardInfo item %d", process.ErrHeaderShardDataMismatch, i) } } From 187313c641dd101f922c67900ff592e18ec3897a Mon Sep 17 00:00:00 2001 From: ssd04 Date: Thu, 18 Dec 2025 14:27:44 +0200 Subject: [PATCH 02/26] handle last included meta headers --- epochStart/bootstrap/baseStorageHandler.go | 6 +++ epochStart/bootstrap/metaStorageHandler.go | 50 ++++++++++++++++++- epochStart/bootstrap/process.go | 10 ++++ process/block/metablockProposal.go | 18 +++++++ process/block/shardInfo.go | 19 ++++++- process/sync/baseSync.go | 39 ++++++++++++++- .../metaStorageBootstrapper.go | 3 ++ process/track/blockNotarizer.go | 29 +++++++++++ 8 files changed, 170 insertions(+), 4 deletions(-) diff --git a/epochStart/bootstrap/baseStorageHandler.go b/epochStart/bootstrap/baseStorageHandler.go index f0abdd78257..f37d82d920a 100644 --- a/epochStart/bootstrap/baseStorageHandler.go +++ b/epochStart/bootstrap/baseStorageHandler.go @@ -176,6 +176,12 @@ func (bsh *baseStorageHandler) saveMetaHdrToStorage(metaBlock data.HeaderHandler headerHash := bsh.hasher.Compute(string(headerBytes)) + log.Debug("saveMetaHdrToStorage", + "hash", headerHash, + "nonce", metaBlock.GetNonce(), + "round", metaBlock.GetRound(), + ) + metaHdrStorage, err := bsh.storageService.GetStorer(dataRetriever.MetaBlockUnit) if err != nil { return nil, err diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index 6a420681a06..a97a04bd0a4 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -131,10 +131,40 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor return err } + epochStartMeta := components.EpochStartMetaBlock + lastSelfNotarizedHeaders := []bootstrapStorage.BootstrapHeaderInfo{lastHeader} + if epochStartMeta.IsHeaderV3() { + for _, epochStartData := range epochStartMeta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { + headerHash := epochStartData.GetLastFinishedMetaBlock() + header, ok := components.Headers[string(headerHash)] + if !ok { + log.Error("should be able to find header", + "hash", headerHash, + "shardID", epochStartData.GetShardID(), + ) + return epochStart.ErrMissingHeader + } + + bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ + ShardId: epochStartData.GetShardID(), + Epoch: header.GetEpoch(), + Nonce: header.GetNonce(), + Hash: headerHash, + } + + log.Debug("SaveDataToStorage", + "LastFinishedMetaBlock: hash", headerHash, + "shard", epochStartData.GetShardID(), + ) + + lastSelfNotarizedHeaders = append([]bootstrapStorage.BootstrapHeaderInfo{bootstrapHdrInfo}, lastSelfNotarizedHeaders...) + } + } + bootStrapData := bootstrapStorage.BootstrapData{ LastHeader: lastHeader, LastCrossNotarizedHeaders: lastCrossNotarizedHeaders, - LastSelfNotarizedHeaders: []bootstrapStorage.BootstrapHeaderInfo{lastHeader}, + LastSelfNotarizedHeaders: lastSelfNotarizedHeaders, ProcessedMiniBlocks: []bootstrapStorage.MiniBlocksInMeta{}, PendingMiniBlocks: miniBlocks, NodesCoordinatorConfigKey: nodesCoordinatorConfigKey, @@ -169,9 +199,19 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor } func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeededForBootstrap) error { - for _, hdr := range components.Headers { + for hash, hdr := range components.Headers { isForCurrentShard := hdr.GetShardID() == msh.shardCoordinator.SelfId() if !isForCurrentShard { + log.Debug("not for curr shard", + "hash", hash, + "shard", hdr.GetShardID(), + "nonce", hdr.GetNonce(), + ) + _, err := msh.saveShardHdrToStorage(hdr) + if err != nil { + return err + } + continue } @@ -179,6 +219,12 @@ func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeed if err != nil { return err } + + log.Debug("saved header", + "hash", hash, + "shard", hdr.GetShardID(), + "nonce", hdr.GetNonce(), + ) } return nil diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index cdd0cb3d108..3ba30d56d5d 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -714,6 +714,16 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma hashesToRequest := make([][]byte, 0) shardIds := make([]uint32, 0) + for _, epochStartData := range meta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { + err := e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetHeaderHash(), epochStartData.GetShardID()) + if err != nil { + return nil, err + } + + hashesToRequest = append(hashesToRequest, epochStartData.GetLastFinishedMetaBlock()) + shardIds = append(shardIds, core.MetachainShardId) + } + syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) if err != nil { return nil, err diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 5b00f2a16f5..0cfdef3432f 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -998,9 +998,27 @@ func (mp *metaProcessor) checkShardInfoValidity(metaHeaderHandler data.MetaHeade log.Debug("checkShardInfoValidity", "hsi hash", headerShardInfo[i].GetHeaderHash(), "hsi nonce", headerShardInfo[i].GetNonce(), + "hsi lastIncludedMetaNonce", headerShardInfo[i].GetLastIncludedMetaNonce(), + "hsi mbs", headerShardInfo[i].GetShardMiniBlockHeaderHandlers(), + "hsi mbs", headerShardInfo[i], "csi hash", createdShardInfo[i].GetHeaderHash(), "csi nonce", createdShardInfo[i].GetNonce(), + "csi lastIncludedMetaNonce", createdShardInfo[i].GetLastIncludedMetaNonce(), + "csi mbs", createdShardInfo[i].GetShardMiniBlockHeaderHandlers(), + "csi mbs", createdShardInfo[i], ) + + for _, mb := range headerShardInfo[i].GetShardMiniBlockHeaderHandlers() { + log.Debug("checkShardInfoValidity.headerShardInfo", + "hash", mb.GetHash(), + ) + } + for _, mb := range createdShardInfo[i].GetShardMiniBlockHeaderHandlers() { + log.Debug("checkShardInfoValidity.createdShardInfo", + "hash", mb.GetHash(), + ) + } + return fmt.Errorf("%w for shardInfo item %d", process.ErrHeaderShardDataMismatch, i) } } diff --git a/process/block/shardInfo.go b/process/block/shardInfo.go index 8be1cf2a05e..42e249b9107 100644 --- a/process/block/shardInfo.go +++ b/process/block/shardInfo.go @@ -203,6 +203,12 @@ func (sic *ShardInfoCreateData) createShardDataFromV3Header( return nil, nil, err } shardDataHandlers[i] = shardData + + log.Debug("createShardDataFromV3Header", + "shardHeader", shardHeader.GetNonce(), + "hash", shardData.GetHeaderHash(), + "lastIncludedMetaNonce", shardData.GetLastIncludedMetaNonce(), + ) } return shardDataProposal, shardDataHandlers, nil @@ -316,10 +322,21 @@ func (sic *ShardInfoCreateData) updateShardDataWithCrossShardInfo(shardData *blo shardData.NumPendingMiniBlocks = uint32(len(sic.pendingMiniBlocksHandler.GetPendingMiniBlocks(header.GetShardID()))) } - metaHeader, _, err := sic.blockTracker.GetLastSelfNotarizedHeader(header.GetShardID()) + metaHeader, metaHash, err := sic.blockTracker.GetLastSelfNotarizedHeader(header.GetShardID()) if err != nil { return err } + + log.Debug("updateShardDataWithCrossShardInfo", + "hash", shardData.GetHeaderHash(), + "shard", header.GetShardID(), + "meta hash", metaHash, + "shard", header.GetShardID(), + "meta shard", metaHeader.GetShardID(), + "nonce", metaHeader.GetNonce(), + "round", metaHeader.GetRound(), + ) + shardData.LastIncludedMetaNonce = metaHeader.GetNonce() return nil diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index a22e6cc84ae..4c112669784 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -1121,7 +1121,7 @@ func (boot *baseBootstrap) prepareForSyncIfNeeded(syncingNonce uint64) error { // if there are multiple headers in between the syncing header and the last one executed, // add them into the queue and pool for i := lastExecutedNonce + 1; i < syncingNonce; i++ { - hdr, hdrHash, errGetHdr := boot.getHeaderFromPoolWithNonce(i) + hdr, hdrHash, errGetHdr := boot.getHeaderWithNonce(i) if errGetHdr != nil { log.Debug("prepareForSyncIfNeeded: failed to get header with nonce", "nonce", i, "error", errGetHdr) return errGetHdr @@ -1774,6 +1774,43 @@ func (boot *baseBootstrap) getHeaderFromPool(hash []byte) (data.HeaderHandler, e return process.GetShardHeaderFromPool(hash, boot.headers) } +func (boot *baseBootstrap) getHeaderWithNonce( + nonce uint64, +) (data.HeaderHandler, []byte, error) { + if boot.shardCoordinator.SelfId() == core.MetachainShardId { + header, hash, err := process.GetMetaHeaderFromPoolWithNonce(nonce, boot.headers) + if err != nil { + header, hash, err = process.GetMetaHeaderFromStorageWithNonce( + nonce, + boot.store, + boot.uint64Converter, + boot.marshalizer, + ) + if err != nil { + return nil, nil, err + } + } + + return header, hash, nil + } + + header, hash, err := process.GetShardHeaderFromPoolWithNonce(nonce, boot.shardCoordinator.SelfId(), boot.headers) + if err != nil { + header, hash, err = process.GetShardHeaderFromStorageWithNonce( + nonce, + boot.shardCoordinator.SelfId(), + boot.store, + boot.uint64Converter, + boot.marshalizer, + ) + if err != nil { + return nil, nil, err + } + } + + return header, hash, nil +} + func (boot *baseBootstrap) getHeaderFromPoolWithNonce( nonce uint64, ) (data.HeaderHandler, []byte, error) { diff --git a/process/sync/storageBootstrap/metaStorageBootstrapper.go b/process/sync/storageBootstrap/metaStorageBootstrapper.go index 328d6f5023b..40305d6e677 100644 --- a/process/sync/storageBootstrap/metaStorageBootstrapper.go +++ b/process/sync/storageBootstrap/metaStorageBootstrapper.go @@ -160,6 +160,9 @@ func (msb *metaStorageBootstrapper) cleanupNotarizedStorageForHigherNoncesIfExis func (msb *metaStorageBootstrapper) applySelfNotarizedHeaders( bootstrapHeadersInfo []bootstrapStorage.BootstrapHeaderInfo, ) ([]data.HeaderHandler, [][]byte, error) { + log.Debug("applySelfNotarizedHeaders", + "len boot", len(bootstrapHeadersInfo), + ) for _, bootstrapHeaderInfo := range bootstrapHeadersInfo { selfNotarizedHeader, err := msb.getHeader(bootstrapHeaderInfo.Hash) diff --git a/process/track/blockNotarizer.go b/process/track/blockNotarizer.go index 6520d3ff810..e236aa0d2d2 100644 --- a/process/track/blockNotarizer.go +++ b/process/track/blockNotarizer.go @@ -66,6 +66,21 @@ func (bn *blockNotarizer) AddNotarizedHeader( return bn.notarizedHeaders[shardID][i].Header.GetNonce() < bn.notarizedHeaders[shardID][j].Header.GetNonce() }) bn.mutNotarizedHeaders.Unlock() + + bn.mutNotarizedHeaders.Lock() + for shard, hdrs := range bn.notarizedHeaders { + log.Debug("AddNotarizedHeader", + "shard", shard, + ) + for _, hdr := range hdrs { + log.Debug("AddNotarizedHeader", + "hash", hdr.Hash, + "nonce", hdr.Header.GetNonce(), + "round", hdr.Header.GetRound(), + ) + } + } + bn.mutNotarizedHeaders.Unlock() } // CleanupNotarizedHeadersBehindNonce cleanups notarized headers for a given shard behind a given nonce @@ -155,6 +170,20 @@ func (bn *blockNotarizer) GetLastNotarizedHeader(shardID uint32) (data.HeaderHan bn.mutNotarizedHeaders.RLock() defer bn.mutNotarizedHeaders.RUnlock() + // for shard, hdrs := range bn.notarizedHeaders { + // log.Debug("GetLastNotarizedHeader", + // "shardID", shardID, + // "shard", shard, + // ) + // for _, hdr := range hdrs { + // log.Debug("GetLastNotarizedHeader", + // "hash", hdr.Hash, + // "nonce", hdr.Header.GetNonce(), + // "round", hdr.Header.GetRound(), + // ) + // } + // } + hdrInfo := bn.lastNotarizedHeaderInfo(shardID) if hdrInfo == nil { return nil, nil, process.ErrNotarizedHeadersSliceForShardIsNil From dcfc4abeb65318c674716e2a6218c80ddd91b0b1 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 19 Dec 2025 10:28:52 +0200 Subject: [PATCH 03/26] fallback to search in storage --- .../executionManager/executionManager.go | 3 +- process/block/baseProcess.go | 27 ++++++++++++++++ process/block/common.go | 31 ------------------- process/block/metablock.go | 12 ++++--- process/block/shardblock.go | 4 +-- 5 files changed, 39 insertions(+), 38 deletions(-) delete mode 100644 process/block/common.go diff --git a/process/asyncExecution/executionManager/executionManager.go b/process/asyncExecution/executionManager/executionManager.go index 35e62d35330..166c94884eb 100644 --- a/process/asyncExecution/executionManager/executionManager.go +++ b/process/asyncExecution/executionManager/executionManager.go @@ -142,7 +142,8 @@ func (em *executionManager) updateContextForReplacedHeader(header data.HeaderHan return err } - headerToSet, err := em.headers.GetHeaderByHash(executionResultToSet.GetHeaderHash()) + // TODO: optimize to add into pool at bootstrap + headerToSet, err := em.getHeaderFromPoolOrStorage(executionResultToSet.GetHeaderHash()) if err != nil { return err } diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index e16f8eed6b7..5ee1966de15 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -1664,6 +1664,12 @@ func (bp *baseProcessor) getLastSelfNotarizedHeadersForShard(shardID uint32) *bo Hash: lastSelfNotarizedHeaderHash, } + log.Debug("getLastSelfNotarizedHeadersForShard", + "shard", shardID, + "lastnot hash", lastSelfNotarizedHeaderHash, + "lastnot nonce", lastSelfNotarizedHeader.GetNonce(), + ) + return headerInfo } @@ -3763,6 +3769,27 @@ func (bp *baseProcessor) getBlockBodyFromPool( return &block.Body{MiniBlocks: miniBlocks}, nil } +func (bp *baseProcessor) getHeaderFromHash( + isHeaderV3 bool, + shardHeaderHash []byte, + shardID uint32, +) (data.HeaderHandler, error) { + if isHeaderV3 { + header, err := process.GetHeader(shardHeaderHash, bp.dataPool.Headers(), bp.store, bp.marshalizer, shardID) + if err != nil { + log.Error("getHeaderFromHash - failed to get header from headers pool", "hash", shardHeaderHash, "error", err) + } + return header, err + } + + headerInfo, ok := bp.hdrsForCurrBlock.GetHeaderInfo(string(shardHeaderHash)) + if !ok { + return nil, process.ErrMissingHeader + } + + return headerInfo.GetHeader(), nil +} + func getProposedAndExecutedMiniBlockHeaders( header data.HeaderHandler, ) ([]data.MiniBlockHeaderHandler, error) { diff --git a/process/block/common.go b/process/block/common.go deleted file mode 100644 index c50c965f729..00000000000 --- a/process/block/common.go +++ /dev/null @@ -1,31 +0,0 @@ -package block - -import ( - "github.com/multiversx/mx-chain-core-go/data" - - "github.com/multiversx/mx-chain-go/dataRetriever" - "github.com/multiversx/mx-chain-go/process" -) - -func getHeaderFromHash( - headersPool dataRetriever.HeadersPool, - hdrsForCurrBlock HeadersForBlock, - isHeaderV3 bool, - shardHeaderHash []byte, -) (data.HeaderHandler, error) { - if isHeaderV3 { - header, err := headersPool.GetHeaderByHash(shardHeaderHash) - // TODO: debug only, remove after test - if err != nil { - log.Error("getHeaderFromHash - failed to get header from headers pool", "hash", shardHeaderHash, "error", err) - } - return header, err - } - - headerInfo, ok := hdrsForCurrBlock.GetHeaderInfo(string(shardHeaderHash)) - if !ok { - return nil, process.ErrMissingHeader - } - - return headerInfo.GetHeader(), nil -} diff --git a/process/block/metablock.go b/process/block/metablock.go index d8823883aec..5a321f67e14 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -496,7 +496,7 @@ func (mp *metaProcessor) getAllMiniBlockDstMeFromShards(metaHdr data.MetaHeaderH var shardHeaderHandler data.HeaderHandler var err error for _, shardInfo := range getShardHeadersReferencedByMeta(metaHdr) { - shardHeaderHandler, err = getHeaderFromHash(mp.dataPool.Headers(), mp.hdrsForCurrBlock, metaHdr.IsHeaderV3(), shardInfo.GetHeaderHash()) + shardHeaderHandler, err = mp.getHeaderFromHash(metaHdr.IsHeaderV3(), shardInfo.GetHeaderHash(), shardInfo.GetShardID()) if err != nil { return nil, fmt.Errorf("%w : for shardInfo.HeaderHash = %s", process.ErrMissingHeader, hex.EncodeToString(shardInfo.GetHeaderHash())) @@ -1409,6 +1409,10 @@ func (mp *metaProcessor) CommitBlock( nodesCoordinatorKey := mp.nodesCoordinator.GetSavedStateKey() epochStartKey := mp.epochStartTrigger.GetSavedStateKey() + log.Debug("getLastSelfNotarizedHeaders", + "hash", headerHash, + "nonoce", header.GetNonce(), + ) args := bootStorerDataArgs{ headerInfo: headerInfo, round: header.GetRound(), @@ -1487,7 +1491,7 @@ func (mp *metaProcessor) computeFinalMetaBlock(metaBlock data.MetaHeaderHandler, func (mp *metaProcessor) updateCrossShardInfo(metaHeader data.MetaHeaderHandler) ([]string, error) { notarizedHeadersHashes := make([]string, 0) for _, shardData := range getShardHeadersReferencedByMeta(metaHeader) { - header, err := getHeaderFromHash(mp.dataPool.Headers(), mp.hdrsForCurrBlock, metaHeader.IsHeaderV3(), shardData.GetHeaderHash()) + header, err := mp.getHeaderFromHash(metaHeader.IsHeaderV3(), shardData.GetHeaderHash(), shardData.GetShardID()) if err != nil { return nil, fmt.Errorf("%w : updateCrossShardInfo shardHeaderHash = %s", err, logger.DisplayByteSlice(shardData.GetHeaderHash())) @@ -1751,7 +1755,7 @@ func (mp *metaProcessor) getLastSelfNotarizedHeaderByShard( continue } - header, err := getHeaderFromHash(mp.dataPool.Headers(), mp.hdrsForCurrBlock, metaHeader.IsHeaderV3(), shardData.GetHeaderHash()) + header, err := mp.getHeaderFromHash(metaHeader.IsHeaderV3(), shardData.GetHeaderHash(), shardData.GetShardID()) if err != nil { log.Debug("getLastSelfNotarizedHeaderByShard", "error", err.Error(), @@ -1962,7 +1966,7 @@ func (mp *metaProcessor) saveLastNotarizedHeader(metaHeader data.MetaHeaderHandl } for _, shardData := range getShardHeadersReferencedByMeta(metaHeader) { - header, err := getHeaderFromHash(mp.dataPool.Headers(), mp.hdrsForCurrBlock, metaHeader.IsHeaderV3(), shardData.GetHeaderHash()) + header, err := mp.getHeaderFromHash(metaHeader.IsHeaderV3(), shardData.GetHeaderHash(), shardData.GetShardID()) if err != nil { return fmt.Errorf("%w : saveLastNotarizedHeader shardHeaderHash = %s", err, logger.DisplayByteSlice(shardData.GetHeaderHash())) diff --git a/process/block/shardblock.go b/process/block/shardblock.go index 32084c7f4af..3e75382f2ab 100644 --- a/process/block/shardblock.go +++ b/process/block/shardblock.go @@ -1414,7 +1414,7 @@ func (sp *shardProcessor) snapShotEpochStartFromMeta(header data.ShardHeaderHand accounts := sp.accountsDB[state.UserAccountsState] for _, metaHash := range header.GetMetaBlockHashes() { - hdr, err := getHeaderFromHash(sp.dataPool.Headers(), sp.hdrsForCurrBlock, header.IsHeaderV3(), metaHash) + hdr, err := sp.getHeaderFromHash(header.IsHeaderV3(), metaHash, core.MetachainShardId) if err != nil { continue } @@ -1768,7 +1768,7 @@ func (sp *shardProcessor) addProcessedCrossMiniBlocksFromHeader(headerHandler da } for _, metaBlockHash := range shardHeader.GetMetaBlockHashes() { - hdr, err := getHeaderFromHash(sp.dataPool.Headers(), sp.hdrsForCurrBlock, shardHeader.IsHeaderV3(), metaBlockHash) + hdr, err := sp.getHeaderFromHash(shardHeader.IsHeaderV3(), metaBlockHash, core.MetachainShardId) if err != nil { return fmt.Errorf("%w : addProcessedCrossMiniBlocksFromHeader metaBlockHash = %s", err, logger.DisplayByteSlice(metaBlockHash)) From 5011943d440015a8e88dd4088d6fa969a65727fb Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 19 Dec 2025 13:17:22 +0200 Subject: [PATCH 04/26] request missing meta headers at bootstrap --- epochStart/bootstrap/fromLocalStorage.go | 4 +- epochStart/bootstrap/metaStorageHandler.go | 52 ++++++++++++++++-- epochStart/bootstrap/process.go | 64 +++++++++++++++++++++- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/epochStart/bootstrap/fromLocalStorage.go b/epochStart/bootstrap/fromLocalStorage.go index f460ad4fd66..c6ae3f5bccf 100644 --- a/epochStart/bootstrap/fromLocalStorage.go +++ b/epochStart/bootstrap/fromLocalStorage.go @@ -13,6 +13,7 @@ import ( "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/epochStart/bootstrap/disabled" + "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/block/bootstrapStorage" "github.com/multiversx/mx-chain-go/sharding" "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" @@ -288,8 +289,7 @@ func (e *epochStartBootstrap) getEpochStartMetaFromStorage(storer storage.Storer return nil, err } - metaBlock := &block.MetaBlock{} - err = e.coreComponentsHolder.InternalMarshalizer().Unmarshal(metaBlock, epochStartMetaBlock) + metaBlock, err := process.UnmarshalMetaHeader(e.coreComponentsHolder.InternalMarshalizer(), epochStartMetaBlock) if err != nil { return nil, err } diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index a97a04bd0a4..5408841f77d 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -132,8 +132,10 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor } epochStartMeta := components.EpochStartMetaBlock - lastSelfNotarizedHeaders := []bootstrapStorage.BootstrapHeaderInfo{lastHeader} - if epochStartMeta.IsHeaderV3() { + var lastSelfNotarizedHeaders []bootstrapStorage.BootstrapHeaderInfo + if !epochStartMeta.IsHeaderV3() { + lastSelfNotarizedHeaders = []bootstrapStorage.BootstrapHeaderInfo{lastHeader} + } else { for _, epochStartData := range epochStartMeta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { headerHash := epochStartData.GetLastFinishedMetaBlock() header, ok := components.Headers[string(headerHash)] @@ -145,6 +147,26 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor return epochStart.ErrMissingHeader } + // lastExecResHeader, err := common.GetLastBaseExecutionResultHandler(header) + // if err != nil { + // return err + // } + + // lastExecHeader, ok := components.Headers[string(lastExecResHeader.GetHeaderHash())] + // if !ok { + // log.Error("should be able to find last exec meta header", + // "hash", lastExecResHeader.GetHeaderHash(), + // ) + // return epochStart.ErrMissingHeader + // } + + // bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ + // ShardId: epochStartData.GetShardID(), + // Epoch: lastExecHeader.GetEpoch(), + // Nonce: lastExecHeader.GetNonce(), + // Hash: lastExecResHeader.GetHeaderHash(), + // } + bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ ShardId: epochStartData.GetShardID(), Epoch: header.GetEpoch(), @@ -153,12 +175,34 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor } log.Debug("SaveDataToStorage", - "LastFinishedMetaBlock: hash", headerHash, + "GetLastFinishedMetaBlock: hash", headerHash, "shard", epochStartData.GetShardID(), ) - lastSelfNotarizedHeaders = append([]bootstrapStorage.BootstrapHeaderInfo{bootstrapHdrInfo}, lastSelfNotarizedHeaders...) + lastSelfNotarizedHeaders = append(lastSelfNotarizedHeaders, bootstrapHdrInfo) + } + + lastExecRes, err := common.GetLastBaseExecutionResultHandler(epochStartMeta) + if err != nil { + return err + } + + lastExecMetaHeader, ok := components.Headers[string(lastExecRes.GetHeaderHash())] + if !ok { + log.Error("should be able to find last exec meta header", + "hash", lastExecRes.GetHeaderHash(), + ) + return epochStart.ErrMissingHeader + } + + bootstrapHdrInfoMeta := bootstrapStorage.BootstrapHeaderInfo{ + ShardId: core.MetachainShardId, + Epoch: lastExecMetaHeader.GetEpoch(), + Nonce: lastExecMetaHeader.GetNonce(), + Hash: lastExecRes.GetHeaderHash(), } + + lastSelfNotarizedHeaders = append(lastSelfNotarizedHeaders, bootstrapHdrInfoMeta) } bootStrapData := bootstrapStorage.BootstrapData{ diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 3ba30d56d5d..c2eaa80757a 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -720,8 +720,68 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma return nil, err } - hashesToRequest = append(hashesToRequest, epochStartData.GetLastFinishedMetaBlock()) - shardIds = append(shardIds, core.MetachainShardId) + err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) + if err != nil { + return nil, err + } + + syncedHeader, ok := syncedHeaders[string(epochStartData.GetHeaderHash())] + if !ok { + log.Error("should have been synced at this point") + return nil, epochStart.ErrMissingHeader + } + shardHeader, ok := syncedHeader.(data.ShardHeaderHandler) + if !ok { + log.Error("epoch start data shard header", + "error", process.ErrWrongTypeAssertion, + ) + return nil, epochStart.ErrWrongTypeAssertion + } + + for _, metaHash := range shardHeader.GetMetaBlockHashes() { + hashesToRequest = append(hashesToRequest, metaHash) + shardIds = append(shardIds, core.MetachainShardId) + } + + lastFinished, ok := syncedHeaders[string(epochStartData.GetLastFinishedMetaBlock())] + if !ok { + log.Error("should have been synced at this point") + return nil, epochStart.ErrMissingHeader + } + + hashToSync := meta.GetPrevHash() + currNonce := meta.GetNonce() + for currNonce > lastFinished.GetNonce() { + header, err := e.syncOneHeader(hashToSync, core.MetachainShardId) + if err != nil { + return nil, err + } + syncedHeaders[string(hashToSync)] = header + + hashToSync = header.GetPrevHash() + currNonce = header.GetNonce() + } + } + + for _, shardData := range meta.GetShardInfoProposalHandlers() { + header, err := e.syncOneHeader(shardData.GetHeaderHash(), shardData.GetShardID()) + if err != nil { + return nil, err + } + syncedHeaders[string(shardData.GetHeaderHash())] = header + + shardHeader, ok := header.(data.ShardHeaderHandler) + if !ok { + log.Error("epoch start data shard header", + "error", process.ErrWrongTypeAssertion, + ) + return nil, epochStart.ErrWrongTypeAssertion + } + + for _, metaHash := range shardHeader.GetMetaBlockHashes() { + hashesToRequest = append(hashesToRequest, metaHash) + shardIds = append(shardIds, core.MetachainShardId) + } } syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) From 3a37ddb680b8ada4152ba4f1e579d6f7a04fdbb9 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 19 Dec 2025 16:18:01 +0200 Subject: [PATCH 05/26] remove unneded log --- process/block/baseProcess.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 5ee1966de15..43677cd7d27 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -3775,11 +3775,7 @@ func (bp *baseProcessor) getHeaderFromHash( shardID uint32, ) (data.HeaderHandler, error) { if isHeaderV3 { - header, err := process.GetHeader(shardHeaderHash, bp.dataPool.Headers(), bp.store, bp.marshalizer, shardID) - if err != nil { - log.Error("getHeaderFromHash - failed to get header from headers pool", "hash", shardHeaderHash, "error", err) - } - return header, err + return process.GetHeader(shardHeaderHash, bp.dataPool.Headers(), bp.store, bp.marshalizer, shardID) } headerInfo, ok := bp.hdrsForCurrBlock.GetHeaderInfo(string(shardHeaderHash)) From bd53570521c1912fe74b5a3db30932a51ef75dcd Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 19 Dec 2025 16:18:36 +0200 Subject: [PATCH 06/26] set last self notarized meta in tracker based on shard header --- epochStart/bootstrap/metaStorageHandler.go | 77 ++++++++++++++-------- epochStart/bootstrap/process.go | 74 +++++++++++---------- 2 files changed, 91 insertions(+), 60 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index 5408841f77d..51eac8327d9 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -12,6 +12,7 @@ import ( "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/epochStart/bootstrap/disabled" + "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/block/bootstrapStorage" "github.com/multiversx/mx-chain-go/storage/factory" ) @@ -137,45 +138,69 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor lastSelfNotarizedHeaders = []bootstrapStorage.BootstrapHeaderInfo{lastHeader} } else { for _, epochStartData := range epochStartMeta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { - headerHash := epochStartData.GetLastFinishedMetaBlock() - header, ok := components.Headers[string(headerHash)] + lastFinishedMetaBlockHash := epochStartData.GetLastFinishedMetaBlock() + lastFinishedMetaBlock, ok := components.Headers[string(lastFinishedMetaBlockHash)] if !ok { log.Error("should be able to find header", - "hash", headerHash, + "hash", lastFinishedMetaBlockHash, "shardID", epochStartData.GetShardID(), ) return epochStart.ErrMissingHeader } - // lastExecResHeader, err := common.GetLastBaseExecutionResultHandler(header) - // if err != nil { - // return err - // } - - // lastExecHeader, ok := components.Headers[string(lastExecResHeader.GetHeaderHash())] - // if !ok { - // log.Error("should be able to find last exec meta header", - // "hash", lastExecResHeader.GetHeaderHash(), - // ) - // return epochStart.ErrMissingHeader - // } - - // bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ - // ShardId: epochStartData.GetShardID(), - // Epoch: lastExecHeader.GetEpoch(), - // Nonce: lastExecHeader.GetNonce(), - // Hash: lastExecResHeader.GetHeaderHash(), - // } + shardHeaderHash := epochStartData.GetHeaderHash() + shardHeader, ok := components.Headers[string(shardHeaderHash)] + if !ok { + log.Error("should be able to find header", + "hash", lastFinishedMetaBlockHash, + "shardID", epochStartData.GetShardID(), + ) + return epochStart.ErrMissingHeader + } + + shardHeaderHandler, ok := shardHeader.(data.ShardHeaderHandler) + if !ok { + log.Error("epoch start data shard header", + "error", process.ErrWrongTypeAssertion, + ) + return epochStart.ErrWrongTypeAssertion + } + + if len(shardHeaderHandler.GetMetaBlockHashes()) > 0 { + metaHash := shardHeaderHandler.GetMetaBlockHashes()[0] + metaHeader0, ok := components.Headers[string(metaHash)] + if !ok { + log.Error("should be able to find header", + "hash", metaHash, + "shardID", epochStartData.GetShardID(), + ) + return epochStart.ErrMissingHeader + } + + prevHash := metaHeader0.GetPrevHash() + + metaHeader1, ok := components.Headers[string(prevHash)] + if !ok { + log.Error("should be able to find header", + "hash", prevHash, + "shardID", epochStartData.GetShardID(), + ) + return epochStart.ErrMissingHeader + } + + lastFinishedMetaBlockHash = prevHash + lastFinishedMetaBlock = metaHeader1 + } bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ ShardId: epochStartData.GetShardID(), - Epoch: header.GetEpoch(), - Nonce: header.GetNonce(), - Hash: headerHash, + Epoch: lastFinishedMetaBlock.GetEpoch(), + Nonce: lastFinishedMetaBlock.GetNonce(), + Hash: lastFinishedMetaBlockHash, } log.Debug("SaveDataToStorage", - "GetLastFinishedMetaBlock: hash", headerHash, + "GetLastFinishedMetaBlock: hash", lastFinishedMetaBlockHash, "shard", epochStartData.GetShardID(), ) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index c2eaa80757a..5e3a719c127 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -705,12 +705,6 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma } syncedHeaders := make(map[string]data.HeaderHandler) - for _, epochStartData := range meta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { - err := e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetHeaderHash(), epochStartData.GetShardID()) - if err != nil { - return nil, err - } - } hashesToRequest := make([][]byte, 0) shardIds := make([]uint32, 0) @@ -720,11 +714,6 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma return nil, err } - err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) - if err != nil { - return nil, err - } - syncedHeader, ok := syncedHeaders[string(epochStartData.GetHeaderHash())] if !ok { log.Error("should have been synced at this point") @@ -738,9 +727,26 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma return nil, epochStart.ErrWrongTypeAssertion } - for _, metaHash := range shardHeader.GetMetaBlockHashes() { - hashesToRequest = append(hashesToRequest, metaHash) - shardIds = append(shardIds, core.MetachainShardId) + // if thare notarized meta headers, sync their previous meta header + if len(shardHeader.GetMetaBlockHashes()) > 0 { + metaHash := shardHeader.GetMetaBlockHashes()[0] + header, err := e.syncOneHeader(metaHash, core.MetachainShardId) + if err != nil { + return nil, err + } + syncedHeaders[string(metaHash)] = header + + prevHash := header.GetPrevHash() + header, err = e.syncOneHeader(prevHash, core.MetachainShardId) + if err != nil { + return nil, err + } + syncedHeaders[string(prevHash)] = header + } + + err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) + if err != nil { + return nil, err } lastFinished, ok := syncedHeaders[string(epochStartData.GetLastFinishedMetaBlock())] @@ -763,26 +769,26 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma } } - for _, shardData := range meta.GetShardInfoProposalHandlers() { - header, err := e.syncOneHeader(shardData.GetHeaderHash(), shardData.GetShardID()) - if err != nil { - return nil, err - } - syncedHeaders[string(shardData.GetHeaderHash())] = header - - shardHeader, ok := header.(data.ShardHeaderHandler) - if !ok { - log.Error("epoch start data shard header", - "error", process.ErrWrongTypeAssertion, - ) - return nil, epochStart.ErrWrongTypeAssertion - } - - for _, metaHash := range shardHeader.GetMetaBlockHashes() { - hashesToRequest = append(hashesToRequest, metaHash) - shardIds = append(shardIds, core.MetachainShardId) - } - } + // for _, shardData := range meta.GetShardInfoProposalHandlers() { + // header, err := e.syncOneHeader(shardData.GetHeaderHash(), shardData.GetShardID()) + // if err != nil { + // return nil, err + // } + // syncedHeaders[string(shardData.GetHeaderHash())] = header + + // shardHeader, ok := header.(data.ShardHeaderHandler) + // if !ok { + // log.Error("epoch start data shard header", + // "error", process.ErrWrongTypeAssertion, + // ) + // return nil, epochStart.ErrWrongTypeAssertion + // } + + // for _, metaHash := range shardHeader.GetMetaBlockHashes() { + // hashesToRequest = append(hashesToRequest, metaHash) + // shardIds = append(shardIds, core.MetachainShardId) + // } + // } syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) if err != nil { From f7a164b0d541704d1ca464d255456ef6f0a79030 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Fri, 19 Dec 2025 17:56:27 +0200 Subject: [PATCH 07/26] remove debug logs --- epochStart/bootstrap/baseStorageHandler.go | 6 --- epochStart/bootstrap/process.go | 50 --------------------- epochStart/bootstrap/shardStorageHandler.go | 5 --- process/block/baseProcess.go | 6 --- process/block/metablockProposal.go | 24 ---------- process/block/shardInfo.go | 19 +------- process/track/blockNotarizer.go | 29 ------------ 7 files changed, 1 insertion(+), 138 deletions(-) diff --git a/epochStart/bootstrap/baseStorageHandler.go b/epochStart/bootstrap/baseStorageHandler.go index f37d82d920a..f0abdd78257 100644 --- a/epochStart/bootstrap/baseStorageHandler.go +++ b/epochStart/bootstrap/baseStorageHandler.go @@ -176,12 +176,6 @@ func (bsh *baseStorageHandler) saveMetaHdrToStorage(metaBlock data.HeaderHandler headerHash := bsh.hasher.Compute(string(headerBytes)) - log.Debug("saveMetaHdrToStorage", - "hash", headerHash, - "nonce", metaBlock.GetNonce(), - "round", metaBlock.GetRound(), - ) - metaHdrStorage, err := bsh.storageService.GetStorer(dataRetriever.MetaBlockUnit) if err != nil { return nil, err diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 5e3a719c127..70af447ae0a 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -769,27 +769,6 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma } } - // for _, shardData := range meta.GetShardInfoProposalHandlers() { - // header, err := e.syncOneHeader(shardData.GetHeaderHash(), shardData.GetShardID()) - // if err != nil { - // return nil, err - // } - // syncedHeaders[string(shardData.GetHeaderHash())] = header - - // shardHeader, ok := header.(data.ShardHeaderHandler) - // if !ok { - // log.Error("epoch start data shard header", - // "error", process.ErrWrongTypeAssertion, - // ) - // return nil, epochStart.ErrWrongTypeAssertion - // } - - // for _, metaHash := range shardHeader.GetMetaBlockHashes() { - // hashesToRequest = append(hashesToRequest, metaHash) - // shardIds = append(shardIds, core.MetachainShardId) - // } - // } - syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) if err != nil { return nil, err @@ -888,12 +867,6 @@ func (e *epochStartBootstrap) requestIntermediateBlocksIfNeeded( baseHeaderNonce := header.GetNonce() lastExecutedNonce := lastExecutionResult.GetHeaderNonce() - log.Debug("requestIntermediateBlocksIfNeeded", - "headerHash", headerHash, - "lastExecutedNonce", lastExecutedNonce, - "baseHeaderNonce", baseHeaderNonce, - ) - if lastExecutedNonce >= baseHeaderNonce { return nil } @@ -901,11 +874,6 @@ func (e *epochStartBootstrap) requestIntermediateBlocksIfNeeded( headerHashToSync := header.GetPrevHash() currentNonce := baseHeaderNonce for currentNonce > lastExecutedNonce { - log.Debug("requestIntermediateBlocksIfNeeded", - "headerHashToSync", headerHashToSync, - "currentNonce", currentNonce, - ) - syncedHeader, err := e.syncOneHeader(headerHashToSync, shardID) if err != nil { return err @@ -956,11 +924,6 @@ func (e *epochStartBootstrap) requestAndProcessing() (Parameters, error) { } log.Debug("start in epoch bootstrap: got shard headers and previous epoch start meta block") - log.Debug("requestAndProcessing: syncedHeaders") - for hash := range e.syncedHeaders { - log.Debug("requestAndProcessing", "hash", hash) - } - prevEpochStartMetaHash := e.epochStartMeta.GetEpochStartHandler().GetEconomicsHandler().GetPrevEpochStartHash() prevEpochStartMeta, ok := e.syncedHeaders[string(prevEpochStartMetaHash)].(data.MetaHeaderHandler) if !ok { @@ -1239,12 +1202,6 @@ func (e *epochStartBootstrap) requestAndProcessForShard(peerMiniBlocks []*block. return err } - log.Debug("requestAndProcessForShard", - "headerHash", epochStartData.GetHeaderHash(), - "nonce", epochStartData.GetNonce(), - "rootHash", epochStartData.GetRootHash(), - ) - ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeToWaitForRequestedData) err = e.miniBlocksSyncer.SyncPendingMiniBlocks(epochStartData.GetPendingMiniBlockHeaderHandlers(), ctx) cancel() @@ -1381,13 +1338,6 @@ func (e *epochStartBootstrap) getDataToSync( epochStartData data.EpochStartShardDataHandler, shardNotarizedHeader data.ShardHeaderHandler, ) (*dataToSync, error) { - log.Debug("epochStartBootstrap.getDataToSync", - "epochStartData.HeaderHash", epochStartData.GetHeaderHash(), - "epochStartData.Nonce", epochStartData.GetNonce(), - "epochStartData.RootHash", epochStartData.GetRootHash(), - "shardNotarizedHeader.Nonce", shardNotarizedHeader.GetNonce(), - ) - var err error e.storerScheduledSCRs, err = e.storageOpenerHandler.OpenDB( e.generalConfig.ScheduledSCRsStorage.DB, diff --git a/epochStart/bootstrap/shardStorageHandler.go b/epochStart/bootstrap/shardStorageHandler.go index 400cc6934d5..7221fab9eb6 100644 --- a/epochStart/bootstrap/shardStorageHandler.go +++ b/epochStart/bootstrap/shardStorageHandler.go @@ -83,11 +83,6 @@ func (ssh *shardStorageHandler) CloseStorageService() { // SaveDataToStorage will save the fetched data to storage, so it will be used by the storage bootstrap component func (ssh *shardStorageHandler) SaveDataToStorage(components *ComponentsNeededForBootstrap, notarizedShardHeader data.HeaderHandler, withScheduled bool, syncedMiniBlocks map[string]*block.MiniBlock) error { - log.Debug("SaveDataToStorage: syncedHeaders") - for hash := range components.Headers { - log.Debug("SaveDataToStorage", "hash", hash) - } - bootStorer, err := ssh.storageService.GetStorer(dataRetriever.BootstrapUnit) if err != nil { return err diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 43677cd7d27..e48e956c7f0 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -1664,12 +1664,6 @@ func (bp *baseProcessor) getLastSelfNotarizedHeadersForShard(shardID uint32) *bo Hash: lastSelfNotarizedHeaderHash, } - log.Debug("getLastSelfNotarizedHeadersForShard", - "shard", shardID, - "lastnot hash", lastSelfNotarizedHeaderHash, - "lastnot nonce", lastSelfNotarizedHeader.GetNonce(), - ) - return headerInfo } diff --git a/process/block/metablockProposal.go b/process/block/metablockProposal.go index 1a61462fab4..71deda262a7 100644 --- a/process/block/metablockProposal.go +++ b/process/block/metablockProposal.go @@ -992,30 +992,6 @@ func (mp *metaProcessor) checkShardInfoValidity(metaHeaderHandler data.MetaHeade for i := 0; i < len(headerShardInfo); i++ { if !headerShardInfo[i].Equal(createdShardInfo[i]) { - log.Debug("checkShardInfoValidity", - "hsi hash", headerShardInfo[i].GetHeaderHash(), - "hsi nonce", headerShardInfo[i].GetNonce(), - "hsi lastIncludedMetaNonce", headerShardInfo[i].GetLastIncludedMetaNonce(), - "hsi mbs", headerShardInfo[i].GetShardMiniBlockHeaderHandlers(), - "hsi mbs", headerShardInfo[i], - "csi hash", createdShardInfo[i].GetHeaderHash(), - "csi nonce", createdShardInfo[i].GetNonce(), - "csi lastIncludedMetaNonce", createdShardInfo[i].GetLastIncludedMetaNonce(), - "csi mbs", createdShardInfo[i].GetShardMiniBlockHeaderHandlers(), - "csi mbs", createdShardInfo[i], - ) - - for _, mb := range headerShardInfo[i].GetShardMiniBlockHeaderHandlers() { - log.Debug("checkShardInfoValidity.headerShardInfo", - "hash", mb.GetHash(), - ) - } - for _, mb := range createdShardInfo[i].GetShardMiniBlockHeaderHandlers() { - log.Debug("checkShardInfoValidity.createdShardInfo", - "hash", mb.GetHash(), - ) - } - return fmt.Errorf("%w for shardInfo item %d", process.ErrHeaderShardDataMismatch, i) } } diff --git a/process/block/shardInfo.go b/process/block/shardInfo.go index 42e249b9107..8be1cf2a05e 100644 --- a/process/block/shardInfo.go +++ b/process/block/shardInfo.go @@ -203,12 +203,6 @@ func (sic *ShardInfoCreateData) createShardDataFromV3Header( return nil, nil, err } shardDataHandlers[i] = shardData - - log.Debug("createShardDataFromV3Header", - "shardHeader", shardHeader.GetNonce(), - "hash", shardData.GetHeaderHash(), - "lastIncludedMetaNonce", shardData.GetLastIncludedMetaNonce(), - ) } return shardDataProposal, shardDataHandlers, nil @@ -322,21 +316,10 @@ func (sic *ShardInfoCreateData) updateShardDataWithCrossShardInfo(shardData *blo shardData.NumPendingMiniBlocks = uint32(len(sic.pendingMiniBlocksHandler.GetPendingMiniBlocks(header.GetShardID()))) } - metaHeader, metaHash, err := sic.blockTracker.GetLastSelfNotarizedHeader(header.GetShardID()) + metaHeader, _, err := sic.blockTracker.GetLastSelfNotarizedHeader(header.GetShardID()) if err != nil { return err } - - log.Debug("updateShardDataWithCrossShardInfo", - "hash", shardData.GetHeaderHash(), - "shard", header.GetShardID(), - "meta hash", metaHash, - "shard", header.GetShardID(), - "meta shard", metaHeader.GetShardID(), - "nonce", metaHeader.GetNonce(), - "round", metaHeader.GetRound(), - ) - shardData.LastIncludedMetaNonce = metaHeader.GetNonce() return nil diff --git a/process/track/blockNotarizer.go b/process/track/blockNotarizer.go index e236aa0d2d2..6520d3ff810 100644 --- a/process/track/blockNotarizer.go +++ b/process/track/blockNotarizer.go @@ -66,21 +66,6 @@ func (bn *blockNotarizer) AddNotarizedHeader( return bn.notarizedHeaders[shardID][i].Header.GetNonce() < bn.notarizedHeaders[shardID][j].Header.GetNonce() }) bn.mutNotarizedHeaders.Unlock() - - bn.mutNotarizedHeaders.Lock() - for shard, hdrs := range bn.notarizedHeaders { - log.Debug("AddNotarizedHeader", - "shard", shard, - ) - for _, hdr := range hdrs { - log.Debug("AddNotarizedHeader", - "hash", hdr.Hash, - "nonce", hdr.Header.GetNonce(), - "round", hdr.Header.GetRound(), - ) - } - } - bn.mutNotarizedHeaders.Unlock() } // CleanupNotarizedHeadersBehindNonce cleanups notarized headers for a given shard behind a given nonce @@ -170,20 +155,6 @@ func (bn *blockNotarizer) GetLastNotarizedHeader(shardID uint32) (data.HeaderHan bn.mutNotarizedHeaders.RLock() defer bn.mutNotarizedHeaders.RUnlock() - // for shard, hdrs := range bn.notarizedHeaders { - // log.Debug("GetLastNotarizedHeader", - // "shardID", shardID, - // "shard", shard, - // ) - // for _, hdr := range hdrs { - // log.Debug("GetLastNotarizedHeader", - // "hash", hdr.Hash, - // "nonce", hdr.Header.GetNonce(), - // "round", hdr.Header.GetRound(), - // ) - // } - // } - hdrInfo := bn.lastNotarizedHeaderInfo(shardID) if hdrInfo == nil { return nil, nil, process.ErrNotarizedHeadersSliceForShardIsNil From d197d3efaba3bab9125d3f66a70cce27094ba057 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 11:43:03 +0200 Subject: [PATCH 08/26] refactor getting from storage with nonce --- process/sync/baseSync.go | 55 ++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index 4c112669784..e47af2556c4 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -1766,6 +1766,7 @@ func (boot *baseBootstrap) getHeader(hash []byte) (data.HeaderHandler, error) { return process.GetShardHeader(hash, boot.headers, boot.marshalizer, boot.store) } +// getHeaderFromPool will try to get header from pool or storage func (boot *baseBootstrap) getHeaderFromPool(hash []byte) (data.HeaderHandler, error) { if boot.shardCoordinator.SelfId() == core.MetachainShardId { return process.GetMetaHeaderFromPool(hash, boot.headers) @@ -1778,37 +1779,43 @@ func (boot *baseBootstrap) getHeaderWithNonce( nonce uint64, ) (data.HeaderHandler, []byte, error) { if boot.shardCoordinator.SelfId() == core.MetachainShardId { - header, hash, err := process.GetMetaHeaderFromPoolWithNonce(nonce, boot.headers) - if err != nil { - header, hash, err = process.GetMetaHeaderFromStorageWithNonce( - nonce, - boot.store, - boot.uint64Converter, - boot.marshalizer, - ) - if err != nil { - return nil, nil, err - } - } + return boot.getMetaHeaderWithNonce(nonce) + } + return boot.getShardHeaderWithNonce(nonce) +} + +func (boot *baseBootstrap) getMetaHeaderWithNonce( + nonce uint64, +) (data.HeaderHandler, []byte, error) { + header, hash, err := process.GetMetaHeaderFromPoolWithNonce(nonce, boot.headers) + if err == nil { return header, hash, nil } + return process.GetMetaHeaderFromStorageWithNonce( + nonce, + boot.store, + boot.uint64Converter, + boot.marshalizer, + ) +} + +func (boot *baseBootstrap) getShardHeaderWithNonce( + nonce uint64, +) (data.HeaderHandler, []byte, error) { header, hash, err := process.GetShardHeaderFromPoolWithNonce(nonce, boot.shardCoordinator.SelfId(), boot.headers) - if err != nil { - header, hash, err = process.GetShardHeaderFromStorageWithNonce( - nonce, - boot.shardCoordinator.SelfId(), - boot.store, - boot.uint64Converter, - boot.marshalizer, - ) - if err != nil { - return nil, nil, err - } + if err == nil { + return header, hash, nil } - return header, hash, nil + return process.GetShardHeaderFromStorageWithNonce( + nonce, + boot.shardCoordinator.SelfId(), + boot.store, + boot.uint64Converter, + boot.marshalizer, + ) } func (boot *baseBootstrap) getHeaderFromPoolWithNonce( From 54b0c24a4746bcbf2bbd5198c3cfe15d646a871f Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 12:24:29 +0200 Subject: [PATCH 09/26] refactor epoch start last self notarized headers --- epochStart/bootstrap/metaStorageHandler.go | 230 +++++++++++---------- epochStart/bootstrap/process.go | 115 ++++++----- 2 files changed, 191 insertions(+), 154 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index 51eac8327d9..cc97df3f245 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -12,7 +12,6 @@ import ( "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/epochStart" "github.com/multiversx/mx-chain-go/epochStart/bootstrap/disabled" - "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/block/bootstrapStorage" "github.com/multiversx/mx-chain-go/storage/factory" ) @@ -132,102 +131,13 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor return err } - epochStartMeta := components.EpochStartMetaBlock - var lastSelfNotarizedHeaders []bootstrapStorage.BootstrapHeaderInfo - if !epochStartMeta.IsHeaderV3() { - lastSelfNotarizedHeaders = []bootstrapStorage.BootstrapHeaderInfo{lastHeader} - } else { - for _, epochStartData := range epochStartMeta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { - lastFinishedMetaBlockHash := epochStartData.GetLastFinishedMetaBlock() - lastFinishedMetaBlock, ok := components.Headers[string(lastFinishedMetaBlockHash)] - if !ok { - log.Error("should be able to find header", - "hash", lastFinishedMetaBlockHash, - "shardID", epochStartData.GetShardID(), - ) - return epochStart.ErrMissingHeader - } - - shardHeaderHash := epochStartData.GetHeaderHash() - shardHeader, ok := components.Headers[string(shardHeaderHash)] - if !ok { - log.Error("should be able to find header", - "hash", lastFinishedMetaBlockHash, - "shardID", epochStartData.GetShardID(), - ) - return epochStart.ErrMissingHeader - } - - shardHeaderHandler, ok := shardHeader.(data.ShardHeaderHandler) - if !ok { - log.Error("epoch start data shard header", - "error", process.ErrWrongTypeAssertion, - ) - return epochStart.ErrWrongTypeAssertion - } - - if len(shardHeaderHandler.GetMetaBlockHashes()) > 0 { - metaHash := shardHeaderHandler.GetMetaBlockHashes()[0] - metaHeader0, ok := components.Headers[string(metaHash)] - if !ok { - log.Error("should be able to find header", - "hash", metaHash, - "shardID", epochStartData.GetShardID(), - ) - return epochStart.ErrMissingHeader - } - - prevHash := metaHeader0.GetPrevHash() - - metaHeader1, ok := components.Headers[string(prevHash)] - if !ok { - log.Error("should be able to find header", - "hash", prevHash, - "shardID", epochStartData.GetShardID(), - ) - return epochStart.ErrMissingHeader - } - - lastFinishedMetaBlockHash = prevHash - lastFinishedMetaBlock = metaHeader1 - } - - bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ - ShardId: epochStartData.GetShardID(), - Epoch: lastFinishedMetaBlock.GetEpoch(), - Nonce: lastFinishedMetaBlock.GetNonce(), - Hash: lastFinishedMetaBlockHash, - } - - log.Debug("SaveDataToStorage", - "GetLastFinishedMetaBlock: hash", lastFinishedMetaBlockHash, - "shard", epochStartData.GetShardID(), - ) - - lastSelfNotarizedHeaders = append(lastSelfNotarizedHeaders, bootstrapHdrInfo) - } - - lastExecRes, err := common.GetLastBaseExecutionResultHandler(epochStartMeta) - if err != nil { - return err - } - - lastExecMetaHeader, ok := components.Headers[string(lastExecRes.GetHeaderHash())] - if !ok { - log.Error("should be able to find last exec meta header", - "hash", lastExecRes.GetHeaderHash(), - ) - return epochStart.ErrMissingHeader - } - - bootstrapHdrInfoMeta := bootstrapStorage.BootstrapHeaderInfo{ - ShardId: core.MetachainShardId, - Epoch: lastExecMetaHeader.GetEpoch(), - Nonce: lastExecMetaHeader.GetNonce(), - Hash: lastExecRes.GetHeaderHash(), - } - - lastSelfNotarizedHeaders = append(lastSelfNotarizedHeaders, bootstrapHdrInfoMeta) + lastSelfNotarizedHeaders, err := msh.getLastSelfNotarizedHeaders( + components.EpochStartMetaBlock, + lastHeader, + components.Headers, + ) + if err != nil { + return err } bootStrapData := bootstrapStorage.BootstrapData{ @@ -267,6 +177,118 @@ func (msh *metaStorageHandler) SaveDataToStorage(components *ComponentsNeededFor return nil } +func (msh *metaStorageHandler) getLastSelfNotarizedHeaders( + epochStartMeta data.MetaHeaderHandler, + epochStartMetaBootstrapInfo bootstrapStorage.BootstrapHeaderInfo, + syncedHeaders map[string]data.HeaderHandler, +) ([]bootstrapStorage.BootstrapHeaderInfo, error) { + var lastSelfNotarizedHeaders []bootstrapStorage.BootstrapHeaderInfo + if !epochStartMeta.IsHeaderV3() { + return []bootstrapStorage.BootstrapHeaderInfo{ + epochStartMetaBootstrapInfo, + }, nil + } + + for _, epochStartData := range epochStartMeta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { + + bootstrapHdrInfo, err := msh.getLastNotarizedBootstrapInfoForEpochStartData(epochStartData, syncedHeaders) + if err != nil { + return nil, err + } + + lastSelfNotarizedHeaders = append(lastSelfNotarizedHeaders, bootstrapHdrInfo) + } + + bootstrapHdrInfoMeta, err := msh.getLastMetaBoostrapInfo(epochStartMeta, syncedHeaders) + if err != nil { + return nil, err + } + + lastSelfNotarizedHeaders = append(lastSelfNotarizedHeaders, bootstrapHdrInfoMeta) + + return lastSelfNotarizedHeaders, nil +} + +func (msh *metaStorageHandler) getLastMetaBoostrapInfo( + epochStartMeta data.MetaHeaderHandler, + syncedHeaders map[string]data.HeaderHandler, +) (bootstrapStorage.BootstrapHeaderInfo, error) { + lastExecRes, err := common.GetLastBaseExecutionResultHandler(epochStartMeta) + if err != nil { + return bootstrapStorage.BootstrapHeaderInfo{}, err + } + + lastExecMetaHeader, ok := syncedHeaders[string(lastExecRes.GetHeaderHash())] + if !ok { + return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader + } + + bootstrapHdrInfoMeta := bootstrapStorage.BootstrapHeaderInfo{ + ShardId: core.MetachainShardId, + Epoch: lastExecMetaHeader.GetEpoch(), + Nonce: lastExecMetaHeader.GetNonce(), + Hash: lastExecRes.GetHeaderHash(), + } + + return bootstrapHdrInfoMeta, nil +} + +func (msh *metaStorageHandler) getLastNotarizedBootstrapInfoForEpochStartData( + epochStartData data.EpochStartShardDataHandler, + syncedHeaders map[string]data.HeaderHandler, +) (bootstrapStorage.BootstrapHeaderInfo, error) { + lastFinishedMetaBlockHash := epochStartData.GetLastFinishedMetaBlock() + lastFinishedMetaBlock, ok := syncedHeaders[string(lastFinishedMetaBlockHash)] + if !ok { + return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader + } + + shardHeaderHash := epochStartData.GetHeaderHash() + shardHeader, ok := syncedHeaders[string(shardHeaderHash)] + if !ok { + return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader + } + + shardHeaderHandler, ok := shardHeader.(data.ShardHeaderHandler) + if !ok { + return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrWrongTypeAssertion + } + + if len(shardHeaderHandler.GetMetaBlockHashes()) <= 0 { + return bootstrapStorage.BootstrapHeaderInfo{ + ShardId: epochStartData.GetShardID(), + Epoch: lastFinishedMetaBlock.GetEpoch(), + Nonce: lastFinishedMetaBlock.GetNonce(), + Hash: lastFinishedMetaBlockHash, + }, nil + } + + metaHash := shardHeaderHandler.GetMetaBlockHashes()[0] + metaHeader, ok := syncedHeaders[string(metaHash)] + if !ok { + return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader + } + + prevHash := metaHeader.GetPrevHash() + + prevMetaHeader, ok := syncedHeaders[string(prevHash)] + if !ok { + return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader + } + + lastFinishedMetaBlockHash = prevHash + lastFinishedMetaBlock = prevMetaHeader + + bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ + ShardId: epochStartData.GetShardID(), + Epoch: lastFinishedMetaBlock.GetEpoch(), + Nonce: lastFinishedMetaBlock.GetNonce(), + Hash: lastFinishedMetaBlockHash, + } + + return bootstrapHdrInfo, nil +} + func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeededForBootstrap) error { for hash, hdr := range components.Headers { isForCurrentShard := hdr.GetShardID() == msh.shardCoordinator.SelfId() @@ -276,10 +298,10 @@ func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeed "shard", hdr.GetShardID(), "nonce", hdr.GetNonce(), ) - _, err := msh.saveShardHdrToStorage(hdr) - if err != nil { - return err - } + // _, err := msh.saveShardHdrToStorage(hdr) + // if err != nil { + // return err + // } continue } @@ -288,12 +310,6 @@ func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeed if err != nil { return err } - - log.Debug("saved header", - "hash", hash, - "shard", hdr.GetShardID(), - "nonce", hdr.GetNonce(), - ) } return nil diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 70af447ae0a..a5e4b1ddd4a 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -714,59 +714,37 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma return nil, err } - syncedHeader, ok := syncedHeaders[string(epochStartData.GetHeaderHash())] - if !ok { - log.Error("should have been synced at this point") - return nil, epochStart.ErrMissingHeader - } - shardHeader, ok := syncedHeader.(data.ShardHeaderHandler) - if !ok { - log.Error("epoch start data shard header", - "error", process.ErrWrongTypeAssertion, - ) - return nil, epochStart.ErrWrongTypeAssertion - } - - // if thare notarized meta headers, sync their previous meta header - if len(shardHeader.GetMetaBlockHashes()) > 0 { - metaHash := shardHeader.GetMetaBlockHashes()[0] - header, err := e.syncOneHeader(metaHash, core.MetachainShardId) - if err != nil { - return nil, err - } - syncedHeaders[string(metaHash)] = header - - prevHash := header.GetPrevHash() - header, err = e.syncOneHeader(prevHash, core.MetachainShardId) - if err != nil { - return nil, err - } - syncedHeaders[string(prevHash)] = header - } - - err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) + err = e.syncLastNotarizedMetaForEpochStartData(epochStartData.GetHeaderHash(), syncedHeaders) if err != nil { return nil, err } - lastFinished, ok := syncedHeaders[string(epochStartData.GetLastFinishedMetaBlock())] - if !ok { - log.Error("should have been synced at this point") - return nil, epochStart.ErrMissingHeader - } + hashesToRequest = append(hashesToRequest, epochStartData.GetLastFinishedMetaBlock()) + shardIds = append(shardIds, core.MetachainShardId) - hashToSync := meta.GetPrevHash() - currNonce := meta.GetNonce() - for currNonce > lastFinished.GetNonce() { - header, err := e.syncOneHeader(hashToSync, core.MetachainShardId) - if err != nil { - return nil, err - } - syncedHeaders[string(hashToSync)] = header + // err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) + // if err != nil { + // return nil, err + // } - hashToSync = header.GetPrevHash() - currNonce = header.GetNonce() - } + // lastFinished, ok := syncedHeaders[string(epochStartData.GetLastFinishedMetaBlock())] + // if !ok { + // log.Error("should have been synced at this point") + // return nil, epochStart.ErrMissingHeader + // } + + // hashToSync := meta.GetPrevHash() + // currNonce := meta.GetNonce() + // for currNonce > lastFinished.GetNonce() { + // header, err := e.syncOneHeader(hashToSync, core.MetachainShardId) + // if err != nil { + // return nil, err + // } + // syncedHeaders[string(hashToSync)] = header + + // hashToSync = header.GetPrevHash() + // currNonce = header.GetNonce() + // } } syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) @@ -781,6 +759,49 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma return syncedHeaders, nil } +func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( + epochStartDataHeaderHash []byte, + syncedHeaders map[string]data.HeaderHandler, +) error { + // epoch start data header should have been synced up to this point + syncedHeader, ok := syncedHeaders[string(epochStartDataHeaderHash)] + if !ok { + return epochStart.ErrMissingHeader + } + shardHeader, ok := syncedHeader.(data.ShardHeaderHandler) + if !ok { + log.Error("epoch start data shard header", + "error", process.ErrWrongTypeAssertion, + ) + return epochStart.ErrWrongTypeAssertion + } + + if len(shardHeader.GetMetaBlockHashes()) <= 0 { + return nil + } + + // if thare notarized meta headers, sync their previous meta header + + // get oldest referenced meta blocks (first in the list should be the oldest) + // and sync it's previous meta header + metaHash := shardHeader.GetMetaBlockHashes()[0] + + header, err := e.syncOneHeader(metaHash, core.MetachainShardId) + if err != nil { + return err + } + syncedHeaders[string(metaHash)] = header + + prevHash := header.GetPrevHash() + header, err = e.syncOneHeader(prevHash, core.MetachainShardId) + if err != nil { + return err + } + syncedHeaders[string(prevHash)] = header + + return nil +} + func (e *epochStartBootstrap) syncEpochStartMetaHeaders( meta data.MetaHeaderHandler, hashesToRequest [][]byte, From cfcbb2d21a8876c6e8d5df60f08fc2d11f6cd888 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 14:00:56 +0200 Subject: [PATCH 10/26] fix saving shard headers to storage --- epochStart/bootstrap/metaStorageHandler.go | 8 +- epochStart/bootstrap/process.go | 105 ++++++++++++--------- 2 files changed, 62 insertions(+), 51 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index cc97df3f245..4c4db2023b3 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -298,10 +298,10 @@ func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeed "shard", hdr.GetShardID(), "nonce", hdr.GetNonce(), ) - // _, err := msh.saveShardHdrToStorage(hdr) - // if err != nil { - // return err - // } + _, err := msh.saveShardHdrToStorage(hdr) + if err != nil { + return err + } continue } diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index a5e4b1ddd4a..16bd2247e4f 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -691,72 +691,83 @@ func (e *epochStartBootstrap) createSyncers() error { } func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (map[string]data.HeaderHandler, error) { - log.Debug("syncHeadersV3From meta", - "nonce", meta.GetNonce(), - ) + syncedHeaders := make(map[string]data.HeaderHandler) for _, epochStartData := range meta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { - log.Debug("syncHeadersV3From", - "headerHash", epochStartData.GetHeaderHash(), - "shardID", epochStartData.GetShardID(), - "round", epochStartData.GetRound(), - "nonce", epochStartData.GetNonce(), - "rootHash", epochStartData.GetRootHash(), - ) + err := e.syncEpochStartDataInfo(meta, epochStartData, syncedHeaders) + if err != nil { + return nil, err + } } - syncedHeaders := make(map[string]data.HeaderHandler) - hashesToRequest := make([][]byte, 0) shardIds := make([]uint32, 0) - for _, epochStartData := range meta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { - err := e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetHeaderHash(), epochStartData.GetShardID()) - if err != nil { - return nil, err + syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) + if err != nil { + return nil, err + } + + for hash, header := range syncedMetaHeaders { + syncedHeaders[hash] = header + } + + return syncedHeaders, nil +} + +func (e *epochStartBootstrap) syncIntermediateMetaBlocksIfNeeded( + epochStartMeta data.HeaderHandler, + lastFinishedMetaBlockHash []byte, + syncedHeaders map[string]data.HeaderHandler, +) error { + lastFinished, ok := syncedHeaders[string(lastFinishedMetaBlockHash)] + if !ok { + return epochStart.ErrMissingHeader + } + + hashToSync := epochStartMeta.GetPrevHash() + currNonce := epochStartMeta.GetNonce() + for currNonce > lastFinished.GetNonce() { + // check if not already synced (when handled for the other shards) + header, ok := syncedHeaders[string(hashToSync)] + if ok { + hashToSync = header.GetPrevHash() + currNonce = header.GetNonce() + continue } - err = e.syncLastNotarizedMetaForEpochStartData(epochStartData.GetHeaderHash(), syncedHeaders) + header, err := e.syncOneHeader(hashToSync, core.MetachainShardId) if err != nil { - return nil, err + return err } + syncedHeaders[string(hashToSync)] = header - hashesToRequest = append(hashesToRequest, epochStartData.GetLastFinishedMetaBlock()) - shardIds = append(shardIds, core.MetachainShardId) - - // err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) - // if err != nil { - // return nil, err - // } - - // lastFinished, ok := syncedHeaders[string(epochStartData.GetLastFinishedMetaBlock())] - // if !ok { - // log.Error("should have been synced at this point") - // return nil, epochStart.ErrMissingHeader - // } + hashToSync = header.GetPrevHash() + currNonce = header.GetNonce() + } - // hashToSync := meta.GetPrevHash() - // currNonce := meta.GetNonce() - // for currNonce > lastFinished.GetNonce() { - // header, err := e.syncOneHeader(hashToSync, core.MetachainShardId) - // if err != nil { - // return nil, err - // } - // syncedHeaders[string(hashToSync)] = header + return nil +} - // hashToSync = header.GetPrevHash() - // currNonce = header.GetNonce() - // } +func (e *epochStartBootstrap) syncEpochStartDataInfo( + epochStartMeta data.HeaderHandler, + epochStartData data.EpochStartShardDataHandler, + syncedHeaders map[string]data.HeaderHandler, +) error { + err := e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetHeaderHash(), epochStartData.GetShardID()) + if err != nil { + return err } - syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) + err = e.syncLastNotarizedMetaForEpochStartData(epochStartData.GetHeaderHash(), syncedHeaders) if err != nil { - return nil, err + return err } - for hash, header := range syncedMetaHeaders { - syncedHeaders[hash] = header + err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) + if err != nil { + return err } - return syncedHeaders, nil + return e.syncIntermediateMetaBlocksIfNeeded(epochStartMeta, epochStartData.GetLastFinishedMetaBlock(), syncedHeaders) } func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( From 00da184d8d1037f5b509c2f45f1e6252875008e5 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 16:30:18 +0200 Subject: [PATCH 11/26] fixes + unit tests --- epochStart/bootstrap/process.go | 38 +++++--- epochStart/bootstrap/process_test.go | 132 +++++++++++++++------------ 2 files changed, 99 insertions(+), 71 deletions(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 16bd2247e4f..0daf1e1cee9 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -757,7 +757,16 @@ func (e *epochStartBootstrap) syncEpochStartDataInfo( return err } - err = e.syncLastNotarizedMetaForEpochStartData(epochStartData.GetHeaderHash(), syncedHeaders) + // epoch start data header should have been synced up to this point + syncedHeader, ok := syncedHeaders[string(epochStartData.GetHeaderHash())] + if !ok { + return epochStart.ErrMissingHeader + } + if !syncedHeader.IsHeaderV3() { + return nil + } + + err = e.syncLastNotarizedMetaForEpochStartData(syncedHeader, syncedHeaders) if err != nil { return err } @@ -771,26 +780,17 @@ func (e *epochStartBootstrap) syncEpochStartDataInfo( } func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( - epochStartDataHeaderHash []byte, + header data.HeaderHandler, syncedHeaders map[string]data.HeaderHandler, ) error { - // epoch start data header should have been synced up to this point - syncedHeader, ok := syncedHeaders[string(epochStartDataHeaderHash)] - if !ok { - return epochStart.ErrMissingHeader - } - shardHeader, ok := syncedHeader.(data.ShardHeaderHandler) + shardHeader, ok := header.(data.ShardHeaderHandler) if !ok { - log.Error("epoch start data shard header", - "error", process.ErrWrongTypeAssertion, - ) return epochStart.ErrWrongTypeAssertion } if len(shardHeader.GetMetaBlockHashes()) <= 0 { return nil } - // if thare notarized meta headers, sync their previous meta header // get oldest referenced meta blocks (first in the list should be the oldest) @@ -823,9 +823,13 @@ func (e *epochStartBootstrap) syncEpochStartMetaHeaders( return nil, err } + // add the epoch start meta hash to the list to sync its proof + hashesToRequest = append(hashesToRequest, epochStartMetaHash) + shardIds = append(shardIds, core.MetachainShardId) + // sync meta header with intermediate blocks up to last executed (for supernova) syncedHeaders := make(map[string]data.HeaderHandler) - err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartMetaHash, meta.GetShardID()) + err = e.requestBlocksUpToLastExecuted(syncedHeaders, meta, core.MetachainShardId) if err != nil { return nil, err } @@ -887,6 +891,14 @@ func (e *epochStartBootstrap) requestIntermediateBlocksIfNeeded( } syncedHeaders[string(headerHash)] = header + return e.requestBlocksUpToLastExecuted(syncedHeaders, header, shardID) +} + +func (e *epochStartBootstrap) requestBlocksUpToLastExecuted( + syncedHeaders map[string]data.HeaderHandler, + header data.HeaderHandler, + shardID uint32, +) error { if !header.IsHeaderV3() { return nil } diff --git a/epochStart/bootstrap/process_test.go b/epochStart/bootstrap/process_test.go index fbda8b708ec..7746e8a0c8f 100644 --- a/epochStart/bootstrap/process_test.go +++ b/epochStart/bootstrap/process_test.go @@ -2603,54 +2603,6 @@ func TestSyncSetGuardianTransaction(t *testing.T) { func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { t.Parallel() - t.Run("should return early if last executed nonce equal to current nonce", func(t *testing.T) { - t.Parallel() - - hdrHash1 := []byte("hdrHash1") - hdrHash2 := []byte("hdrHash2") - - header1 := &block.HeaderV3{ - Nonce: 11, - PrevHash: hdrHash2, - LastExecutionResult: &block.ExecutionResultInfo{ - ExecutionResult: &block.BaseExecutionResult{ - HeaderNonce: 11, - }, - }, - } - - coreComp, cryptoComp := createComponentsForEpochStart() - args := createMockEpochStartBootstrapArgs(coreComp, cryptoComp) - - epochStartProvider, _ := NewEpochStartBootstrap(args) - epochStartProvider.headersSyncer = &epochStartMocks.HeadersByHashSyncerStub{ - SyncMissingHeadersByHashCalled: func(shardIDs []uint32, headersHashes [][]byte, ctx context.Context) error { - return nil - }, - GetHeadersCalled: func() (m map[string]data.HeaderHandler, err error) { - return map[string]data.HeaderHandler{ - string(hdrHash1): header1, - }, nil - }, - } - - metaBlock := &block.MetaBlockV3{ - Epoch: 2, - EpochStart: block.EpochStart{ - LastFinalizedHeaders: []block.EpochStartShardData{ - {HeaderHash: hdrHash1, ShardID: 0}, - }, - Economics: block.Economics{ - PrevEpochStartHash: hdrHash2, - }, - }, - } - - headers, err := epochStartProvider.syncHeadersFrom(metaBlock) - require.Nil(t, err) - require.Equal(t, 1, len(headers)) - }) - t.Run("should error if requested header not in returned headers", func(t *testing.T) { t.Parallel() @@ -2823,6 +2775,11 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { PrevEpochStartHash: hdrHash2, }, }, + LastExecutionResult: &block.MetaExecutionResultInfo{ + ExecutionResult: &block.BaseMetaExecutionResult{ + BaseExecutionResult: &block.BaseExecutionResult{}, + }, + }, } headers, err := epochStartProvider.syncHeadersFrom(metaBlock) @@ -2835,12 +2792,22 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { hdrHash1 := []byte("hdrHash1") hdrHash2 := []byte("hdrHash2") + lastExecMetaHash := []byte("lastExecMetaHash") header1 := &block.Header{ Nonce: 11, PrevHash: hdrHash2, } + lastExecMeta := &block.MetaBlockV3{ + Nonce: 20, + LastExecutionResult: &block.MetaExecutionResultInfo{ + ExecutionResult: &block.BaseMetaExecutionResult{ + BaseExecutionResult: &block.BaseExecutionResult{}, + }, + }, + } + coreComp, cryptoComp := createComponentsForEpochStart() args := createMockEpochStartBootstrapArgs(coreComp, cryptoComp) @@ -2851,26 +2818,41 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { }, GetHeadersCalled: func() (m map[string]data.HeaderHandler, err error) { return map[string]data.HeaderHandler{ - string(hdrHash1): header1, + string(hdrHash1): header1, + string(lastExecMetaHash): lastExecMeta, }, nil }, } metaBlock := &block.MetaBlockV3{ - Epoch: 2, + Epoch: 2, + Nonce: 21, + PrevHash: lastExecMetaHash, EpochStart: block.EpochStart{ LastFinalizedHeaders: []block.EpochStartShardData{ - {HeaderHash: hdrHash1, ShardID: 0}, + { + HeaderHash: hdrHash1, + ShardID: 0, + LastFinishedMetaBlock: lastExecMetaHash, + }, }, Economics: block.Economics{ PrevEpochStartHash: hdrHash2, }, }, + LastExecutionResult: &block.MetaExecutionResultInfo{ + ExecutionResult: &block.BaseMetaExecutionResult{ + BaseExecutionResult: &block.BaseExecutionResult{ + HeaderNonce: 20, + HeaderHash: lastExecMetaHash, + }, + }, + }, } headers, err := epochStartProvider.syncHeadersFrom(metaBlock) require.Nil(t, err) - require.Equal(t, 1, len(headers)) + require.Equal(t, 2, len(headers)) }) t.Run("should work with meta v3 and shard v3", func(t *testing.T) { @@ -2879,6 +2861,8 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { hdrHash1 := []byte("hdrHash1") hdrHash2 := []byte("hdrHash2") hdrHash3 := []byte("hdrHash3") + hdrHash4 := []byte("hdrHash4") + lastExecMetaHash := []byte("lastExecMetaHash") header1 := &block.HeaderV3{ Nonce: 12, @@ -2899,6 +2883,22 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { LastExecutionResult: &block.ExecutionResultInfo{}, } + lastExecMeta := &block.MetaBlockV3{ + Nonce: 20, + PrevHash: hdrHash4, + LastExecutionResult: &block.MetaExecutionResultInfo{ + ExecutionResult: &block.BaseMetaExecutionResult{ + BaseExecutionResult: &block.BaseExecutionResult{ + HeaderNonce: 19, + }, + }, + }, + } + + metaHeader4 := &block.MetaBlockV3{ + Nonce: 19, + } + coreComp, cryptoComp := createComponentsForEpochStart() args := createMockEpochStartBootstrapArgs(coreComp, cryptoComp) @@ -2909,28 +2909,44 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { }, GetHeadersCalled: func() (m map[string]data.HeaderHandler, err error) { return map[string]data.HeaderHandler{ - string(hdrHash1): header1, - string(hdrHash2): header2, - string(hdrHash3): header3, + string(hdrHash1): header1, + string(hdrHash2): header2, + string(hdrHash3): header3, + string(hdrHash4): metaHeader4, + string(lastExecMetaHash): lastExecMeta, }, nil }, } metaBlock := &block.MetaBlockV3{ - Epoch: 2, + Epoch: 2, + Nonce: 21, + PrevHash: lastExecMetaHash, EpochStart: block.EpochStart{ LastFinalizedHeaders: []block.EpochStartShardData{ - {HeaderHash: hdrHash1, ShardID: 0}, + { + HeaderHash: hdrHash1, + ShardID: 0, + LastFinishedMetaBlock: lastExecMetaHash, + }, }, Economics: block.Economics{ PrevEpochStartHash: hdrHash2, }, }, + LastExecutionResult: &block.MetaExecutionResultInfo{ + ExecutionResult: &block.BaseMetaExecutionResult{ + BaseExecutionResult: &block.BaseExecutionResult{ + HeaderHash: lastExecMetaHash, + HeaderNonce: 20, + }, + }, + }, } headers, err := epochStartProvider.syncHeadersFrom(metaBlock) require.Nil(t, err) - require.Equal(t, 2, len(headers)) + require.Equal(t, 5, len(headers)) }) } From ff4caa7c14600d92c9b96de3994b0843dd9f4a57 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 16:38:09 +0200 Subject: [PATCH 12/26] fix process tests --- .../executionManager/executionManager_test.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/process/asyncExecution/executionManager/executionManager_test.go b/process/asyncExecution/executionManager/executionManager_test.go index 67f6070f384..16b959d1f7e 100644 --- a/process/asyncExecution/executionManager/executionManager_test.go +++ b/process/asyncExecution/executionManager/executionManager_test.go @@ -342,7 +342,16 @@ func TestExecutionManager_AddPairForExecution(t *testing.T) { args.Headers = &pool.HeadersPoolStub{ GetHeaderByHashCalled: func(hash []byte) (data.HeaderHandler, error) { - return nil, errExpected + return nil, errors.New("fetch error") + }, + } + args.StorageService = &storageStubs.ChainStorerStub{ + GetStorerCalled: func(unitType dataRetriever.UnitType) (storage.Storer, error) { + return &storageStubs.StorerStub{ + GetCalled: func(key []byte) ([]byte, error) { + return nil, errExpected + }, + }, nil }, } @@ -357,7 +366,7 @@ func TestExecutionManager_AddPairForExecution(t *testing.T) { } err := em.AddPairForExecution(pair) - require.Equal(t, errExpected, err) + require.ErrorIs(t, err, process.ErrMissingHeader) require.Equal(t, 0, counter) }) From 6a43815d353c9881126cd6e350a2957573c42bbe Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 16:39:19 +0200 Subject: [PATCH 13/26] remove debug log --- epochStart/bootstrap/metaStorageHandler.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index 4c4db2023b3..271392332d3 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -290,14 +290,9 @@ func (msh *metaStorageHandler) getLastNotarizedBootstrapInfoForEpochStartData( } func (msh *metaStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNeededForBootstrap) error { - for hash, hdr := range components.Headers { + for _, hdr := range components.Headers { isForCurrentShard := hdr.GetShardID() == msh.shardCoordinator.SelfId() if !isForCurrentShard { - log.Debug("not for curr shard", - "hash", hash, - "shard", hdr.GetShardID(), - "nonce", hdr.GetNonce(), - ) _, err := msh.saveShardHdrToStorage(hdr) if err != nil { return err From 8206f45795971f391e79a4ec306bd5f3ed1d3ee0 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 16:46:37 +0200 Subject: [PATCH 14/26] remove commented code --- epochStart/bootstrap/shardStorageHandler.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/epochStart/bootstrap/shardStorageHandler.go b/epochStart/bootstrap/shardStorageHandler.go index 7221fab9eb6..f2af348ad89 100644 --- a/epochStart/bootstrap/shardStorageHandler.go +++ b/epochStart/bootstrap/shardStorageHandler.go @@ -183,11 +183,8 @@ func (ssh *shardStorageHandler) saveEpochStartMetaHdrs(components *ComponentsNee func (ssh *shardStorageHandler) saveEpochStartShardHdrs(components *ComponentsNeededForBootstrap) error { for _, hdr := range components.Headers { - // not only start of epoch header have to be saved at this point, we should save + // not only start of epoch header should be saved at this point, we should save // also intermediate headers up to last executed header - // if !hdr.IsStartOfEpochBlock() { - // continue - // } isForCurrentShard := hdr.GetShardID() == ssh.shardCoordinator.SelfId() if !isForCurrentShard { From e36c8ee2989ad619fac25fee4431a50d4762b85d Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 22 Dec 2025 16:47:33 +0200 Subject: [PATCH 15/26] remove debug log --- process/sync/storageBootstrap/metaStorageBootstrapper.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/process/sync/storageBootstrap/metaStorageBootstrapper.go b/process/sync/storageBootstrap/metaStorageBootstrapper.go index 40305d6e677..64dc475562b 100644 --- a/process/sync/storageBootstrap/metaStorageBootstrapper.go +++ b/process/sync/storageBootstrap/metaStorageBootstrapper.go @@ -160,10 +160,6 @@ func (msb *metaStorageBootstrapper) cleanupNotarizedStorageForHigherNoncesIfExis func (msb *metaStorageBootstrapper) applySelfNotarizedHeaders( bootstrapHeadersInfo []bootstrapStorage.BootstrapHeaderInfo, ) ([]data.HeaderHandler, [][]byte, error) { - log.Debug("applySelfNotarizedHeaders", - "len boot", len(bootstrapHeadersInfo), - ) - for _, bootstrapHeaderInfo := range bootstrapHeadersInfo { selfNotarizedHeader, err := msb.getHeader(bootstrapHeaderInfo.Hash) if err != nil { From 0009304b6a2edd38778347f21f9ba5d414d7c988 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Tue, 23 Dec 2025 11:27:54 +0200 Subject: [PATCH 16/26] add nonce check --- epochStart/bootstrap/process.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 0daf1e1cee9..da5b1f0206c 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -725,6 +725,12 @@ func (e *epochStartBootstrap) syncIntermediateMetaBlocksIfNeeded( hashToSync := epochStartMeta.GetPrevHash() currNonce := epochStartMeta.GetNonce() + + lastFinishedNonce := lastFinished.GetNonce() + if lastFinishedNonce >= currNonce { + return nil + } + for currNonce > lastFinished.GetNonce() { // check if not already synced (when handled for the other shards) header, ok := syncedHeaders[string(hashToSync)] From 54fc5840c5ca27916767c8a1d859c441d2b32070 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 24 Dec 2025 13:00:57 +0200 Subject: [PATCH 17/26] refactor to not sync last executed header for last finished ref meta --- epochStart/bootstrap/process.go | 48 ++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index da5b1f0206c..7728ecb844e 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -692,15 +692,19 @@ func (e *epochStartBootstrap) createSyncers() error { func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (map[string]data.HeaderHandler, error) { syncedHeaders := make(map[string]data.HeaderHandler) + + hashesToRequest := make([][]byte, 0) + shardIds := make([]uint32, 0) for _, epochStartData := range meta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { err := e.syncEpochStartDataInfo(meta, epochStartData, syncedHeaders) if err != nil { return nil, err } + + hashesToRequest = append(hashesToRequest, epochStartData.GetLastFinishedMetaBlock()) + shardIds = append(shardIds, core.MetachainShardId) } - hashesToRequest := make([][]byte, 0) - shardIds := make([]uint32, 0) syncedMetaHeaders, err := e.syncEpochStartMetaHeaders(meta, hashesToRequest, shardIds) if err != nil { return nil, err @@ -714,24 +718,19 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma } func (e *epochStartBootstrap) syncIntermediateMetaBlocksIfNeeded( - epochStartMeta data.HeaderHandler, - lastFinishedMetaBlockHash []byte, syncedHeaders map[string]data.HeaderHandler, + epochStartMeta data.HeaderHandler, + lastFinishedMetaForShard data.HeaderHandler, ) error { - lastFinished, ok := syncedHeaders[string(lastFinishedMetaBlockHash)] - if !ok { - return epochStart.ErrMissingHeader - } - hashToSync := epochStartMeta.GetPrevHash() currNonce := epochStartMeta.GetNonce() - lastFinishedNonce := lastFinished.GetNonce() + lastFinishedNonce := lastFinishedMetaForShard.GetNonce() if lastFinishedNonce >= currNonce { return nil } - for currNonce > lastFinished.GetNonce() { + for currNonce > lastFinishedNonce { // check if not already synced (when handled for the other shards) header, ok := syncedHeaders[string(hashToSync)] if ok { @@ -758,36 +757,41 @@ func (e *epochStartBootstrap) syncEpochStartDataInfo( epochStartData data.EpochStartShardDataHandler, syncedHeaders map[string]data.HeaderHandler, ) error { - err := e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetHeaderHash(), epochStartData.GetShardID()) + syncedHeader, err := e.syncOneHeader(epochStartData.GetHeaderHash(), epochStartData.GetShardID()) if err != nil { return err } + syncedHeaders[string(epochStartData.GetHeaderHash())] = syncedHeader - // epoch start data header should have been synced up to this point - syncedHeader, ok := syncedHeaders[string(epochStartData.GetHeaderHash())] - if !ok { - return epochStart.ErrMissingHeader - } if !syncedHeader.IsHeaderV3() { return nil } - err = e.syncLastNotarizedMetaForEpochStartData(syncedHeader, syncedHeaders) + err = e.requestBlocksUpToLastExecuted(syncedHeaders, syncedHeader, epochStartData.GetShardID()) + if err != nil { + return err + } + + // sync last notarized meta header references by epoch start header for shard + // this will sync based on the meta block hashes references on header and based on the provided LastFinishedMetaBlock + err = e.syncLastNotarizedMetaForEpochStartData(syncedHeaders, syncedHeader) if err != nil { return err } - err = e.requestIntermediateBlocksIfNeeded(syncedHeaders, epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) + lastFinishedMetaBlockForShard, err := e.syncOneHeader(epochStartData.GetLastFinishedMetaBlock(), core.MetachainShardId) if err != nil { return err } + syncedHeaders[string(epochStartData.GetLastFinishedMetaBlock())] = lastFinishedMetaBlockForShard - return e.syncIntermediateMetaBlocksIfNeeded(epochStartMeta, epochStartData.GetLastFinishedMetaBlock(), syncedHeaders) + // sync meta blocks from epoch start meta blocks up to last finished metablock referenced on shard + return e.syncIntermediateMetaBlocksIfNeeded(syncedHeaders, epochStartMeta, lastFinishedMetaBlockForShard) } func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( - header data.HeaderHandler, syncedHeaders map[string]data.HeaderHandler, + header data.HeaderHandler, ) error { shardHeader, ok := header.(data.ShardHeaderHandler) if !ok { @@ -886,7 +890,7 @@ func (e *epochStartBootstrap) syncHeadersFrom(meta data.MetaHeaderHandler) (map[ return syncedHeaders, nil } -func (e *epochStartBootstrap) requestIntermediateBlocksIfNeeded( +func (e *epochStartBootstrap) requestHeaderAndIntermediateBlocksUpToLastExecuted( syncedHeaders map[string]data.HeaderHandler, headerHash []byte, shardID uint32, From f58157e68058f9de96bac7b39cd9929cfb1e25b5 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 24 Dec 2025 13:37:24 +0200 Subject: [PATCH 18/26] fixes after review - typos --- epochStart/bootstrap/metaStorageHandler.go | 4 ++-- epochStart/bootstrap/process.go | 2 +- epochStart/bootstrap/startInEpochScheduled.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index 271392332d3..26f90470bea 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -199,7 +199,7 @@ func (msh *metaStorageHandler) getLastSelfNotarizedHeaders( lastSelfNotarizedHeaders = append(lastSelfNotarizedHeaders, bootstrapHdrInfo) } - bootstrapHdrInfoMeta, err := msh.getLastMetaBoostrapInfo(epochStartMeta, syncedHeaders) + bootstrapHdrInfoMeta, err := msh.getLastMetaBootstrapInfo(epochStartMeta, syncedHeaders) if err != nil { return nil, err } @@ -209,7 +209,7 @@ func (msh *metaStorageHandler) getLastSelfNotarizedHeaders( return lastSelfNotarizedHeaders, nil } -func (msh *metaStorageHandler) getLastMetaBoostrapInfo( +func (msh *metaStorageHandler) getLastMetaBootstrapInfo( epochStartMeta data.MetaHeaderHandler, syncedHeaders map[string]data.HeaderHandler, ) (bootstrapStorage.BootstrapHeaderInfo, error) { diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 7728ecb844e..b7805316841 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -804,7 +804,7 @@ func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( // if thare notarized meta headers, sync their previous meta header // get oldest referenced meta blocks (first in the list should be the oldest) - // and sync it's previous meta header + // and sync its previous meta header metaHash := shardHeader.GetMetaBlockHashes()[0] header, err := e.syncOneHeader(metaHash, core.MetachainShardId) diff --git a/epochStart/bootstrap/startInEpochScheduled.go b/epochStart/bootstrap/startInEpochScheduled.go index 7a5f3b05b87..4454bb96206 100644 --- a/epochStart/bootstrap/startInEpochScheduled.go +++ b/epochStart/bootstrap/startInEpochScheduled.go @@ -90,7 +90,7 @@ func (ses *startInEpochWithScheduledDataSyncer) IsInterfaceNil() bool { func (ses *startInEpochWithScheduledDataSyncer) getRequiredHeaderByHash( notarizedShardHeader data.ShardHeaderHandler, ) (data.ShardHeaderHandler, map[string]data.HeaderHandler, error) { - // TODO: analize the requested headers in this func, after andromeda commited blocks are final + // TODO: analyze the requested headers in this func, after andromeda committed blocks are final // it might not be needed to request based on prev header shardIDs, hashesToRequest := getShardIDAndHashesForIncludedMetaBlocks(notarizedShardHeader) From df9793fa75bb33f9efd06ea3a2ea590f119da685 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 24 Dec 2025 13:40:20 +0200 Subject: [PATCH 19/26] fixes after review - typos --- epochStart/bootstrap/process.go | 2 +- process/block/metablock.go | 4 ---- process/sync/baseSync.go | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index b7805316841..93b03f03e67 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -801,7 +801,7 @@ func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( if len(shardHeader.GetMetaBlockHashes()) <= 0 { return nil } - // if thare notarized meta headers, sync their previous meta header + // if there are notarized meta headers, sync their previous meta header // get oldest referenced meta blocks (first in the list should be the oldest) // and sync its previous meta header diff --git a/process/block/metablock.go b/process/block/metablock.go index 5a321f67e14..ac65fefee02 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -1409,10 +1409,6 @@ func (mp *metaProcessor) CommitBlock( nodesCoordinatorKey := mp.nodesCoordinator.GetSavedStateKey() epochStartKey := mp.epochStartTrigger.GetSavedStateKey() - log.Debug("getLastSelfNotarizedHeaders", - "hash", headerHash, - "nonoce", header.GetNonce(), - ) args := bootStorerDataArgs{ headerInfo: headerInfo, round: header.GetRound(), diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index e47af2556c4..0c14bb5a053 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -1766,7 +1766,7 @@ func (boot *baseBootstrap) getHeader(hash []byte) (data.HeaderHandler, error) { return process.GetShardHeader(hash, boot.headers, boot.marshalizer, boot.store) } -// getHeaderFromPool will try to get header from pool or storage +// getHeaderFromPool will try to get the header from pool func (boot *baseBootstrap) getHeaderFromPool(hash []byte) (data.HeaderHandler, error) { if boot.shardCoordinator.SelfId() == core.MetachainShardId { return process.GetMetaHeaderFromPool(hash, boot.headers) From 761ac1c854b839a7cc24839e0947af52b68cfa5b Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 24 Dec 2025 13:41:29 +0200 Subject: [PATCH 20/26] fix conflicts after merge --- process/sync/baseSync.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/process/sync/baseSync.go b/process/sync/baseSync.go index f2d4d3832f4..949fee5e320 100644 --- a/process/sync/baseSync.go +++ b/process/sync/baseSync.go @@ -1091,13 +1091,8 @@ func (boot *baseBootstrap) prepareForSyncIfNeeded(syncingNonce uint64) error { // if there are multiple headers in between the syncing header and the last one executed, // add them into the queue and pool -<<<<<<< HEAD - for i := lastExecutedNonce + 1; i < syncingNonce; i++ { - hdr, hdrHash, errGetHdr := boot.getHeaderWithNonce(i) -======= for i := lastExecutionResultHeaderNonce + 1; i < syncingNonce; i++ { - hdr, hdrHash, errGetHdr := boot.getHeaderFromPoolWithNonce(i) ->>>>>>> feat/supernova-async-exec + hdr, hdrHash, errGetHdr := boot.getHeaderWithNonce(i) if errGetHdr != nil { log.Debug("prepareForSyncIfNeeded: failed to get header with nonce", "nonce", i, "error", errGetHdr) return errGetHdr From 8abf8f7063c9bf38e7727e3f10468e0495bc8819 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Wed, 24 Dec 2025 14:11:35 +0200 Subject: [PATCH 21/26] fix linter issue --- epochStart/bootstrap/process.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 93b03f03e67..f2b656cdf32 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -890,20 +890,6 @@ func (e *epochStartBootstrap) syncHeadersFrom(meta data.MetaHeaderHandler) (map[ return syncedHeaders, nil } -func (e *epochStartBootstrap) requestHeaderAndIntermediateBlocksUpToLastExecuted( - syncedHeaders map[string]data.HeaderHandler, - headerHash []byte, - shardID uint32, -) error { - header, err := e.syncOneHeader(headerHash, shardID) - if err != nil { - return err - } - syncedHeaders[string(headerHash)] = header - - return e.requestBlocksUpToLastExecuted(syncedHeaders, header, shardID) -} - func (e *epochStartBootstrap) requestBlocksUpToLastExecuted( syncedHeaders map[string]data.HeaderHandler, header data.HeaderHandler, From 61401da07558141b067ea5e006a07ab727a0db52 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 29 Dec 2025 15:31:02 +0200 Subject: [PATCH 22/26] get ref meta header for last self notarized headers --- epochStart/bootstrap/metaStorageHandler.go | 56 ++++---- epochStart/bootstrap/process.go | 157 ++++++++++++++++++--- 2 files changed, 165 insertions(+), 48 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index 26f90470bea..be1f3e5fb25 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -233,57 +233,49 @@ func (msh *metaStorageHandler) getLastMetaBootstrapInfo( return bootstrapHdrInfoMeta, nil } -func (msh *metaStorageHandler) getLastNotarizedBootstrapInfoForEpochStartData( - epochStartData data.EpochStartShardDataHandler, +func fetchPrevHeader( syncedHeaders map[string]data.HeaderHandler, -) (bootstrapStorage.BootstrapHeaderInfo, error) { - lastFinishedMetaBlockHash := epochStartData.GetLastFinishedMetaBlock() - lastFinishedMetaBlock, ok := syncedHeaders[string(lastFinishedMetaBlockHash)] - if !ok { - return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader - } - - shardHeaderHash := epochStartData.GetHeaderHash() - shardHeader, ok := syncedHeaders[string(shardHeaderHash)] + header data.HeaderHandler, +) (data.ShardHeaderHandler, error) { + prevHash := header.GetPrevHash() + syncedHeader, ok := syncedHeaders[string(prevHash)] if !ok { - return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader + return nil, epochStart.ErrMissingHeader } - shardHeaderHandler, ok := shardHeader.(data.ShardHeaderHandler) + shardHeader, ok := syncedHeader.(data.ShardHeaderHandler) if !ok { - return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrWrongTypeAssertion + return nil, epochStart.ErrWrongTypeAssertion } - if len(shardHeaderHandler.GetMetaBlockHashes()) <= 0 { - return bootstrapStorage.BootstrapHeaderInfo{ - ShardId: epochStartData.GetShardID(), - Epoch: lastFinishedMetaBlock.GetEpoch(), - Nonce: lastFinishedMetaBlock.GetNonce(), - Hash: lastFinishedMetaBlockHash, - }, nil - } + return shardHeader, nil +} - metaHash := shardHeaderHandler.GetMetaBlockHashes()[0] - metaHeader, ok := syncedHeaders[string(metaHash)] +func (msh *metaStorageHandler) getLastNotarizedBootstrapInfoForEpochStartData( + epochStartData data.EpochStartShardDataHandler, + syncedHeaders map[string]data.HeaderHandler, +) (bootstrapStorage.BootstrapHeaderInfo, error) { + shardHeaderHash := epochStartData.GetHeaderHash() + shardHeader, ok := syncedHeaders[string(shardHeaderHash)] if !ok { return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader } - prevHash := metaHeader.GetPrevHash() + lastReferencedMetaHash, err := getLastReferencedMetaHash(syncedHeaders, fetchPrevHeader, shardHeader) + if err != nil { + return bootstrapStorage.BootstrapHeaderInfo{}, err + } - prevMetaHeader, ok := syncedHeaders[string(prevHash)] + lastReferencesMetaBlock, ok := syncedHeaders[string(lastReferencedMetaHash)] if !ok { return bootstrapStorage.BootstrapHeaderInfo{}, epochStart.ErrMissingHeader } - lastFinishedMetaBlockHash = prevHash - lastFinishedMetaBlock = prevMetaHeader - bootstrapHdrInfo := bootstrapStorage.BootstrapHeaderInfo{ ShardId: epochStartData.GetShardID(), - Epoch: lastFinishedMetaBlock.GetEpoch(), - Nonce: lastFinishedMetaBlock.GetNonce(), - Hash: lastFinishedMetaBlockHash, + Epoch: lastReferencesMetaBlock.GetEpoch(), + Nonce: lastReferencesMetaBlock.GetNonce(), + Hash: lastReferencedMetaHash, } return bootstrapHdrInfo, nil diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index f2b656cdf32..293ce0aba03 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -793,34 +793,159 @@ func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( syncedHeaders map[string]data.HeaderHandler, header data.HeaderHandler, ) error { - shardHeader, ok := header.(data.ShardHeaderHandler) - if !ok { - return epochStart.ErrWrongTypeAssertion + lastReferencedMetaHash, err := getLastReferencedMetaHash(syncedHeaders, e.syncPrevShardHeaderHandler, header) + if err != nil { + return err } - if len(shardHeader.GetMetaBlockHashes()) <= 0 { - return nil + syncedHeader, err := e.syncOneHeader(lastReferencedMetaHash, core.MetachainShardId) + if err != nil { + return err } - // if there are notarized meta headers, sync their previous meta header + syncedHeaders[string(lastReferencedMetaHash)] = syncedHeader - // get oldest referenced meta blocks (first in the list should be the oldest) - // and sync its previous meta header - metaHash := shardHeader.GetMetaBlockHashes()[0] + return nil +} - header, err := e.syncOneHeader(metaHash, core.MetachainShardId) +func getLastReferencedMetaHash( + syncedHeaders map[string]data.HeaderHandler, + fetchPrevHeader func(syncedHeaders map[string]data.HeaderHandler, header data.HeaderHandler) (data.ShardHeaderHandler, error), + header data.HeaderHandler, +) ([]byte, error) { + // get last execution result header for epoch start data shard header + lastExecutionResult, err := common.GetLastBaseExecutionResultHandler(header) if err != nil { - return err + return nil, err + } + + lastExecutedHeader, ok := syncedHeaders[string(lastExecutionResult.GetHeaderHash())] + if !ok { + return nil, epochStart.ErrMissingHeader } - syncedHeaders[string(metaHash)] = header + lastExecutedShardHeader, ok := lastExecutedHeader.(data.ShardHeaderHandler) + if !ok { + return nil, epochStart.ErrWrongTypeAssertion + } + + // for last self notarized header + // get it based on epoch start data shard header + // - based on it's last executed header + // - and get last referenced meta + // - if there are references meta get last finished and last pending + // - if there aren't, go and search to prev header, and so on + + currentHdr := lastExecutedShardHeader + for { + numIncludedMetaBlocks := len(currentHdr.GetMetaBlockHashes()) + + // if there are no included meta blocks, go to prev header + if numIncludedMetaBlocks == 0 { + header, err := fetchPrevHeader(syncedHeaders, currentHdr) + if err != nil { + return nil, err + } + + currentHdr = header + continue + } + + // if there are notarized meta headers, return last included meta header + metaHash := currentHdr.GetMetaBlockHashes()[numIncludedMetaBlocks-1] + + return metaHash, nil + } +} + +func (e *epochStartBootstrap) syncPrevShardHeaderHandler( + syncedHeaders map[string]data.HeaderHandler, + header data.HeaderHandler, +) (data.ShardHeaderHandler, error) { prevHash := header.GetPrevHash() - header, err = e.syncOneHeader(prevHash, core.MetachainShardId) + syncedHeader, err := e.syncOneHeader(prevHash, core.MetachainShardId) if err != nil { - return err + return nil, err } - syncedHeaders[string(prevHash)] = header + syncedHeaders[string(prevHash)] = syncedHeader - return nil + shardHeader, ok := syncedHeader.(data.ShardHeaderHandler) + if !ok { + return nil, epochStart.ErrWrongTypeAssertion + } + + return shardHeader, nil +} + +func (e *epochStartBootstrap) getLastRefMetaHash( + syncedHeaders map[string]data.HeaderHandler, + header data.ShardHeaderHandler, +) ([]byte, error) { + shardHeader, ok := header.(data.ShardHeaderHandler) + if !ok { + return nil, epochStart.ErrWrongTypeAssertion + } + + var lastFinalizedRefMetaHash []byte + var firstPendingMetaHash []byte + + for currentHdr := shardHeader; currentHdr.GetNonce() > 0; { + if len(currentHdr.GetMetaBlockHashes()) == 0 { + shardHeader, err := e.syncPrevShardHeaderHandler(syncedHeaders, currentHdr) + if err != nil { + return nil, err + } + + currentHdr = shardHeader + continue + } + + numIncludedMetaHeaders := len(currentHdr.GetMetaBlockHashes()) + if numIncludedMetaHeaders > 1 { + if len(firstPendingMetaHash) == 0 { + lastFinalizedRefMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-2] + return lastFinalizedRefMetaHash, nil + } + + if bytes.Equal(firstPendingMetaHash, currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1]) { + lastFinalizedRefMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-2] + return lastFinalizedRefMetaHash, nil + + } + + lastFinalizedRefMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1] + return lastFinalizedRefMetaHash, nil + } + + if len(firstPendingMetaHash) == 0 { + firstPendingMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1] + + shardHeader, err := e.syncPrevShardHeaderHandler(syncedHeaders, currentHdr) + if err != nil { + return nil, err + } + + currentHdr = shardHeader + continue + } + + // if there is an included meta header, we consider it first pending meta hash + // and we have to go backwards to previous headers and find last finalized referenced meta hash. + // last finalized meta hash will be the first hash different from first pending meta hash + + lastFinalizedMetaHash := currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1] + if !bytes.Equal(firstPendingMetaHash, lastFinalizedMetaHash) { + return lastFinalizedMetaHash, nil + } + + shardHeader, err := e.syncPrevShardHeaderHandler(syncedHeaders, currentHdr) + if err != nil { + return nil, err + } + + currentHdr = shardHeader + } + + return lastFinalizedRefMetaHash, nil } func (e *epochStartBootstrap) syncEpochStartMetaHeaders( From 73b2142572eb088592ece421217410810f601313 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 29 Dec 2025 15:57:13 +0200 Subject: [PATCH 23/26] fixes after review --- epochStart/bootstrap/metaStorageHandler.go | 1 - epochStart/bootstrap/process.go | 40 +++++----------------- epochStart/bootstrap/process_test.go | 2 ++ process/block/baseProcess.go | 6 ++-- 4 files changed, 14 insertions(+), 35 deletions(-) diff --git a/epochStart/bootstrap/metaStorageHandler.go b/epochStart/bootstrap/metaStorageHandler.go index be1f3e5fb25..9b216dee234 100644 --- a/epochStart/bootstrap/metaStorageHandler.go +++ b/epochStart/bootstrap/metaStorageHandler.go @@ -190,7 +190,6 @@ func (msh *metaStorageHandler) getLastSelfNotarizedHeaders( } for _, epochStartData := range epochStartMeta.GetEpochStartHandler().GetLastFinalizedHeaderHandlers() { - bootstrapHdrInfo, err := msh.getLastNotarizedBootstrapInfoForEpochStartData(epochStartData, syncedHeaders) if err != nil { return nil, err diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 293ce0aba03..399e8ecca7e 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -717,20 +717,19 @@ func (e *epochStartBootstrap) syncHeadersV3From(meta data.MetaHeaderHandler) (ma return syncedHeaders, nil } -func (e *epochStartBootstrap) syncIntermediateMetaBlocksIfNeeded( +func (e *epochStartBootstrap) syncIntermediateBlocksIfNeeded( syncedHeaders map[string]data.HeaderHandler, - epochStartMeta data.HeaderHandler, - lastFinishedMetaForShard data.HeaderHandler, + header data.HeaderHandler, + lastExecutedNonce uint64, ) error { - hashToSync := epochStartMeta.GetPrevHash() - currNonce := epochStartMeta.GetNonce() + hashToSync := header.GetPrevHash() + currNonce := header.GetNonce() - lastFinishedNonce := lastFinishedMetaForShard.GetNonce() - if lastFinishedNonce >= currNonce { + if lastExecutedNonce >= currNonce { return nil } - for currNonce > lastFinishedNonce { + for currNonce > lastExecutedNonce { // check if not already synced (when handled for the other shards) header, ok := syncedHeaders[string(hashToSync)] if ok { @@ -786,7 +785,7 @@ func (e *epochStartBootstrap) syncEpochStartDataInfo( syncedHeaders[string(epochStartData.GetLastFinishedMetaBlock())] = lastFinishedMetaBlockForShard // sync meta blocks from epoch start meta blocks up to last finished metablock referenced on shard - return e.syncIntermediateMetaBlocksIfNeeded(syncedHeaders, epochStartMeta, lastFinishedMetaBlockForShard) + return e.syncIntermediateBlocksIfNeeded(syncedHeaders, epochStartMeta, lastFinishedMetaBlockForShard.GetNonce()) } func (e *epochStartBootstrap) syncLastNotarizedMetaForEpochStartData( @@ -1029,28 +1028,7 @@ func (e *epochStartBootstrap) requestBlocksUpToLastExecuted( return err } - baseHeaderNonce := header.GetNonce() - lastExecutedNonce := lastExecutionResult.GetHeaderNonce() - - if lastExecutedNonce >= baseHeaderNonce { - return nil - } - - headerHashToSync := header.GetPrevHash() - currentNonce := baseHeaderNonce - for currentNonce > lastExecutedNonce { - syncedHeader, err := e.syncOneHeader(headerHashToSync, shardID) - if err != nil { - return err - } - - syncedHeaders[string(headerHashToSync)] = syncedHeader - - headerHashToSync = syncedHeader.GetPrevHash() - currentNonce = syncedHeader.GetNonce() - } - - return nil + return e.syncIntermediateBlocksIfNeeded(syncedHeaders, header, lastExecutionResult.GetHeaderNonce()) } func (e *epochStartBootstrap) syncOneHeader( diff --git a/epochStart/bootstrap/process_test.go b/epochStart/bootstrap/process_test.go index 7746e8a0c8f..b839ad9ec92 100644 --- a/epochStart/bootstrap/process_test.go +++ b/epochStart/bootstrap/process_test.go @@ -2870,6 +2870,7 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { LastExecutionResult: &block.ExecutionResultInfo{ ExecutionResult: &block.BaseExecutionResult{ HeaderNonce: 10, + HeaderHash: hdrHash3, }, }, } @@ -2881,6 +2882,7 @@ func TestEpochStartBoostrap_SyncHeadersV3FromMeta(t *testing.T) { header3 := &block.HeaderV3{ Nonce: 10, LastExecutionResult: &block.ExecutionResultInfo{}, + MetaBlockHashes: [][]byte{hdrHash4, lastExecMetaHash}, } lastExecMeta := &block.MetaBlockV3{ diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index e48e956c7f0..a2979718b0e 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -3765,14 +3765,14 @@ func (bp *baseProcessor) getBlockBodyFromPool( func (bp *baseProcessor) getHeaderFromHash( isHeaderV3 bool, - shardHeaderHash []byte, + headerHash []byte, shardID uint32, ) (data.HeaderHandler, error) { if isHeaderV3 { - return process.GetHeader(shardHeaderHash, bp.dataPool.Headers(), bp.store, bp.marshalizer, shardID) + return process.GetHeader(headerHash, bp.dataPool.Headers(), bp.store, bp.marshalizer, shardID) } - headerInfo, ok := bp.hdrsForCurrBlock.GetHeaderInfo(string(shardHeaderHash)) + headerInfo, ok := bp.hdrsForCurrBlock.GetHeaderInfo(string(headerHash)) if !ok { return nil, process.ErrMissingHeader } From 8661f6c3fc8682fdd9df7bcd780628173c4edfd6 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 29 Dec 2025 16:00:03 +0200 Subject: [PATCH 24/26] remove unused code --- epochStart/bootstrap/process.go | 79 --------------------------------- 1 file changed, 79 deletions(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 399e8ecca7e..027fcd0e1a6 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -827,13 +827,6 @@ func getLastReferencedMetaHash( return nil, epochStart.ErrWrongTypeAssertion } - // for last self notarized header - // get it based on epoch start data shard header - // - based on it's last executed header - // - and get last referenced meta - // - if there are references meta get last finished and last pending - // - if there aren't, go and search to prev header, and so on - currentHdr := lastExecutedShardHeader for { numIncludedMetaBlocks := len(currentHdr.GetMetaBlockHashes()) @@ -875,78 +868,6 @@ func (e *epochStartBootstrap) syncPrevShardHeaderHandler( return shardHeader, nil } -func (e *epochStartBootstrap) getLastRefMetaHash( - syncedHeaders map[string]data.HeaderHandler, - header data.ShardHeaderHandler, -) ([]byte, error) { - shardHeader, ok := header.(data.ShardHeaderHandler) - if !ok { - return nil, epochStart.ErrWrongTypeAssertion - } - - var lastFinalizedRefMetaHash []byte - var firstPendingMetaHash []byte - - for currentHdr := shardHeader; currentHdr.GetNonce() > 0; { - if len(currentHdr.GetMetaBlockHashes()) == 0 { - shardHeader, err := e.syncPrevShardHeaderHandler(syncedHeaders, currentHdr) - if err != nil { - return nil, err - } - - currentHdr = shardHeader - continue - } - - numIncludedMetaHeaders := len(currentHdr.GetMetaBlockHashes()) - if numIncludedMetaHeaders > 1 { - if len(firstPendingMetaHash) == 0 { - lastFinalizedRefMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-2] - return lastFinalizedRefMetaHash, nil - } - - if bytes.Equal(firstPendingMetaHash, currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1]) { - lastFinalizedRefMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-2] - return lastFinalizedRefMetaHash, nil - - } - - lastFinalizedRefMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1] - return lastFinalizedRefMetaHash, nil - } - - if len(firstPendingMetaHash) == 0 { - firstPendingMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1] - - shardHeader, err := e.syncPrevShardHeaderHandler(syncedHeaders, currentHdr) - if err != nil { - return nil, err - } - - currentHdr = shardHeader - continue - } - - // if there is an included meta header, we consider it first pending meta hash - // and we have to go backwards to previous headers and find last finalized referenced meta hash. - // last finalized meta hash will be the first hash different from first pending meta hash - - lastFinalizedMetaHash := currentHdr.GetMetaBlockHashes()[numIncludedMetaHeaders-1] - if !bytes.Equal(firstPendingMetaHash, lastFinalizedMetaHash) { - return lastFinalizedMetaHash, nil - } - - shardHeader, err := e.syncPrevShardHeaderHandler(syncedHeaders, currentHdr) - if err != nil { - return nil, err - } - - currentHdr = shardHeader - } - - return lastFinalizedRefMetaHash, nil -} - func (e *epochStartBootstrap) syncEpochStartMetaHeaders( meta data.MetaHeaderHandler, hashesToRequest [][]byte, From 67853596afa7d86030c72ca6ba6bcf62d5dee488 Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 29 Dec 2025 16:58:10 +0200 Subject: [PATCH 25/26] fix request shard id --- epochStart/bootstrap/process.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 027fcd0e1a6..44cdd828cfb 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -722,6 +722,8 @@ func (e *epochStartBootstrap) syncIntermediateBlocksIfNeeded( header data.HeaderHandler, lastExecutedNonce uint64, ) error { + shardID := header.GetShardID() + hashToSync := header.GetPrevHash() currNonce := header.GetNonce() @@ -738,7 +740,7 @@ func (e *epochStartBootstrap) syncIntermediateBlocksIfNeeded( continue } - header, err := e.syncOneHeader(hashToSync, core.MetachainShardId) + header, err := e.syncOneHeader(hashToSync, shardID) if err != nil { return err } @@ -766,7 +768,7 @@ func (e *epochStartBootstrap) syncEpochStartDataInfo( return nil } - err = e.requestBlocksUpToLastExecuted(syncedHeaders, syncedHeader, epochStartData.GetShardID()) + err = e.syncBlocksUpToLastExecuted(syncedHeaders, syncedHeader, epochStartData.GetShardID()) if err != nil { return err } @@ -854,7 +856,7 @@ func (e *epochStartBootstrap) syncPrevShardHeaderHandler( header data.HeaderHandler, ) (data.ShardHeaderHandler, error) { prevHash := header.GetPrevHash() - syncedHeader, err := e.syncOneHeader(prevHash, core.MetachainShardId) + syncedHeader, err := e.syncOneHeader(prevHash, header.GetShardID()) if err != nil { return nil, err } @@ -884,7 +886,7 @@ func (e *epochStartBootstrap) syncEpochStartMetaHeaders( // sync meta header with intermediate blocks up to last executed (for supernova) syncedHeaders := make(map[string]data.HeaderHandler) - err = e.requestBlocksUpToLastExecuted(syncedHeaders, meta, core.MetachainShardId) + err = e.syncBlocksUpToLastExecuted(syncedHeaders, meta, core.MetachainShardId) if err != nil { return nil, err } @@ -935,7 +937,7 @@ func (e *epochStartBootstrap) syncHeadersFrom(meta data.MetaHeaderHandler) (map[ return syncedHeaders, nil } -func (e *epochStartBootstrap) requestBlocksUpToLastExecuted( +func (e *epochStartBootstrap) syncBlocksUpToLastExecuted( syncedHeaders map[string]data.HeaderHandler, header data.HeaderHandler, shardID uint32, From 4f5f4eee3f302fc30a8276baca4e22cbd05e7efe Mon Sep 17 00:00:00 2001 From: ssd04 Date: Mon, 29 Dec 2025 17:48:23 +0200 Subject: [PATCH 26/26] fixes after review --- epochStart/bootstrap/process.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/epochStart/bootstrap/process.go b/epochStart/bootstrap/process.go index 44cdd828cfb..97495c67dfe 100644 --- a/epochStart/bootstrap/process.go +++ b/epochStart/bootstrap/process.go @@ -829,26 +829,28 @@ func getLastReferencedMetaHash( return nil, epochStart.ErrWrongTypeAssertion } + var lastReferencedMetaHash []byte + currentHdr := lastExecutedShardHeader - for { + for currentHdr.GetNonce() > 0 { numIncludedMetaBlocks := len(currentHdr.GetMetaBlockHashes()) - // if there are no included meta blocks, go to prev header - if numIncludedMetaBlocks == 0 { - header, err := fetchPrevHeader(syncedHeaders, currentHdr) - if err != nil { - return nil, err - } - - currentHdr = header - continue + // if there are notarized meta headers, return last included meta header + if numIncludedMetaBlocks > 0 { + lastReferencedMetaHash = currentHdr.GetMetaBlockHashes()[numIncludedMetaBlocks-1] + break } - // if there are notarized meta headers, return last included meta header - metaHash := currentHdr.GetMetaBlockHashes()[numIncludedMetaBlocks-1] + // if there are no included meta blocks, go to prev header + header, err := fetchPrevHeader(syncedHeaders, currentHdr) + if err != nil { + return nil, err + } - return metaHash, nil + currentHdr = header } + + return lastReferencedMetaHash, nil } func (e *epochStartBootstrap) syncPrevShardHeaderHandler(