diff --git a/api/api_full.go b/api/api_full.go index d4299887b..ba6a59fce 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -268,6 +268,8 @@ type FullNode interface { StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) // StateSectorGetInfo returns the on-chain info for the specified miner's sector StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) + // StateSectorPartition finds deadline/partition with the specified sector + StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*SectorLocation, error) StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error) // StateSearchMsg searches for a message in the chain, and returns its receipt and the tipset where it was executed StateSearchMsg(context.Context, cid.Cid) (*MsgLookup, error) @@ -358,6 +360,11 @@ type MinerSectors struct { Pset uint64 } +type SectorLocation struct { + Deadline uint64 + Partition uint64 +} + type ImportRes struct { Root cid.Cid ImportID int64 diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 6ab12ca6e..8ab487583 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -139,6 +139,7 @@ type FullNodeStruct struct { StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` StateSectorGetInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` + StateSectorPartition func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*api.SectorLocation, error) `perm:"read"` StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` @@ -624,6 +625,10 @@ func (c *FullNodeStruct) StateSectorGetInfo(ctx context.Context, maddr address.A return c.Internal.StateSectorGetInfo(ctx, maddr, n, tsk) } +func (c *FullNodeStruct) StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*api.SectorLocation, error) { + return c.Internal.StateSectorPartition(ctx, maddr, sectorNumber, tok) +} + func (c *FullNodeStruct) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.InvocResult, error) { return c.Internal.StateCall(ctx, msg, tsk) } diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 022c032ef..e012add8e 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -3,9 +3,8 @@ package full import ( "bytes" "context" + "errors" "fmt" - "github.com/filecoin-project/go-bitfield" - "github.com/filecoin-project/specs-actors/actors/util/adt" "strconv" cid "github.com/ipfs/go-cid" @@ -17,6 +16,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-amt-ipld/v2" + "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/specs-actors/actors/abi" "github.com/filecoin-project/specs-actors/actors/abi/big" @@ -27,6 +27,7 @@ import ( "github.com/filecoin-project/specs-actors/actors/builtin/power" "github.com/filecoin-project/specs-actors/actors/builtin/reward" "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" @@ -42,6 +43,8 @@ import ( "github.com/filecoin-project/lotus/node/modules/dtypes" ) +var errBreakForeach = errors.New("break") + type StateAPI struct { fx.In @@ -633,6 +636,45 @@ func (a *StateAPI) StateSectorGetInfo(ctx context.Context, maddr address.Address return stmgr.MinerSectorInfo(ctx, a.StateManager, maddr, n, ts) } +func (a *StateAPI) StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tsk types.TipSetKey) (*api.SectorLocation, error) { + var found *api.SectorLocation + + err := a.StateManager.WithParentStateTsk(tsk, + a.StateManager.WithActor(maddr, + a.StateManager.WithActorState(ctx, + a.StateManager.WithDeadlines(func(store adt.Store, deadlines *miner.Deadlines) error { + err := a.StateManager.WithEachDeadline(func(store adt.Store, di uint64, deadline *miner.Deadline) error { + return a.StateManager.WithEachPartition(func(store adt.Store, pi uint64, partition *miner.Partition) error { + set, err := partition.Sectors.IsSet(uint64(sectorNumber)) + if err != nil { + return xerrors.Errorf("is set: %w", err) + } + if set { + found = &api.SectorLocation{ + Deadline: di, + Partition: pi, + } + return errBreakForeach + } + return nil + })(store, di, deadline) + })(store, deadlines) + if err == errBreakForeach { + err = nil + } + return err + })))) + if err != nil { + return nil, err + } + + if found == nil { + + } + + return found, nil +} + func (a *StateAPI) StateListMessages(ctx context.Context, match *types.Message, tsk types.TipSetKey, toheight abi.ChainEpoch) ([]cid.Cid, error) { ts, err := a.Chain.GetTipSetFromKey(tsk) if err != nil { diff --git a/storage/adapter_storage_miner.go b/storage/adapter_storage_miner.go index eaaa7a75c..a80bfae7a 100644 --- a/storage/adapter_storage_miner.go +++ b/storage/adapter_storage_miner.go @@ -184,6 +184,27 @@ func (s SealingAPIAdapter) StateSectorGetInfo(ctx context.Context, maddr address return s.delegate.StateSectorGetInfo(ctx, maddr, sectorNumber, tsk) } + +func (s SealingAPIAdapter) StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok sealing.TipSetToken) (*sealing.SectorLocation, error) { + tsk, err := types.TipSetKeyFromBytes(tok) + if err != nil { + return nil, xerrors.Errorf("failed to unmarshal TipSetToken to TipSetKey: %w", err) + } + + l, err := s.delegate.StateSectorPartition(ctx, maddr, sectorNumber, tsk) + if err != nil { + return nil, err + } + if l != nil { + return &sealing.SectorLocation{ + Deadline: l.Deadline, + Partition: l.Partition, + }, nil + } + + return nil, nil // not found +} + func (s SealingAPIAdapter) StateMarketStorageDeal(ctx context.Context, dealID abi.DealID, tok sealing.TipSetToken) (market.DealProposal, error) { tsk, err := types.TipSetKeyFromBytes(tok) if err != nil { diff --git a/storage/miner.go b/storage/miner.go index a0e2c9225..962900b61 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -52,6 +52,7 @@ type storageMinerApi interface { StateMinerSectors(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) StateSectorGetInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (*miner.SectorOnChainInfo, error) + StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*api.SectorLocation, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error) StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error) StateMinerInitialPledgeCollateral(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (types.BigInt, error)