Merge pull request #6906 from filecoin-project/nonsense/get-enabled-subsystems-api

adding an RuntimeSubsystems API to storage miner; fix `lotus-miner info`
This commit is contained in:
raulk 2021-07-29 00:04:29 +01:00 committed by GitHub
commit 640407aae7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 261 additions and 80 deletions

View File

@ -166,6 +166,10 @@ type StorageMiner interface {
MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write MarketPendingDeals(ctx context.Context) (PendingDealInfo, error) //perm:write
MarketPublishPendingDeals(ctx context.Context) error //perm:admin MarketPublishPendingDeals(ctx context.Context) error //perm:admin
// RuntimeSubsystems returns the subsystems that are enabled
// in this instance.
RuntimeSubsystems(ctx context.Context) (MinerSubsystems, error) //perm:read
DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error //perm:admin
DealsList(ctx context.Context) ([]MarketDeal, error) //perm:admin DealsList(ctx context.Context) ([]MarketDeal, error) //perm:admin
DealsConsiderOnlineStorageDeals(context.Context) (bool, error) //perm:admin DealsConsiderOnlineStorageDeals(context.Context) (bool, error) //perm:admin

View File

@ -16,10 +16,10 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/ipfs/go-filestore" "github.com/ipfs/go-filestore"
metrics "github.com/libp2p/go-libp2p-core/metrics" "github.com/libp2p/go-libp2p-core/metrics"
"github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peer"
protocol "github.com/libp2p/go-libp2p-core/protocol" "github.com/libp2p/go-libp2p-core/protocol"
pubsub "github.com/libp2p/go-libp2p-pubsub" pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multiaddr"
@ -46,11 +46,12 @@ import (
) )
var ExampleValues = map[reflect.Type]interface{}{ var ExampleValues = map[reflect.Type]interface{}{
reflect.TypeOf(auth.Permission("")): auth.Permission("write"), reflect.TypeOf(api.MinerSubsystem(0)): api.MinerSubsystem(1),
reflect.TypeOf(""): "string value", reflect.TypeOf(auth.Permission("")): auth.Permission("write"),
reflect.TypeOf(uint64(42)): uint64(42), reflect.TypeOf(""): "string value",
reflect.TypeOf(byte(7)): byte(7), reflect.TypeOf(uint64(42)): uint64(42),
reflect.TypeOf([]byte{}): []byte("byte array"), reflect.TypeOf(byte(7)): byte(7),
reflect.TypeOf([]byte{}): []byte("byte array"),
} }
func addExample(v interface{}) { func addExample(v interface{}) {
@ -264,6 +265,12 @@ func init() {
addExample(api.CheckStatusCode(0)) addExample(api.CheckStatusCode(0))
addExample(map[string]interface{}{"abc": 123}) addExample(map[string]interface{}{"abc": 123})
addExample(api.MinerSubsystems{
api.SubsystemMining,
api.SubsystemSealing,
api.SubsystemSectorStorage,
api.SubsystemMarkets,
})
} }
func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) {

79
api/miner_subsystems.go Normal file
View File

@ -0,0 +1,79 @@
package api
import (
"encoding/json"
)
// MinerSubsystem represents a miner subsystem. Int and string values are not
// guaranteed to be stable over time is not
// guaranteed to be stable over time.
type MinerSubsystem int
const (
// SubsystemUnknown is a placeholder for the zero value. It should never
// be used.
SubsystemUnknown MinerSubsystem = iota
// SubsystemMarkets signifies the storage and retrieval
// deal-making subsystem.
SubsystemMarkets
// SubsystemMining signifies the mining subsystem.
SubsystemMining
// SubsystemSealing signifies the sealing subsystem.
SubsystemSealing
// SubsystemSectorStorage signifies the sector storage subsystem.
SubsystemSectorStorage
)
var MinerSubsystemToString = map[MinerSubsystem]string{
SubsystemUnknown: "Unknown",
SubsystemMarkets: "Markets",
SubsystemMining: "Mining",
SubsystemSealing: "Sealing",
SubsystemSectorStorage: "SectorStorage",
}
var MinerSubsystemToID = map[string]MinerSubsystem{
"Unknown": SubsystemUnknown,
"Markets": SubsystemMarkets,
"Mining": SubsystemMining,
"Sealing": SubsystemSealing,
"SectorStorage": SubsystemSectorStorage,
}
func (ms MinerSubsystem) MarshalJSON() ([]byte, error) {
return json.Marshal(MinerSubsystemToString[ms])
}
func (ms *MinerSubsystem) UnmarshalJSON(b []byte) error {
var j string
err := json.Unmarshal(b, &j)
if err != nil {
return err
}
s, ok := MinerSubsystemToID[j]
if !ok {
*ms = SubsystemUnknown
} else {
*ms = s
}
return nil
}
type MinerSubsystems []MinerSubsystem
func (ms MinerSubsystems) Has(entry MinerSubsystem) bool {
for _, v := range ms {
if v == entry {
return true
}
}
return false
}
func (ms MinerSubsystem) String() string {
s, ok := MinerSubsystemToString[ms]
if !ok {
return MinerSubsystemToString[SubsystemUnknown]
}
return s
}

View File

@ -699,6 +699,8 @@ type StorageMinerStruct struct {
ReturnUnsealPiece func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` ReturnUnsealPiece func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"`
RuntimeSubsystems func(p0 context.Context) (MinerSubsystems, error) `perm:"read"`
SealingAbort func(p0 context.Context, p1 storiface.CallID) error `perm:"admin"` SealingAbort func(p0 context.Context, p1 storiface.CallID) error `perm:"admin"`
SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"` SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"`
@ -4095,6 +4097,17 @@ func (s *StorageMinerStub) ReturnUnsealPiece(p0 context.Context, p1 storiface.Ca
return ErrNotSupported return ErrNotSupported
} }
func (s *StorageMinerStruct) RuntimeSubsystems(p0 context.Context) (MinerSubsystems, error) {
if s.Internal.RuntimeSubsystems == nil {
return *new(MinerSubsystems), ErrNotSupported
}
return s.Internal.RuntimeSubsystems(p0)
}
func (s *StorageMinerStub) RuntimeSubsystems(p0 context.Context) (MinerSubsystems, error) {
return *new(MinerSubsystems), ErrNotSupported
}
func (s *StorageMinerStruct) SealingAbort(p0 context.Context, p1 storiface.CallID) error { func (s *StorageMinerStruct) SealingAbort(p0 context.Context, p1 storiface.CallID) error {
if s.Internal.SealingAbort == nil { if s.Internal.SealingAbort == nil {
return ErrNotSupported return ErrNotSupported

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -21,6 +21,7 @@ import (
"github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api/v0api"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing" sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
"github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api"
@ -55,7 +56,7 @@ func infoCmdAct(cctx *cli.Context) error {
} }
defer closer() defer closer()
api, acloser, err := lcli.GetFullNodeAPI(cctx) fullapi, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
} }
@ -63,9 +64,16 @@ func infoCmdAct(cctx *cli.Context) error {
ctx := lcli.ReqContext(cctx) ctx := lcli.ReqContext(cctx)
subsystems, err := nodeApi.RuntimeSubsystems(ctx)
if err != nil {
return err
}
fmt.Println("Enabled subsystems:", subsystems)
fmt.Print("Chain: ") fmt.Print("Chain: ")
head, err := api.ChainHead(ctx) head, err := fullapi.ChainHead(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -95,24 +103,42 @@ func infoCmdAct(cctx *cli.Context) error {
fmt.Println() fmt.Println()
if subsystems.Has(api.SubsystemSectorStorage) {
err := handleMiningInfo(ctx, cctx, fullapi, nodeApi)
if err != nil {
return err
}
}
if subsystems.Has(api.SubsystemMarkets) {
err := handleMarketsInfo(ctx, nodeApi)
if err != nil {
return err
}
}
return nil
}
func handleMiningInfo(ctx context.Context, cctx *cli.Context, fullapi v0api.FullNode, nodeApi api.StorageMiner) error {
maddr, err := getActorAddress(ctx, cctx) maddr, err := getActorAddress(ctx, cctx)
if err != nil { if err != nil {
return err return err
} }
mact, err := api.StateGetActor(ctx, maddr, types.EmptyTSK) mact, err := fullapi.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(api), blockstore.NewMemory()) tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(fullapi), blockstore.NewMemory())
mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact) mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact)
if err != nil { if err != nil {
return err return err
} }
// Sector size // Sector size
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) mi, err := fullapi.StateMinerInfo(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -120,7 +146,7 @@ func infoCmdAct(cctx *cli.Context) error {
ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize))) ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize)))
fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize) fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize)
pow, err := api.StateMinerPower(ctx, maddr, types.EmptyTSK) pow, err := fullapi.StateMinerPower(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -142,7 +168,7 @@ func infoCmdAct(cctx *cli.Context) error {
pow.TotalPower.RawBytePower, pow.TotalPower.RawBytePower,
), ),
) )
secCounts, err := api.StateMinerSectorCount(ctx, maddr, types.EmptyTSK) secCounts, err := fullapi.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
if err != nil { if err != nil {
return err return err
} }
@ -219,6 +245,75 @@ func infoCmdAct(cctx *cli.Context) error {
fmt.Println() fmt.Println()
spendable := big.Zero()
// NOTE: there's no need to unlock anything here. Funds only
// vest on deadline boundaries, and they're unlocked by cron.
lockedFunds, err := mas.LockedFunds()
if err != nil {
return xerrors.Errorf("getting locked funds: %w", err)
}
availBalance, err := mas.AvailableBalance(mact.Balance)
if err != nil {
return xerrors.Errorf("getting available balance: %w", err)
}
spendable = big.Add(spendable, availBalance)
fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance).Short()))
fmt.Printf(" PreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits).Short())
fmt.Printf(" Pledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement).Short())
fmt.Printf(" Vesting: %s\n", types.FIL(lockedFunds.VestingFunds).Short())
colorTokenAmount(" Available: %s\n", availBalance)
mb, err := fullapi.StateMarketBalance(ctx, maddr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting market balance: %w", err)
}
spendable = big.Add(spendable, big.Sub(mb.Escrow, mb.Locked))
fmt.Printf("Market Balance: %s\n", types.FIL(mb.Escrow).Short())
fmt.Printf(" Locked: %s\n", types.FIL(mb.Locked).Short())
colorTokenAmount(" Available: %s\n", big.Sub(mb.Escrow, mb.Locked))
wb, err := fullapi.WalletBalance(ctx, mi.Worker)
if err != nil {
return xerrors.Errorf("getting worker balance: %w", err)
}
spendable = big.Add(spendable, wb)
color.Cyan("Worker Balance: %s", types.FIL(wb).Short())
if len(mi.ControlAddresses) > 0 {
cbsum := big.Zero()
for _, ca := range mi.ControlAddresses {
b, err := fullapi.WalletBalance(ctx, ca)
if err != nil {
return xerrors.Errorf("getting control address balance: %w", err)
}
cbsum = big.Add(cbsum, b)
}
spendable = big.Add(spendable, cbsum)
fmt.Printf(" Control: %s\n", types.FIL(cbsum).Short())
}
colorTokenAmount("Total Spendable: %s\n", spendable)
fmt.Println()
if !cctx.Bool("hide-sectors-info") {
fmt.Println("Sectors:")
err = sectorsInfo(ctx, nodeApi)
if err != nil {
return err
}
}
// TODO: grab actr state / info
// * Sealed sectors (count / bytes)
// * Power
return nil
}
func handleMarketsInfo(ctx context.Context, nodeApi api.StorageMiner) error {
deals, err := nodeApi.MarketListIncompleteDeals(ctx) deals, err := nodeApi.MarketListIncompleteDeals(ctx)
if err != nil { if err != nil {
return err return err
@ -309,70 +404,6 @@ func infoCmdAct(cctx *cli.Context) error {
fmt.Println() fmt.Println()
spendable := big.Zero()
// NOTE: there's no need to unlock anything here. Funds only
// vest on deadline boundaries, and they're unlocked by cron.
lockedFunds, err := mas.LockedFunds()
if err != nil {
return xerrors.Errorf("getting locked funds: %w", err)
}
availBalance, err := mas.AvailableBalance(mact.Balance)
if err != nil {
return xerrors.Errorf("getting available balance: %w", err)
}
spendable = big.Add(spendable, availBalance)
fmt.Printf("Miner Balance: %s\n", color.YellowString("%s", types.FIL(mact.Balance).Short()))
fmt.Printf(" PreCommit: %s\n", types.FIL(lockedFunds.PreCommitDeposits).Short())
fmt.Printf(" Pledge: %s\n", types.FIL(lockedFunds.InitialPledgeRequirement).Short())
fmt.Printf(" Vesting: %s\n", types.FIL(lockedFunds.VestingFunds).Short())
colorTokenAmount(" Available: %s\n", availBalance)
mb, err := api.StateMarketBalance(ctx, maddr, types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting market balance: %w", err)
}
spendable = big.Add(spendable, big.Sub(mb.Escrow, mb.Locked))
fmt.Printf("Market Balance: %s\n", types.FIL(mb.Escrow).Short())
fmt.Printf(" Locked: %s\n", types.FIL(mb.Locked).Short())
colorTokenAmount(" Available: %s\n", big.Sub(mb.Escrow, mb.Locked))
wb, err := api.WalletBalance(ctx, mi.Worker)
if err != nil {
return xerrors.Errorf("getting worker balance: %w", err)
}
spendable = big.Add(spendable, wb)
color.Cyan("Worker Balance: %s", types.FIL(wb).Short())
if len(mi.ControlAddresses) > 0 {
cbsum := big.Zero()
for _, ca := range mi.ControlAddresses {
b, err := api.WalletBalance(ctx, ca)
if err != nil {
return xerrors.Errorf("getting control address balance: %w", err)
}
cbsum = big.Add(cbsum, b)
}
spendable = big.Add(spendable, cbsum)
fmt.Printf(" Control: %s\n", types.FIL(cbsum).Short())
}
colorTokenAmount("Total Spendable: %s\n", spendable)
fmt.Println()
if !cctx.Bool("hide-sectors-info") {
fmt.Println("Sectors:")
err = sectorsInfo(ctx, nodeApi)
if err != nil {
return err
}
}
// TODO: grab actr state / info
// * Sealed sectors (count / bytes)
// * Power
return nil return nil
} }

View File

@ -94,6 +94,8 @@
* [ReturnSealPreCommit1](#ReturnSealPreCommit1) * [ReturnSealPreCommit1](#ReturnSealPreCommit1)
* [ReturnSealPreCommit2](#ReturnSealPreCommit2) * [ReturnSealPreCommit2](#ReturnSealPreCommit2)
* [ReturnUnsealPiece](#ReturnUnsealPiece) * [ReturnUnsealPiece](#ReturnUnsealPiece)
* [Runtime](#Runtime)
* [RuntimeSubsystems](#RuntimeSubsystems)
* [Sealing](#Sealing) * [Sealing](#Sealing)
* [SealingAbort](#SealingAbort) * [SealingAbort](#SealingAbort)
* [SealingSchedDiag](#SealingSchedDiag) * [SealingSchedDiag](#SealingSchedDiag)
@ -1522,6 +1524,28 @@ Inputs:
Response: `{}` Response: `{}`
## Runtime
### RuntimeSubsystems
RuntimeSubsystems returns the subsystems that are enabled
in this instance.
Perms: read
Inputs: `null`
Response:
```json
[
"Mining",
"Sealing",
"SectorStorage",
"Markets"
]
```
## Sealing ## Sealing

View File

@ -72,6 +72,7 @@ func ConfigStorageMiner(c interface{}) Option {
return Options( return Options(
ConfigCommon(&cfg.Common, enableLibp2pNode), ConfigCommon(&cfg.Common, enableLibp2pNode),
Override(new(api.MinerSubsystems), modules.ExtractEnabledMinerSubsystems(cfg.Subsystems)),
Override(new(stores.LocalStorage), From(new(repo.LockedRepo))), Override(new(stores.LocalStorage), From(new(repo.LockedRepo))),
Override(new(*stores.Local), modules.LocalStorage), Override(new(*stores.Local), modules.LocalStorage),
Override(new(*stores.Remote), modules.RemoteStorage), Override(new(*stores.Remote), modules.RemoteStorage),

View File

@ -23,8 +23,8 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
datatransfer "github.com/filecoin-project/go-data-transfer" datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-fil-markets/piecestore" "github.com/filecoin-project/go-fil-markets/piecestore"
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/retrievalmarket"
storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage"
@ -51,6 +51,8 @@ type StorageMinerAPI struct {
api.Common api.Common
api.Net api.Net
EnabledSubsystems api.MinerSubsystems
Full api.FullNode Full api.FullNode
LocalStore *stores.Local LocalStore *stores.Local
RemoteStore *stores.Remote RemoteStore *stores.Remote
@ -703,4 +705,8 @@ func (sm *StorageMinerAPI) ComputeProof(ctx context.Context, ssi []builtin.Secto
return sm.Epp.ComputeProof(ctx, ssi, rand) return sm.Epp.ComputeProof(ctx, ssi, rand)
} }
func (sm *StorageMinerAPI) RuntimeSubsystems(context.Context) (res api.MinerSubsystems, err error) {
return sm.EnabledSubsystems, nil
}
var _ api.StorageMiner = &StorageMinerAPI{} var _ api.StorageMiner = &StorageMinerAPI{}

View File

@ -1007,3 +1007,19 @@ func mutateCfg(r repo.LockedRepo, mutator func(*config.StorageMiner)) error {
return multierr.Combine(typeErr, setConfigErr) return multierr.Combine(typeErr, setConfigErr)
} }
func ExtractEnabledMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.MinerSubsystems) {
if cfg.EnableMining {
res = append(res, api.SubsystemMining)
}
if cfg.EnableSealing {
res = append(res, api.SubsystemSealing)
}
if cfg.EnableSectorStorage {
res = append(res, api.SubsystemSectorStorage)
}
if cfg.EnableMarkets {
res = append(res, api.SubsystemMarkets)
}
return res
}