github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/internal/chunks/handle_address.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 "encoding/binary" 9 "errors" 10 "fmt" 11 "io" 12 "strings" 13 14 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 15 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config" 16 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/file" 17 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/index" 18 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/output" 19 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/tslib" 20 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types" 21 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/walk" 22 ) 23 24 func (opts *ChunksOptions) HandleAddresses(rCtx *output.RenderCtx, blockNums []base.Blknum) error { 25 chain := opts.Globals.Chain 26 been_here := 0 27 fetchData := func(modelChan chan types.Modeler, errorChan chan error) { 28 var showAddresses func(walker *walk.CacheWalker, path string, first bool) (bool, error) 29 if opts.Globals.Verbose { 30 showAddresses = func(walker *walk.CacheWalker, path string, first bool) (bool, error) { 31 return opts.handleResolvedRecords1(modelChan, walker, path) 32 } 33 } else { 34 showAddresses = func(walker *walk.CacheWalker, path string, first bool) (bool, error) { 35 if path != index.ToBloomPath(path) { 36 return false, fmt.Errorf("should not happen in showAddresses") 37 } 38 39 path = index.ToIndexPath(path) 40 if !file.FileExists(path) { 41 // This is okay, if the user used chifra init without the --all option. Warn them and continue 42 msg := "" 43 path = strings.Replace(path, config.PathToIndex(chain)+"/", "$indexPath/", 1) 44 if been_here < 3 { 45 msg = fmt.Sprintf("index file %s does not exist. Run 'chifra init --all' to create it.", path) 46 } else if been_here == 3 { 47 msg = fmt.Sprintf("index file %s does not exist. Warnings turned off...", path) 48 } 49 if msg != "" { 50 errorChan <- errors.New(msg) 51 } 52 been_here++ 53 return true, nil 54 } 55 56 indexChunk, err := index.OpenIndex(path, true /* check */) 57 if err != nil { 58 return false, err 59 } 60 defer indexChunk.Close() 61 62 _, err = indexChunk.File.Seek(int64(index.HeaderWidth), io.SeekStart) 63 if err != nil { 64 return false, err 65 } 66 67 cnt := 0 68 for i := 0; i < int(indexChunk.Header.AddressCount); i++ { 69 if opts.Globals.TestMode && i > walker.MaxTests() { 70 continue 71 } 72 73 obj := types.AddrRecord{} 74 if err := binary.Read(indexChunk.File, binary.LittleEndian, &obj); err != nil { 75 return false, err 76 } 77 78 rng := indexChunk.Range 79 s := types.ChunkAddress{ 80 Address: obj.Address, 81 Range: rng.String(), 82 Offset: uint64(obj.Offset), 83 Count: uint64(obj.Count), 84 } 85 rd := tslib.RangeToBounds(chain, &rng) 86 s.RangeDates = &rd 87 88 modelChan <- &s 89 cnt++ 90 } 91 return true, nil 92 } 93 } 94 95 walker := walk.NewCacheWalker( 96 chain, 97 opts.Globals.TestMode, 98 10, /* maxTests */ 99 showAddresses, 100 ) 101 if err := walker.WalkBloomFilters(blockNums); err != nil { 102 errorChan <- err 103 rCtx.Cancel() 104 } 105 } 106 107 return output.StreamMany(rCtx, fetchData, opts.Globals.OutputOpts()) 108 }