github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/chunks/handle_check_internal.go (about) 1 // Copyright 2021 The TrueBlocks Authors. All rights reserved. 2 // Use of this source code is governed by a license that can 3 // be found in the LICENSE file. 4 5 package chunksPkg 6 7 import ( 8 "errors" 9 "fmt" 10 "strings" 11 12 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 13 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config" 14 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/index" 15 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types" 16 ) 17 18 // CheckInternal reads the header of each chunk on disc looking for the Magic number and 19 // the hash of the spec version for expected values. 20 func (opts *ChunksOptions) CheckInternal(fileNames []string, blockNums []base.Blknum, report *types.ReportCheck) error { 21 for _, fileName := range fileNames { 22 opts.checkIndexChunkInternal(fileName, false /* check version */, report) 23 // opts.checkBloomInternal(testId, fileName, report) 24 } 25 return nil 26 } 27 28 func (opts *ChunksOptions) checkIndexChunkInternal(fileName string, checkVersion bool, report *types.ReportCheck) { 29 report.VisitedCnt++ 30 report.CheckedCnt++ 31 32 fileName = index.ToIndexPath(fileName) 33 indexChunk, err := index.OpenIndex(fileName, true /* check */) 34 if err != nil { 35 if strings.Contains(err.Error(), "no such file or directory") { 36 // This is the case where the user did not download all the index chunks, only blooms 37 report.PassedCnt++ 38 } else if !checkVersion && errors.Is(err, index.ErrIncorrectHash) { 39 report.PassedCnt++ 40 } else { 41 report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("%s: %s", err, fileName)) 42 } 43 } else { 44 report.PassedCnt++ 45 if !checkVersion { 46 opts.checkSnaps(fileName, &indexChunk, report) 47 } 48 } 49 50 indexChunk.Close() 51 } 52 53 func (opts *ChunksOptions) checkSnaps(fileName string, indexChunk *index.Index, report *types.ReportCheck) { 54 report.VisitedCnt++ 55 report.CheckedCnt++ 56 57 // we will check the manifest since it's the gold standard 58 isSnap := func(fR base.FileRange, snapMarker, firstSnap base.Blknum) bool { 59 return fR.Last >= firstSnap && fR.Last%snapMarker == 0 60 } 61 62 chain := opts.Globals.Chain 63 firstSnap := base.Blknum(config.GetScrape(chain).FirstSnap) 64 snapMarker := base.Blknum(config.GetScrape(chain).SnapToGrid) 65 appsPer := uint32(config.GetScrape(chain).AppsPerChunk) 66 if fR, err := base.RangeFromFilenameE(fileName); err != nil { 67 report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("%s: %s", err, fileName)) 68 } else { 69 if isSnap(fR, snapMarker, firstSnap) { 70 if fR.Last < firstSnap { 71 // Is there a snap_to_grid after first_snap everywhere it's supposed to be? 72 report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("checkSnap: snap too early %s firstSnap=%d", fR, firstSnap)) 73 } else if indexChunk.Header.AppearanceCount >= appsPer { 74 // For snapped chunks, nApps < apps_per_chunk. 75 report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("contract: too many apps at %s appsPer=%d", fR, appsPer)) 76 } else { 77 report.PassedCnt++ 78 } 79 } else { 80 if indexChunk.Header.AppearanceCount < appsPer && fR.Last > 0 { 81 // For non-snapped chunks, nApps ≥ apps_per_chunk. 82 report.MsgStrings = append(report.MsgStrings, fmt.Sprintf("checkSnap: too few appearances at %s appsPer=%d", fR, appsPer)) 83 } else { 84 report.PassedCnt++ 85 } 86 } 87 } 88 }