lotus/storage/miner.go

178 lines
5.1 KiB
Go
Raw Normal View History

2019-07-29 18:57:23 +00:00
package storage
import (
"context"
"errors"
2019-12-03 00:08:08 +00:00
"time"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-sectorbuilder"
2019-07-29 18:57:23 +00:00
"github.com/ipfs/go-cid"
"github.com/ipfs/go-datastore"
logging "github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p-core/host"
"golang.org/x/xerrors"
2019-07-29 18:57:23 +00:00
"github.com/filecoin-project/lotus/api"
2019-11-30 23:17:50 +00:00
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/events"
2019-11-25 04:45:13 +00:00
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/storage/sealing"
2019-07-29 18:57:23 +00:00
)
var log = logging.Logger("storageminer")
type Miner struct {
api storageMinerApi
h host.Host
sb sectorbuilder.Interface
ds datastore.Batching
tktFn sealing.TicketFn
2019-07-29 18:57:23 +00:00
2019-11-01 13:58:48 +00:00
maddr address.Address
2019-07-29 18:57:23 +00:00
worker address.Address
sealing *sealing.Sealing
2019-09-19 16:17:49 +00:00
2020-01-16 02:54:57 +00:00
stop chan struct{}
stopped chan struct{}
2019-07-29 18:57:23 +00:00
}
type storageMinerApi interface {
// Call a read only method on actors (no interaction with the chain required)
2020-01-21 18:51:17 +00:00
StateCall(context.Context, *types.Message, *types.TipSet) (*api.MethodCall, error)
StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error)
StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error)
2019-11-08 18:15:13 +00:00
StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error)
StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error)
StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error)
2019-11-20 19:44:38 +00:00
StateWaitMsg(context.Context, cid.Cid) (*api.MsgWait, error) // TODO: removeme eventually
2019-11-19 21:27:25 +00:00
StateGetActor(ctx context.Context, actor address.Address, ts *types.TipSet) (*types.Actor, error)
StateGetReceipt(context.Context, cid.Cid, *types.TipSet) (*types.MessageReceipt, error)
2019-07-29 18:57:23 +00:00
2019-09-19 16:17:49 +00:00
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error)
2019-07-29 18:57:23 +00:00
ChainHead(context.Context) (*types.TipSet, error)
2019-09-18 11:01:52 +00:00
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error)
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
2019-08-08 04:24:49 +00:00
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
2019-08-08 04:24:49 +00:00
WalletBalance(context.Context, address.Address) (types.BigInt, error)
2019-08-08 17:29:23 +00:00
WalletHas(context.Context, address.Address) (bool, error)
2019-07-29 18:57:23 +00:00
}
func NewMiner(api storageMinerApi, addr address.Address, h host.Host, ds datastore.Batching, sb sectorbuilder.Interface, tktFn sealing.TicketFn) (*Miner, error) {
2020-01-10 02:11:00 +00:00
m := &Miner{
2020-01-16 02:54:57 +00:00
api: api,
2019-07-29 18:57:23 +00:00
h: h,
2019-11-07 18:43:15 +00:00
sb: sb,
2020-01-16 02:54:57 +00:00
ds: ds,
2019-11-07 18:22:59 +00:00
tktFn: tktFn,
2019-11-01 13:58:48 +00:00
maddr: addr,
2020-01-16 02:54:57 +00:00
stop: make(chan struct{}),
stopped: make(chan struct{}),
2020-01-10 02:11:00 +00:00
}
return m, nil
2019-07-29 18:57:23 +00:00
}
func (m *Miner) Run(ctx context.Context) error {
if err := m.runPreflightChecks(ctx); err != nil {
return xerrors.Errorf("miner preflight checks failed: %w", err)
2019-07-29 18:57:23 +00:00
}
fps := &fpostScheduler{
2020-01-16 02:54:57 +00:00
api: m.api,
sb: m.sb,
actor: m.maddr,
worker: m.worker,
}
go fps.run(ctx)
evts := events.NewEvents(ctx, m.api)
m.sealing = sealing.New(m.api, evts, m.maddr, m.worker, m.ds, m.sb, m.tktFn)
2019-12-04 22:14:50 +00:00
2020-01-20 08:23:56 +00:00
go m.sealing.Run(ctx)
2019-07-29 18:57:23 +00:00
return nil
}
2019-11-01 13:58:48 +00:00
func (m *Miner) Stop(ctx context.Context) error {
defer m.sealing.Stop(ctx)
2020-01-10 02:11:00 +00:00
2019-11-01 13:58:48 +00:00
close(m.stop)
select {
case <-m.stopped:
return nil
case <-ctx.Done():
return ctx.Err()
}
2019-07-29 18:57:23 +00:00
}
func (m *Miner) runPreflightChecks(ctx context.Context) error {
worker, err := m.api.StateMinerWorker(ctx, m.maddr, nil)
2019-07-29 18:57:23 +00:00
if err != nil {
return err
}
m.worker = worker
2019-08-08 17:29:23 +00:00
has, err := m.api.WalletHas(ctx, worker)
if err != nil {
return xerrors.Errorf("failed to check wallet for worker key: %w", err)
}
if !has {
return errors.New("key for worker not found in local wallet")
2019-07-29 18:57:23 +00:00
}
log.Infof("starting up miner %s, worker addr %s", m.maddr, m.worker)
2019-07-29 18:57:23 +00:00
return nil
}
2019-11-25 04:45:13 +00:00
2019-12-02 12:51:16 +00:00
type SectorBuilderEpp struct {
2020-01-13 20:47:27 +00:00
sb sectorbuilder.Interface
2019-11-25 04:45:13 +00:00
}
2020-01-13 20:47:27 +00:00
func NewElectionPoStProver(sb sectorbuilder.Interface) *SectorBuilderEpp {
return &SectorBuilderEpp{sb}
2019-11-25 04:45:13 +00:00
}
2019-12-02 12:51:16 +00:00
var _ gen.ElectionPoStProver = (*SectorBuilderEpp)(nil)
2019-11-25 04:45:13 +00:00
2019-12-02 12:51:16 +00:00
func (epp *SectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte) ([]sectorbuilder.EPostCandidate, error) {
2019-12-03 00:08:08 +00:00
start := time.Now()
2019-11-25 04:45:13 +00:00
var faults []uint64 // TODO
var randbuf [32]byte
copy(randbuf[:], rand)
2019-12-03 00:08:08 +00:00
cds, err := epp.sb.GenerateEPostCandidates(ssi, randbuf, faults)
if err != nil {
return nil, err
}
log.Infof("Generate candidates took %s", time.Since(start))
return cds, nil
2019-11-25 04:45:13 +00:00
}
2019-12-02 12:51:16 +00:00
func (epp *SectorBuilderEpp) ComputeProof(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) {
2019-11-30 23:17:50 +00:00
if build.InsecurePoStValidation {
log.Warn("Generating fake EPost proof! You should only see this while running tests!")
return []byte("valid proof"), nil
}
2019-12-03 00:08:08 +00:00
start := time.Now()
proof, err := epp.sb.ComputeElectionPoSt(ssi, rand, winners)
if err != nil {
return nil, err
}
log.Infof("ComputeElectionPost took %s", time.Since(start))
return proof, nil
2019-11-25 04:45:13 +00:00
}