package hapi import ( "net/http" "time" lru "github.com/hashicorp/golang-lru/v2" blocks "github.com/ipfs/go-block-format" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/lotus/blockstore" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/must" ) var ChainBlockCache = must.One(lru.New[blockstore.MhString, blocks.Block](4096)) func (a *app) pipelinePorepSectors(w http.ResponseWriter, r *http.Request) { ctx := r.Context() type PipelineTask struct { SpID int64 `db:"sp_id"` SectorNumber int64 `db:"sector_number"` CreateTime time.Time `db:"create_time"` TaskSDR *int64 `db:"task_id_sdr"` AfterSDR bool `db:"after_sdr"` TaskTreeD *int64 `db:"task_id_tree_d"` AfterTreeD bool `db:"after_tree_d"` TaskTreeC *int64 `db:"task_id_tree_c"` AfterTreeC bool `db:"after_tree_c"` TaskTreeR *int64 `db:"task_id_tree_r"` AfterTreeR bool `db:"after_tree_r"` TaskPrecommitMsg *int64 `db:"task_id_precommit_msg"` AfterPrecommitMsg bool `db:"after_precommit_msg"` AfterPrecommitMsgSuccess bool `db:"after_precommit_msg_success"` SeedEpoch *int64 `db:"seed_epoch"` TaskPoRep *int64 `db:"task_id_porep"` PoRepProof []byte `db:"porep_proof"` AfterPoRep bool `db:"after_porep"` TaskFinalize *int64 `db:"task_id_finalize"` AfterFinalize bool `db:"after_finalize"` TaskMoveStorage *int64 `db:"task_id_move_storage"` AfterMoveStorage bool `db:"after_move_storage"` TaskCommitMsg *int64 `db:"task_id_commit_msg"` AfterCommitMsg bool `db:"after_commit_msg"` AfterCommitMsgSuccess bool `db:"after_commit_msg_success"` Failed bool `db:"failed"` FailedReason string `db:"failed_reason"` } var tasks []PipelineTask err := a.db.Select(ctx, &tasks, `SELECT sp_id, sector_number, create_time, task_id_sdr, after_sdr, task_id_tree_d, after_tree_d, task_id_tree_c, after_tree_c, task_id_tree_r, after_tree_r, task_id_precommit_msg, after_precommit_msg, after_precommit_msg_success, seed_epoch, task_id_porep, porep_proof, after_porep, task_id_finalize, after_finalize, task_id_move_storage, after_move_storage, task_id_commit_msg, after_commit_msg, after_commit_msg_success, failed, failed_reason FROM sectors_sdr_pipeline order by sp_id, sector_number`) // todo where constrain list if err != nil { http.Error(w, xerrors.Errorf("failed to fetch pipeline tasks: %w", err).Error(), http.StatusInternalServerError) return } type sectorListEntry struct { PipelineTask Address address.Address CreateTime string AfterSeed bool ChainAlloc, ChainSector, ChainActive, ChainUnproven, ChainFaulty bool } head, err := a.workingApi.ChainHead(ctx) if err != nil { http.Error(w, xerrors.Errorf("failed to fetch chain head: %w", err).Error(), http.StatusInternalServerError) return } epoch := head.Height() stor := store.ActorStore(ctx, blockstore.NewReadCachedBlockstore(blockstore.NewAPIBlockstore(a.workingApi), ChainBlockCache)) type minerBitfields struct { alloc, sectorSet, active, unproven, faulty bitfield.BitField } minerBitfieldCache := map[address.Address]minerBitfields{} sectorList := make([]sectorListEntry, 0, len(tasks)) for _, task := range tasks { task := task task.CreateTime = task.CreateTime.Local() addr, err := address.NewIDAddress(uint64(task.SpID)) if err != nil { http.Error(w, xerrors.Errorf("failed to create actor address: %w", err).Error(), http.StatusInternalServerError) return } mbf, ok := minerBitfieldCache[addr] if !ok { act, err := a.workingApi.StateGetActor(ctx, addr, types.EmptyTSK) if err != nil { http.Error(w, xerrors.Errorf("failed to load actor: %w", err).Error(), http.StatusInternalServerError) return } mas, err := miner.Load(stor, act) if err != nil { http.Error(w, xerrors.Errorf("failed to load miner actor: %w", err).Error(), http.StatusInternalServerError) return } activeSectors, err := miner.AllPartSectors(mas, miner.Partition.ActiveSectors) if err != nil { http.Error(w, xerrors.Errorf("failed to load active sectors: %w", err).Error(), http.StatusInternalServerError) return } allSectors, err := miner.AllPartSectors(mas, miner.Partition.AllSectors) if err != nil { http.Error(w, xerrors.Errorf("failed to load all sectors: %w", err).Error(), http.StatusInternalServerError) return } unproved, err := miner.AllPartSectors(mas, miner.Partition.UnprovenSectors) if err != nil { http.Error(w, xerrors.Errorf("failed to load unproven sectors: %w", err).Error(), http.StatusInternalServerError) return } faulty, err := miner.AllPartSectors(mas, miner.Partition.FaultySectors) if err != nil { http.Error(w, xerrors.Errorf("failed to load faulty sectors: %w", err).Error(), http.StatusInternalServerError) return } alloc, err := mas.GetAllocatedSectors() if err != nil { http.Error(w, xerrors.Errorf("failed to load allocated sectors: %w", err).Error(), http.StatusInternalServerError) return } mbf = minerBitfields{ alloc: *alloc, sectorSet: allSectors, active: activeSectors, unproven: unproved, faulty: faulty, } minerBitfieldCache[addr] = mbf } afterSeed := task.SeedEpoch != nil && *task.SeedEpoch <= int64(epoch) sectorList = append(sectorList, sectorListEntry{ PipelineTask: task, Address: addr, CreateTime: task.CreateTime.Format(time.DateTime), AfterSeed: afterSeed, ChainAlloc: must.One(mbf.alloc.IsSet(uint64(task.SectorNumber))), ChainSector: must.One(mbf.sectorSet.IsSet(uint64(task.SectorNumber))), ChainActive: must.One(mbf.active.IsSet(uint64(task.SectorNumber))), ChainUnproven: must.One(mbf.unproven.IsSet(uint64(task.SectorNumber))), ChainFaulty: must.One(mbf.faulty.IsSet(uint64(task.SectorNumber))), }) } a.executeTemplate(w, "pipeline_porep_sectors", sectorList) }