2019-09-06 06:26:02 +00:00
|
|
|
package stmgr
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-10-16 07:07:16 +00:00
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
|
|
"github.com/filecoin-project/lotus/chain/actors"
|
|
|
|
"github.com/filecoin-project/lotus/chain/address"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2019-09-17 22:43:47 +00:00
|
|
|
|
|
|
|
amt "github.com/filecoin-project/go-amt-ipld"
|
2019-09-06 06:26:02 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
2019-10-16 07:07:16 +00:00
|
|
|
hamt "github.com/ipfs/go-hamt-ipld"
|
2019-09-18 02:55:51 +00:00
|
|
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
2019-09-17 22:43:47 +00:00
|
|
|
cbor "github.com/ipfs/go-ipld-cbor"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
2019-09-06 06:26:02 +00:00
|
|
|
"golang.org/x/xerrors"
|
|
|
|
)
|
|
|
|
|
2019-10-23 17:39:14 +00:00
|
|
|
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
2019-09-09 20:03:10 +00:00
|
|
|
recp, err := sm.CallRaw(ctx, &types.Message{
|
2019-09-06 06:26:02 +00:00
|
|
|
To: maddr,
|
|
|
|
From: maddr,
|
|
|
|
Method: actors.MAMethods.GetWorkerAddr,
|
2019-09-20 02:54:52 +00:00
|
|
|
}, st, nil, 0)
|
2019-09-06 06:26:02 +00:00
|
|
|
if err != nil {
|
|
|
|
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if recp.ExitCode != 0 {
|
|
|
|
return address.Undef, xerrors.Errorf("getting miner worker addr failed (exit code %d)", recp.ExitCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
worker, err := address.NewFromBytes(recp.Return)
|
|
|
|
if err != nil {
|
|
|
|
return address.Undef, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if worker.Protocol() == address.ID {
|
|
|
|
return address.Undef, xerrors.Errorf("need to resolve worker address to a pubkeyaddr")
|
|
|
|
}
|
|
|
|
|
|
|
|
return worker, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
2019-09-09 20:03:10 +00:00
|
|
|
recp, err := sm.CallRaw(ctx, &types.Message{
|
2019-09-06 06:26:02 +00:00
|
|
|
To: maddr,
|
|
|
|
From: maddr,
|
|
|
|
Method: actors.MAMethods.GetOwner,
|
2019-09-20 02:54:52 +00:00
|
|
|
}, st, nil, 0)
|
2019-09-06 06:26:02 +00:00
|
|
|
if err != nil {
|
|
|
|
return address.Undef, xerrors.Errorf("callRaw failed: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if recp.ExitCode != 0 {
|
|
|
|
return address.Undef, xerrors.Errorf("getting miner owner addr failed (exit code %d)", recp.ExitCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
owner, err := address.NewFromBytes(recp.Return)
|
|
|
|
if err != nil {
|
|
|
|
return address.Undef, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if owner.Protocol() == address.ID {
|
|
|
|
return address.Undef, xerrors.Errorf("need to resolve owner address to a pubkeyaddr")
|
|
|
|
}
|
|
|
|
|
|
|
|
return owner, nil
|
|
|
|
}
|
2019-09-09 20:03:10 +00:00
|
|
|
|
|
|
|
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
var mpow types.BigInt
|
|
|
|
|
|
|
|
if maddr != address.Undef {
|
2019-10-15 14:59:31 +00:00
|
|
|
enc, aerr := actors.SerializeParams(&actors.PowerLookupParams{maddr})
|
|
|
|
if aerr != nil {
|
|
|
|
return types.EmptyInt, types.EmptyInt, aerr
|
|
|
|
}
|
2019-09-09 20:03:10 +00:00
|
|
|
ret, err := sm.Call(ctx, &types.Message{
|
|
|
|
From: maddr,
|
2019-10-19 08:06:41 +00:00
|
|
|
To: actors.StoragePowerAddress,
|
2019-10-11 22:59:36 +00:00
|
|
|
Method: actors.SPAMethods.PowerLookup,
|
2019-09-09 20:03:10 +00:00
|
|
|
Params: enc,
|
|
|
|
}, ts)
|
|
|
|
if err != nil {
|
|
|
|
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain: %w", err)
|
|
|
|
}
|
|
|
|
if ret.ExitCode != 0 {
|
|
|
|
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain (exit code %d)", ret.ExitCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
mpow = types.BigFromBytes(ret.Return)
|
|
|
|
}
|
|
|
|
|
|
|
|
ret, err := sm.Call(ctx, &types.Message{
|
2019-10-19 08:06:41 +00:00
|
|
|
From: actors.StoragePowerAddress,
|
|
|
|
To: actors.StoragePowerAddress,
|
2019-10-11 22:59:36 +00:00
|
|
|
Method: actors.SPAMethods.GetTotalStorage,
|
2019-09-09 20:03:10 +00:00
|
|
|
}, ts)
|
|
|
|
if err != nil {
|
|
|
|
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err)
|
|
|
|
}
|
|
|
|
if ret.ExitCode != 0 {
|
|
|
|
return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
tpow := types.BigFromBytes(ret.Return)
|
|
|
|
|
|
|
|
return mpow, tpow, nil
|
|
|
|
}
|
2019-09-17 08:00:38 +00:00
|
|
|
|
|
|
|
func GetMinerPeerID(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (peer.ID, error) {
|
|
|
|
recp, err := sm.Call(ctx, &types.Message{
|
|
|
|
To: maddr,
|
|
|
|
From: maddr,
|
2019-09-17 08:34:41 +00:00
|
|
|
Method: actors.MAMethods.GetPeerID,
|
2019-09-17 08:00:38 +00:00
|
|
|
}, ts)
|
|
|
|
if err != nil {
|
2019-10-23 17:39:14 +00:00
|
|
|
return "", xerrors.Errorf("call failed: %w", err)
|
2019-09-17 08:00:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if recp.ExitCode != 0 {
|
|
|
|
return "", xerrors.Errorf("getting miner peer ID failed (exit code %d)", recp.ExitCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
return peer.IDFromBytes(recp.Return)
|
|
|
|
}
|
2019-09-17 22:43:47 +00:00
|
|
|
|
2019-10-23 17:39:14 +00:00
|
|
|
func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (address.Address, error) {
|
|
|
|
recp, err := sm.Call(ctx, &types.Message{
|
|
|
|
To: maddr,
|
|
|
|
From: maddr,
|
|
|
|
Method: actors.MAMethods.GetWorkerAddr,
|
|
|
|
}, ts)
|
|
|
|
if err != nil {
|
|
|
|
return address.Undef, xerrors.Errorf("call failed: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if recp.ExitCode != 0 {
|
|
|
|
return address.Undef, xerrors.Errorf("getting miner peer ID failed (exit code %d)", recp.ExitCode)
|
|
|
|
}
|
|
|
|
|
|
|
|
return address.NewFromBytes(recp.Return)
|
|
|
|
}
|
|
|
|
|
2019-09-17 22:43:47 +00:00
|
|
|
func GetMinerProvingPeriodEnd(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
|
|
|
var mas actors.StorageMinerActorState
|
|
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
|
|
if err != nil {
|
|
|
|
return 0, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return mas.ProvingPeriodEnd, nil
|
|
|
|
}
|
|
|
|
|
2019-09-18 02:50:03 +00:00
|
|
|
func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.SectorInfo, error) {
|
2019-09-17 22:43:47 +00:00
|
|
|
var mas actors.StorageMinerActorState
|
|
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
2019-09-18 02:55:51 +00:00
|
|
|
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.ProvingSet)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.SectorInfo, error) {
|
|
|
|
var mas actors.StorageMinerActorState
|
|
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors)
|
|
|
|
}
|
|
|
|
|
2019-10-16 07:07:16 +00:00
|
|
|
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
|
|
|
var mas actors.StorageMinerActorState
|
|
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
|
|
if err != nil {
|
|
|
|
return 0, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
|
|
|
|
var minfo actors.MinerInfo
|
|
|
|
if err := cst.Get(ctx, mas.Info, &minfo); err != nil {
|
|
|
|
return 0, xerrors.Errorf("failed to read miner info: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return minfo.SectorSize, nil
|
|
|
|
}
|
|
|
|
|
2019-09-18 02:55:51 +00:00
|
|
|
func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid) ([]*api.SectorInfo, error) {
|
|
|
|
blks := amt.WrapBlockstore(bs)
|
|
|
|
a, err := amt.LoadAMT(blks, ssc)
|
2019-09-17 22:43:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-09-18 02:50:03 +00:00
|
|
|
var sset []*api.SectorInfo
|
2019-09-17 22:43:47 +00:00
|
|
|
if err := a.ForEach(func(i uint64, v *cbg.Deferred) error {
|
|
|
|
var comms [][]byte
|
|
|
|
if err := cbor.DecodeInto(v.Raw, &comms); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-09-18 02:50:03 +00:00
|
|
|
sset = append(sset, &api.SectorInfo{
|
2019-09-17 22:43:47 +00:00
|
|
|
SectorID: i,
|
|
|
|
CommR: comms[0],
|
|
|
|
CommD: comms[1],
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sset, nil
|
|
|
|
}
|