@@ -11,10 +11,12 @@ import (
11
11
12
12
"github.com/BurntSushi/toml"
13
13
"github.com/dustin/go-humanize"
14
+ cbor "github.com/ipfs/go-ipld-cbor"
14
15
"github.com/samber/lo"
15
16
"golang.org/x/xerrors"
16
17
17
18
"github.com/filecoin-project/go-address"
19
+ "github.com/filecoin-project/go-bitfield"
18
20
"github.com/filecoin-project/go-jsonrpc"
19
21
"github.com/filecoin-project/go-state-types/abi"
20
22
"github.com/filecoin-project/go-state-types/big"
@@ -24,6 +26,8 @@ import (
24
26
"github.com/filecoin-project/curio/deps/config"
25
27
"github.com/filecoin-project/curio/harmony/harmonydb"
26
28
29
+ "github.com/filecoin-project/lotus/blockstore"
30
+ "github.com/filecoin-project/lotus/chain/actors/adt"
27
31
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
28
32
"github.com/filecoin-project/lotus/chain/types"
29
33
cliutil "github.com/filecoin-project/lotus/cli/util"
@@ -717,3 +721,81 @@ func chainSyncCheck(al *alerts) {
717
721
}
718
722
}
719
723
}
724
+
725
+ func missingSectorCheck (al * alerts ) {
726
+ Name := "MissingSectors"
727
+ al .alertMap [Name ] = & alertOut {}
728
+
729
+ var sectors []struct {
730
+ MinerID int64 `db:"miner_id"`
731
+ SectorID int64 `db:"sector_num"`
732
+ }
733
+
734
+ err := al .db .Select (al .ctx , & sectors , `SELECT miner_id, sector_num FROM sector_location WHERE sector_filetype = 2 GROUP BY miner_id, sector_num ORDER BY miner_id, sector_num` )
735
+ if err != nil {
736
+ al .alertMap [Name ].err = xerrors .Errorf ("getting sealed sectors from database: %w" , err )
737
+ return
738
+ }
739
+
740
+ dbMap := map [address.Address ]* bitfield.BitField {}
741
+ minerMap := map [int64 ]address.Address {}
742
+
743
+ for _ , sector := range sectors {
744
+ m , ok := minerMap [sector .MinerID ]
745
+ if ! ok {
746
+ m , err = address .NewIDAddress (uint64 (sector .MinerID ))
747
+ if err != nil {
748
+ al .alertMap [Name ].err = xerrors .Errorf ("parsing miner address: %w" , err )
749
+ return
750
+ }
751
+ minerMap [sector .MinerID ] = m
752
+ }
753
+ bf , ok := dbMap [m ]
754
+ if ! ok {
755
+ newbf := bitfield .New ()
756
+ newbf .Set (uint64 (sector .SectorID ))
757
+ dbMap [m ] = & newbf
758
+ continue
759
+ }
760
+ bf .Set (uint64 (sector .SectorID ))
761
+ }
762
+
763
+ head , err := al .api .ChainHead (al .ctx )
764
+ if err != nil {
765
+ al .alertMap [Name ].err = xerrors .Errorf ("ChainHead: %w" , err )
766
+ return
767
+ }
768
+
769
+ for _ , m := range minerMap {
770
+ mact , err := al .api .StateGetActor (al .ctx , m , head .Key ())
771
+ if err != nil {
772
+ al .alertMap [Name ].err = xerrors .Errorf ("getting miner actor %s: %w" , m .String (), err )
773
+ return
774
+ }
775
+ tbs := blockstore .NewTieredBstore (blockstore .NewAPIBlockstore (al .api ), blockstore .NewMemory ())
776
+ mas , err := miner .Load (adt .WrapStore (al .ctx , cbor .NewCborStore (tbs )), mact )
777
+ if err != nil {
778
+ al .alertMap [Name ].err = xerrors .Errorf ("loading miner %s: %w" , m .String (), err )
779
+ return
780
+ }
781
+
782
+ liveSectors , err := miner .AllPartSectors (mas , miner .Partition .LiveSectors )
783
+ if err != nil {
784
+ al .alertMap [Name ].err = xerrors .Errorf ("getting live sectors for miner %s: %w" , m .String (), err )
785
+ return
786
+ }
787
+
788
+ diff , err := bitfield .SubtractBitField (liveSectors , * dbMap [m ])
789
+ if err != nil {
790
+ al .alertMap [Name ].err = xerrors .Errorf ("subtracting live sectors for miner %s: %w" , m .String (), err )
791
+ }
792
+ err = diff .ForEach (func (i uint64 ) error {
793
+ al .alertMap [Name ].alertString += fmt .Sprintf ("Missing sector %d in storage for miner %s. " , i , m .String ())
794
+ return nil
795
+ })
796
+ if err != nil {
797
+ al .alertMap [Name ].err = xerrors .Errorf ("getting missing sectors for miner %s: %w" , m .String (), err )
798
+ return
799
+ }
800
+ }
801
+ }
0 commit comments