add RuntimeSubsystems API method; use it in lotus-miner info
This commit is contained in:
parent
40449f1ccb
commit
e90e71456b
@ -166,8 +166,6 @@ 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
|
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
|
||||||
|
63
api/api_subsystems.go
Normal file
63
api/api_subsystems.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MinerSubsystems []MinerSubsystem
|
||||||
|
|
||||||
|
func (ms MinerSubsystems) Has(entry MinerSubsystem) bool {
|
||||||
|
for _, v := range ms {
|
||||||
|
if v == entry {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type MinerSubsystem int
|
||||||
|
|
||||||
|
const (
|
||||||
|
MarketsSubsystem MinerSubsystem = iota
|
||||||
|
MiningSubsystem
|
||||||
|
SealingSubsystem
|
||||||
|
SectorStorageSubsystem
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ms MinerSubsystem) String() string {
|
||||||
|
return MinerSubsystemToString[ms]
|
||||||
|
}
|
||||||
|
|
||||||
|
var MinerSubsystemToString = map[MinerSubsystem]string{
|
||||||
|
MarketsSubsystem: "Markets",
|
||||||
|
MiningSubsystem: "Mining",
|
||||||
|
SealingSubsystem: "Sealing",
|
||||||
|
SectorStorageSubsystem: "SectorStorage",
|
||||||
|
}
|
||||||
|
|
||||||
|
var MinerSubsystemToID = map[string]MinerSubsystem{
|
||||||
|
"Markets": MarketsSubsystem,
|
||||||
|
"Mining": MiningSubsystem,
|
||||||
|
"Sealing": SealingSubsystem,
|
||||||
|
"SectorStorage": SectorStorageSubsystem,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms MinerSubsystem) MarshalJSON() ([]byte, error) {
|
||||||
|
buffer := bytes.NewBufferString(`"`)
|
||||||
|
buffer.WriteString(MinerSubsystemToString[ms])
|
||||||
|
buffer.WriteString(`"`)
|
||||||
|
return buffer.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *MinerSubsystem) UnmarshalJSON(b []byte) error {
|
||||||
|
var j string
|
||||||
|
err := json.Unmarshal(b, &j)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// TODO: handle zero value
|
||||||
|
*ms = MinerSubsystemToID[j]
|
||||||
|
return nil
|
||||||
|
}
|
@ -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"
|
||||||
"github.com/libp2p/go-libp2p-core/metrics"
|
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"
|
||||||
"github.com/libp2p/go-libp2p-core/protocol"
|
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"
|
||||||
|
|
||||||
@ -265,12 +265,6 @@ 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) {
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
Binary file not shown.
@ -21,7 +21,6 @@ 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"
|
||||||
@ -50,13 +49,7 @@ var infoCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func infoCmdAct(cctx *cli.Context) error {
|
func infoCmdAct(cctx *cli.Context) error {
|
||||||
minerApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer closer()
|
|
||||||
|
|
||||||
marketsApi, closer, err := lcli.GetMarketsAPI(cctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -70,19 +63,12 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
|
|
||||||
ctx := lcli.ReqContext(cctx)
|
ctx := lcli.ReqContext(cctx)
|
||||||
|
|
||||||
subsystems, err := minerApi.RuntimeSubsystems(ctx)
|
subsystems, err := nodeApi.RuntimeSubsystems(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Enabled subsystems (from miner API):", subsystems)
|
fmt.Println("Enabled subsystems:", subsystems)
|
||||||
|
|
||||||
subsystems, err = marketsApi.RuntimeSubsystems(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Enabled subsystems (from markets API):", subsystems)
|
|
||||||
|
|
||||||
fmt.Print("Chain: ")
|
fmt.Print("Chain: ")
|
||||||
|
|
||||||
@ -116,303 +102,288 @@ func infoCmdAct(cctx *cli.Context) error {
|
|||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
err = handleMiningInfo(ctx, cctx, fullapi, minerApi)
|
if subsystems.Has(api.SectorStorageSubsystem) {
|
||||||
if err != nil {
|
maddr, err := getActorAddress(ctx, cctx)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = handleMarketsInfo(ctx, marketsApi)
|
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
mact, err := fullapi.StateGetActor(ctx, maddr, types.EmptyTSK)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(fullapi), blockstore.NewMemory())
|
|
||||||
mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sector size
|
|
||||||
mi, err := fullapi.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize)))
|
|
||||||
fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize)
|
|
||||||
|
|
||||||
pow, err := fullapi.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Power: %s / %s (%0.4f%%)\n",
|
|
||||||
color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)),
|
|
||||||
types.DeciStr(pow.TotalPower.QualityAdjPower),
|
|
||||||
types.BigDivFloat(
|
|
||||||
types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)),
|
|
||||||
pow.TotalPower.QualityAdjPower,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n",
|
|
||||||
color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)),
|
|
||||||
types.SizeStr(pow.TotalPower.RawBytePower),
|
|
||||||
types.BigDivFloat(
|
|
||||||
types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)),
|
|
||||||
pow.TotalPower.RawBytePower,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
secCounts, err := fullapi.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
proving := secCounts.Active + secCounts.Faulty
|
|
||||||
nfaults := secCounts.Faulty
|
|
||||||
fmt.Printf("\tCommitted: %s\n", types.SizeStr(types.BigMul(types.NewInt(secCounts.Live), types.NewInt(uint64(mi.SectorSize)))))
|
|
||||||
if nfaults == 0 {
|
|
||||||
fmt.Printf("\tProving: %s\n", types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))))
|
|
||||||
} else {
|
|
||||||
var faultyPercentage float64
|
|
||||||
if secCounts.Live != 0 {
|
|
||||||
faultyPercentage = float64(100*nfaults) / float64(secCounts.Live)
|
|
||||||
}
|
|
||||||
fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n",
|
|
||||||
types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))),
|
|
||||||
types.SizeStr(types.BigMul(types.NewInt(nfaults), types.NewInt(uint64(mi.SectorSize)))),
|
|
||||||
faultyPercentage)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !pow.HasMinPower {
|
|
||||||
fmt.Print("Below minimum power threshold, no blocks will be won")
|
|
||||||
} else {
|
|
||||||
|
|
||||||
winRatio := new(corebig.Rat).SetFrac(
|
|
||||||
types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int,
|
|
||||||
pow.TotalPower.QualityAdjPower.Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 {
|
|
||||||
|
|
||||||
// if the corresponding poisson distribution isn't infinitely small then
|
|
||||||
// throw it into the mix as well, accounting for multi-wins
|
|
||||||
winRationWithPoissonFloat := -math.Expm1(-winRatioFloat)
|
|
||||||
winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat)
|
|
||||||
if winRationWithPoisson != nil {
|
|
||||||
winRatio = winRationWithPoisson
|
|
||||||
winRatioFloat = winRationWithPoissonFloat
|
|
||||||
}
|
|
||||||
|
|
||||||
weekly, _ := new(corebig.Rat).Mul(
|
|
||||||
winRatio,
|
|
||||||
new(corebig.Rat).SetInt64(7*builtin.EpochsInDay),
|
|
||||||
).Float64()
|
|
||||||
|
|
||||||
avgDuration, _ := new(corebig.Rat).Mul(
|
|
||||||
new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds),
|
|
||||||
new(corebig.Rat).Inv(winRatio),
|
|
||||||
).Float64()
|
|
||||||
|
|
||||||
fmt.Print("Projected average block win rate: ")
|
|
||||||
color.Blue(
|
|
||||||
"%.02f/week (every %s)",
|
|
||||||
weekly,
|
|
||||||
(time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples
|
|
||||||
// https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t
|
|
||||||
// t == how many dice-rolls (epochs) before win
|
|
||||||
// p == winRate == ( minerPower / netPower )
|
|
||||||
// c == target probability of win ( 99.9% in this case )
|
|
||||||
fmt.Print("Projected block win with ")
|
|
||||||
color.Green(
|
|
||||||
"99.9%% probability every %s",
|
|
||||||
(time.Second * time.Duration(
|
|
||||||
builtin.EpochDurationSeconds*math.Log(1-0.999)/
|
|
||||||
math.Log(1-winRatioFloat),
|
|
||||||
)).Truncate(time.Second).String(),
|
|
||||||
)
|
|
||||||
fmt.Println("(projections DO NOT account for future network and miner growth)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: grab actr state / info
|
mact, err := fullapi.StateGetActor(ctx, maddr, types.EmptyTSK)
|
||||||
// * Sealed sectors (count / bytes)
|
if err != nil {
|
||||||
// * Power
|
return err
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleMarketsInfo(ctx context.Context, nodeApi api.StorageMiner) error {
|
|
||||||
deals, err := nodeApi.MarketListIncompleteDeals(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type dealStat struct {
|
|
||||||
count, verifCount int
|
|
||||||
bytes, verifBytes uint64
|
|
||||||
}
|
|
||||||
dsAdd := func(ds *dealStat, deal storagemarket.MinerDeal) {
|
|
||||||
ds.count++
|
|
||||||
ds.bytes += uint64(deal.Proposal.PieceSize)
|
|
||||||
if deal.Proposal.VerifiedDeal {
|
|
||||||
ds.verifCount++
|
|
||||||
ds.verifBytes += uint64(deal.Proposal.PieceSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showDealStates := map[storagemarket.StorageDealStatus]struct{}{
|
|
||||||
storagemarket.StorageDealActive: {},
|
|
||||||
storagemarket.StorageDealTransferring: {},
|
|
||||||
storagemarket.StorageDealStaged: {},
|
|
||||||
storagemarket.StorageDealAwaitingPreCommit: {},
|
|
||||||
storagemarket.StorageDealSealing: {},
|
|
||||||
storagemarket.StorageDealPublish: {},
|
|
||||||
storagemarket.StorageDealCheckForAcceptance: {},
|
|
||||||
storagemarket.StorageDealPublishing: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
var total dealStat
|
|
||||||
perState := map[storagemarket.StorageDealStatus]*dealStat{}
|
|
||||||
for _, deal := range deals {
|
|
||||||
if _, ok := showDealStates[deal.State]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if perState[deal.State] == nil {
|
|
||||||
perState[deal.State] = new(dealStat)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dsAdd(&total, deal)
|
tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(fullapi), blockstore.NewMemory())
|
||||||
dsAdd(perState[deal.State], deal)
|
mas, err := miner.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact)
|
||||||
}
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
type wstr struct {
|
// Sector size
|
||||||
str string
|
mi, err := fullapi.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||||
status storagemarket.StorageDealStatus
|
if err != nil {
|
||||||
}
|
return err
|
||||||
sorted := make([]wstr, 0, len(perState))
|
}
|
||||||
for status, stat := range perState {
|
|
||||||
st := strings.TrimPrefix(storagemarket.DealStates[status], "StorageDeal")
|
ssize := types.SizeStr(types.NewInt(uint64(mi.SectorSize)))
|
||||||
sorted = append(sorted, wstr{
|
fmt.Printf("Miner: %s (%s sectors)\n", color.BlueString("%s", maddr), ssize)
|
||||||
str: fmt.Sprintf(" %s:\t%d\t\t%s\t(Verified: %d\t%s)\n", st, stat.count, types.SizeStr(types.NewInt(stat.bytes)), stat.verifCount, types.SizeStr(types.NewInt(stat.verifBytes))),
|
|
||||||
status: status,
|
pow, err := fullapi.StateMinerPower(ctx, maddr, types.EmptyTSK)
|
||||||
},
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Power: %s / %s (%0.4f%%)\n",
|
||||||
|
color.GreenString(types.DeciStr(pow.MinerPower.QualityAdjPower)),
|
||||||
|
types.DeciStr(pow.TotalPower.QualityAdjPower),
|
||||||
|
types.BigDivFloat(
|
||||||
|
types.BigMul(pow.MinerPower.QualityAdjPower, big.NewInt(100)),
|
||||||
|
pow.TotalPower.QualityAdjPower,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
|
||||||
sort.Slice(sorted, func(i, j int) bool {
|
fmt.Printf("\tRaw: %s / %s (%0.4f%%)\n",
|
||||||
if sorted[i].status == storagemarket.StorageDealActive || sorted[j].status == storagemarket.StorageDealActive {
|
color.BlueString(types.SizeStr(pow.MinerPower.RawBytePower)),
|
||||||
return sorted[i].status == storagemarket.StorageDealActive
|
types.SizeStr(pow.TotalPower.RawBytePower),
|
||||||
|
types.BigDivFloat(
|
||||||
|
types.BigMul(pow.MinerPower.RawBytePower, big.NewInt(100)),
|
||||||
|
pow.TotalPower.RawBytePower,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
secCounts, err := fullapi.StateMinerSectorCount(ctx, maddr, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return sorted[i].status > sorted[j].status
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Println()
|
proving := secCounts.Active + secCounts.Faulty
|
||||||
fmt.Printf("Storage Deals: %d, %s\n", total.count, types.SizeStr(types.NewInt(total.bytes)))
|
nfaults := secCounts.Faulty
|
||||||
|
fmt.Printf("\tCommitted: %s\n", types.SizeStr(types.BigMul(types.NewInt(secCounts.Live), types.NewInt(uint64(mi.SectorSize)))))
|
||||||
tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
|
if nfaults == 0 {
|
||||||
for _, e := range sorted {
|
fmt.Printf("\tProving: %s\n", types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))))
|
||||||
_, _ = tw.Write([]byte(e.str))
|
} else {
|
||||||
}
|
var faultyPercentage float64
|
||||||
|
if secCounts.Live != 0 {
|
||||||
_ = tw.Flush()
|
faultyPercentage = float64(100*nfaults) / float64(secCounts.Live)
|
||||||
fmt.Println()
|
}
|
||||||
|
fmt.Printf("\tProving: %s (%s Faulty, %.2f%%)\n",
|
||||||
retrievals, err := nodeApi.MarketListRetrievalDeals(ctx)
|
types.SizeStr(types.BigMul(types.NewInt(proving), types.NewInt(uint64(mi.SectorSize)))),
|
||||||
if err != nil {
|
types.SizeStr(types.BigMul(types.NewInt(nfaults), types.NewInt(uint64(mi.SectorSize)))),
|
||||||
return xerrors.Errorf("getting retrieval deal list: %w", err)
|
faultyPercentage)
|
||||||
}
|
|
||||||
|
|
||||||
var retrComplete dealStat
|
|
||||||
for _, retrieval := range retrievals {
|
|
||||||
if retrieval.Status == retrievalmarket.DealStatusCompleted {
|
|
||||||
retrComplete.count++
|
|
||||||
retrComplete.bytes += retrieval.TotalSent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !pow.HasMinPower {
|
||||||
|
fmt.Print("Below minimum power threshold, no blocks will be won")
|
||||||
|
} else {
|
||||||
|
|
||||||
|
winRatio := new(corebig.Rat).SetFrac(
|
||||||
|
types.BigMul(pow.MinerPower.QualityAdjPower, types.NewInt(build.BlocksPerEpoch)).Int,
|
||||||
|
pow.TotalPower.QualityAdjPower.Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
if winRatioFloat, _ := winRatio.Float64(); winRatioFloat > 0 {
|
||||||
|
|
||||||
|
// if the corresponding poisson distribution isn't infinitely small then
|
||||||
|
// throw it into the mix as well, accounting for multi-wins
|
||||||
|
winRationWithPoissonFloat := -math.Expm1(-winRatioFloat)
|
||||||
|
winRationWithPoisson := new(corebig.Rat).SetFloat64(winRationWithPoissonFloat)
|
||||||
|
if winRationWithPoisson != nil {
|
||||||
|
winRatio = winRationWithPoisson
|
||||||
|
winRatioFloat = winRationWithPoissonFloat
|
||||||
|
}
|
||||||
|
|
||||||
|
weekly, _ := new(corebig.Rat).Mul(
|
||||||
|
winRatio,
|
||||||
|
new(corebig.Rat).SetInt64(7*builtin.EpochsInDay),
|
||||||
|
).Float64()
|
||||||
|
|
||||||
|
avgDuration, _ := new(corebig.Rat).Mul(
|
||||||
|
new(corebig.Rat).SetInt64(builtin.EpochDurationSeconds),
|
||||||
|
new(corebig.Rat).Inv(winRatio),
|
||||||
|
).Float64()
|
||||||
|
|
||||||
|
fmt.Print("Projected average block win rate: ")
|
||||||
|
color.Blue(
|
||||||
|
"%.02f/week (every %s)",
|
||||||
|
weekly,
|
||||||
|
(time.Second * time.Duration(avgDuration)).Truncate(time.Second).String(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Geometric distribution of P(Y < k) calculated as described in https://en.wikipedia.org/wiki/Geometric_distribution#Probability_Outcomes_Examples
|
||||||
|
// https://www.wolframalpha.com/input/?i=t+%3E+0%3B+p+%3E+0%3B+p+%3C+1%3B+c+%3E+0%3B+c+%3C1%3B+1-%281-p%29%5E%28t%29%3Dc%3B+solve+t
|
||||||
|
// t == how many dice-rolls (epochs) before win
|
||||||
|
// p == winRate == ( minerPower / netPower )
|
||||||
|
// c == target probability of win ( 99.9% in this case )
|
||||||
|
fmt.Print("Projected block win with ")
|
||||||
|
color.Green(
|
||||||
|
"99.9%% probability every %s",
|
||||||
|
(time.Second * time.Duration(
|
||||||
|
builtin.EpochDurationSeconds*math.Log(1-0.999)/
|
||||||
|
math.Log(1-winRatioFloat),
|
||||||
|
)).Truncate(time.Second).String(),
|
||||||
|
)
|
||||||
|
fmt.Println("(projections DO NOT account for future network and miner growth)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Retrieval Deals (complete): %d, %s\n", retrComplete.count, types.SizeStr(types.NewInt(retrComplete.bytes)))
|
if subsystems.Has(api.MarketsSubsystem) {
|
||||||
|
deals, err := nodeApi.MarketListIncompleteDeals(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println()
|
type dealStat struct {
|
||||||
|
count, verifCount int
|
||||||
|
bytes, verifBytes uint64
|
||||||
|
}
|
||||||
|
dsAdd := func(ds *dealStat, deal storagemarket.MinerDeal) {
|
||||||
|
ds.count++
|
||||||
|
ds.bytes += uint64(deal.Proposal.PieceSize)
|
||||||
|
if deal.Proposal.VerifiedDeal {
|
||||||
|
ds.verifCount++
|
||||||
|
ds.verifBytes += uint64(deal.Proposal.PieceSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showDealStates := map[storagemarket.StorageDealStatus]struct{}{
|
||||||
|
storagemarket.StorageDealActive: {},
|
||||||
|
storagemarket.StorageDealTransferring: {},
|
||||||
|
storagemarket.StorageDealStaged: {},
|
||||||
|
storagemarket.StorageDealAwaitingPreCommit: {},
|
||||||
|
storagemarket.StorageDealSealing: {},
|
||||||
|
storagemarket.StorageDealPublish: {},
|
||||||
|
storagemarket.StorageDealCheckForAcceptance: {},
|
||||||
|
storagemarket.StorageDealPublishing: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
var total dealStat
|
||||||
|
perState := map[storagemarket.StorageDealStatus]*dealStat{}
|
||||||
|
for _, deal := range deals {
|
||||||
|
if _, ok := showDealStates[deal.State]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if perState[deal.State] == nil {
|
||||||
|
perState[deal.State] = new(dealStat)
|
||||||
|
}
|
||||||
|
|
||||||
|
dsAdd(&total, deal)
|
||||||
|
dsAdd(perState[deal.State], deal)
|
||||||
|
}
|
||||||
|
|
||||||
|
type wstr struct {
|
||||||
|
str string
|
||||||
|
status storagemarket.StorageDealStatus
|
||||||
|
}
|
||||||
|
sorted := make([]wstr, 0, len(perState))
|
||||||
|
for status, stat := range perState {
|
||||||
|
st := strings.TrimPrefix(storagemarket.DealStates[status], "StorageDeal")
|
||||||
|
sorted = append(sorted, wstr{
|
||||||
|
str: fmt.Sprintf(" %s:\t%d\t\t%s\t(Verified: %d\t%s)\n", st, stat.count, types.SizeStr(types.NewInt(stat.bytes)), stat.verifCount, types.SizeStr(types.NewInt(stat.verifBytes))),
|
||||||
|
status: status,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
sort.Slice(sorted, func(i, j int) bool {
|
||||||
|
if sorted[i].status == storagemarket.StorageDealActive || sorted[j].status == storagemarket.StorageDealActive {
|
||||||
|
return sorted[i].status == storagemarket.StorageDealActive
|
||||||
|
}
|
||||||
|
return sorted[i].status > sorted[j].status
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Printf("Storage Deals: %d, %s\n", total.count, types.SizeStr(types.NewInt(total.bytes)))
|
||||||
|
|
||||||
|
tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
|
||||||
|
for _, e := range sorted {
|
||||||
|
_, _ = tw.Write([]byte(e.str))
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = tw.Flush()
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
retrievals, err := nodeApi.MarketListRetrievalDeals(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting retrieval deal list: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var retrComplete dealStat
|
||||||
|
for _, retrieval := range retrievals {
|
||||||
|
if retrieval.Status == retrievalmarket.DealStatusCompleted {
|
||||||
|
retrComplete.count++
|
||||||
|
retrComplete.bytes += retrieval.TotalSent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Retrieval Deals (complete): %d, %s\n", retrComplete.count, types.SizeStr(types.NewInt(retrComplete.bytes)))
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1528,23 +1528,13 @@ Response: `{}`
|
|||||||
|
|
||||||
|
|
||||||
### RuntimeSubsystems
|
### RuntimeSubsystems
|
||||||
RuntimeSubsystems returns the subsystems that are enabled
|
|
||||||
in this instance.
|
|
||||||
|
|
||||||
|
|
||||||
Perms: read
|
Perms: read
|
||||||
|
|
||||||
Inputs: `null`
|
Inputs: `null`
|
||||||
|
|
||||||
Response:
|
Response: `null`
|
||||||
```json
|
|
||||||
[
|
|
||||||
"Mining",
|
|
||||||
"Sealing",
|
|
||||||
"SectorStorage",
|
|
||||||
"Markets"
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sealing
|
## Sealing
|
||||||
|
|
||||||
|
@ -72,7 +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([]api.MinerSubsystem), modules.AddMinerSubsystems(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),
|
||||||
@ -216,6 +216,7 @@ func StorageMiner(out *api.StorageMiner, subsystemsCfg config.MinerSubsystemConf
|
|||||||
|
|
||||||
func(s *Settings) error {
|
func(s *Settings) error {
|
||||||
resAPI := &impl.StorageMinerAPI{}
|
resAPI := &impl.StorageMinerAPI{}
|
||||||
|
|
||||||
s.invokes[ExtractApiKey] = fx.Populate(resAPI)
|
s.invokes[ExtractApiKey] = fx.Populate(resAPI)
|
||||||
*out = resAPI
|
*out = resAPI
|
||||||
return nil
|
return nil
|
||||||
|
@ -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"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
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"
|
||||||
@ -48,11 +48,11 @@ import (
|
|||||||
type StorageMinerAPI struct {
|
type StorageMinerAPI struct {
|
||||||
fx.In
|
fx.In
|
||||||
|
|
||||||
|
Subsystems api.MinerSubsystems
|
||||||
|
|
||||||
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
|
||||||
@ -706,7 +706,7 @@ func (sm *StorageMinerAPI) ComputeProof(ctx context.Context, ssi []builtin.Secto
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StorageMinerAPI) RuntimeSubsystems(context.Context) (res api.MinerSubsystems, err error) {
|
func (sm *StorageMinerAPI) RuntimeSubsystems(context.Context) (res api.MinerSubsystems, err error) {
|
||||||
return sm.EnabledSubsystems, nil
|
return sm.Subsystems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ api.StorageMiner = &StorageMinerAPI{}
|
var _ api.StorageMiner = &StorageMinerAPI{}
|
||||||
|
@ -1008,18 +1008,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) {
|
func AddMinerSubsystems(cfg config.MinerSubsystemConfig) (res api.MinerSubsystems) {
|
||||||
if cfg.EnableMining {
|
if cfg.EnableMining {
|
||||||
res = append(res, api.SubsystemMining)
|
res = append(res, api.MiningSubsystem)
|
||||||
}
|
}
|
||||||
if cfg.EnableSealing {
|
if cfg.EnableSealing {
|
||||||
res = append(res, api.SubsystemSealing)
|
res = append(res, api.SealingSubsystem)
|
||||||
}
|
}
|
||||||
if cfg.EnableSectorStorage {
|
if cfg.EnableSectorStorage {
|
||||||
res = append(res, api.SubsystemSectorStorage)
|
res = append(res, api.SectorStorageSubsystem)
|
||||||
}
|
}
|
||||||
if cfg.EnableMarkets {
|
if cfg.EnableMarkets {
|
||||||
res = append(res, api.SubsystemMarkets)
|
res = append(res, api.MarketsSubsystem)
|
||||||
}
|
}
|
||||||
return res
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user