github.com/gochain-io/gochain@v2.2.26+incompatible/cmd/gochain-ethdb/check.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "flag" 8 "fmt" 9 "path/filepath" 10 11 "github.com/gochain-io/gochain/ethdb" 12 ) 13 14 var ( 15 ErrUnsupportedCheckType = errors.New("unsupported check type") 16 ) 17 18 type CheckCommand struct{} 19 20 func NewCheckCommand() *CheckCommand { 21 return &CheckCommand{} 22 } 23 24 func (cmd *CheckCommand) Run(args []string) error { 25 // Parse flags. 26 fs := flag.NewFlagSet("gochain-ethdb-check", flag.ContinueOnError) 27 if err := fs.Parse(args); err != nil { 28 return err 29 } 30 31 if fs.NArg() == 0 { 32 return errors.New("path required") 33 } 34 35 // Iterate over each path passed in. 36 for _, path := range fs.Args() { 37 if err := cmd.check(path); err == ErrUnsupportedCheckType { 38 fmt.Printf("%s: not currently supported, skipping\n", path) 39 continue 40 } else if err != nil { 41 return fmt.Errorf("%s: %s", path, err) 42 } 43 } 44 return nil 45 } 46 47 func (cmd *CheckCommand) check(path string) error { 48 typ, err := ethdb.SegmentFileType(path) 49 if err != nil { 50 return err 51 } 52 53 switch typ { 54 case ethdb.SegmentLDB1: 55 return cmd.checkLDBSegment(path) 56 case ethdb.SegmentETH1: 57 return cmd.checkETHSegment(path) 58 default: 59 return fmt.Errorf("unknown segment type: %q", typ) 60 } 61 } 62 63 func (cmd *CheckCommand) checkLDBSegment(path string) error { 64 return ErrUnsupportedCheckType 65 } 66 67 func (cmd *CheckCommand) checkETHSegment(path string) error { 68 s := ethdb.NewFileSegment(filepath.Base(path), path) 69 if err := s.Open(); err != nil { 70 return err 71 } 72 defer s.Close() 73 74 // Print stats. 75 fmt.Printf("[eth1] %s\n", path) 76 fmt.Printf("SIZE: %d bytes\n", s.Size()) 77 fmt.Printf("IDX: %d bytes\n", len(s.Index())) 78 fmt.Printf("LEN: %d items\n", s.Len()) 79 fmt.Printf("CAP: %d items\n", s.Cap()) 80 fmt.Printf("CHKSUM: %x\n", s.Checksum()) 81 82 // Verify checksum integrity. 83 if chksum, err := ethdb.ChecksumFileSegment(path); err != nil { 84 return err 85 } else if !bytes.Equal(chksum, s.Checksum()) { 86 return fmt.Errorf("checksum mismatch: %x != %x", chksum, s.Checksum()) 87 } 88 89 // Verify index is the correct size. 90 if len(s.Index()) != s.Cap()*8 { 91 return fmt.Errorf("unexpected index size: %d != %d", len(s.Index()), s.Cap()*8) 92 } 93 94 // Verify every index in bounds. 95 data, idx := s.Data(), s.Index() 96 for i := 0; i < s.Cap(); i++ { 97 offset := int64(binary.BigEndian.Uint64(idx[i*8:])) 98 if offset == 0 { 99 continue 100 } else if offset > int64(len(data)) { 101 return fmt.Errorf("offset out of bound: i=%d offset=%d", i, offset) 102 } 103 } 104 105 fmt.Println("") 106 107 return nil 108 }