2019-07-29 18:57:23 +00:00
|
|
|
package storage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-11-22 16:20:56 +00:00
|
|
|
"errors"
|
2020-03-18 01:08:11 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
2019-12-03 00:08:08 +00:00
|
|
|
"time"
|
2019-11-06 06:26:50 +00:00
|
|
|
|
2020-01-16 02:55:12 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
2020-03-06 05:30:47 +00:00
|
|
|
"github.com/filecoin-project/specs-storage/storage"
|
2019-07-29 18:57:23 +00:00
|
|
|
"github.com/ipfs/go-cid"
|
|
|
|
"github.com/ipfs/go-datastore"
|
2020-01-08 19:10:57 +00:00
|
|
|
logging "github.com/ipfs/go-log/v2"
|
2019-09-18 13:32:21 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/host"
|
2019-11-22 16:20:56 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-07-29 18:57:23 +00:00
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
"github.com/filecoin-project/lotus/storage/sectorstorage"
|
2020-03-03 22:19:22 +00:00
|
|
|
|
2020-02-21 17:43:44 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
2020-02-23 20:00:47 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/crypto"
|
2020-02-08 02:18:32 +00:00
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
2019-11-30 23:17:50 +00:00
|
|
|
"github.com/filecoin-project/lotus/build"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/events"
|
2019-11-25 04:45:13 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/gen"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/store"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-01-15 20:49:11 +00:00
|
|
|
"github.com/filecoin-project/lotus/storage/sealing"
|
2019-07-29 18:57:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var log = logging.Logger("storageminer")
|
|
|
|
|
|
|
|
type Miner struct {
|
2020-03-03 22:19:22 +00:00
|
|
|
api storageMinerApi
|
|
|
|
h host.Host
|
2020-03-23 11:40:02 +00:00
|
|
|
sealer sectorstorage.SectorManager
|
2020-03-03 22:19:22 +00:00
|
|
|
ds datastore.Batching
|
|
|
|
tktFn sealing.TicketFn
|
2020-03-18 01:08:11 +00:00
|
|
|
sc sealing.SectorIDCounter
|
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
|
|
|
|
|
2020-01-15 20:49:11 +00:00
|
|
|
sealing *sealing.Sealing
|
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-03-03 23:32:17 +00:00
|
|
|
StateCall(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error)
|
2020-02-11 23:29:45 +00:00
|
|
|
StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error)
|
2020-02-24 17:32:02 +00:00
|
|
|
StateMinerPostState(ctx context.Context, actor address.Address, ts types.TipSetKey) (*miner.PoStState, error)
|
2020-02-11 23:29:45 +00:00
|
|
|
StateMinerSectors(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
|
|
|
|
StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error)
|
2020-02-24 17:32:02 +00:00
|
|
|
StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error)
|
2020-03-18 23:06:53 +00:00
|
|
|
StateWaitMsg(context.Context, cid.Cid) (*api.MsgLookup, error) // TODO: removeme eventually
|
2020-02-24 17:32:02 +00:00
|
|
|
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
2020-02-11 23:29:45 +00:00
|
|
|
StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error)
|
2020-02-24 17:32:02 +00:00
|
|
|
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error)
|
|
|
|
StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, 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
|
|
|
|
2020-02-24 17:45:25 +00:00
|
|
|
ChainHead(context.Context) (*types.TipSet, error)
|
2019-09-18 11:01:52 +00:00
|
|
|
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
|
2020-02-23 20:00:47 +00:00
|
|
|
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error)
|
2020-02-24 17:32:02 +00:00
|
|
|
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
|
2019-09-18 11:45:52 +00:00
|
|
|
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
|
2020-01-23 17:34:04 +00:00
|
|
|
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
2020-02-13 03:50:37 +00:00
|
|
|
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
2019-08-08 04:24:49 +00:00
|
|
|
|
2020-02-25 21:09:22 +00:00
|
|
|
WalletSign(context.Context, address.Address, []byte) (*crypto.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
|
|
|
}
|
|
|
|
|
2020-03-23 11:40:02 +00:00
|
|
|
func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, ds datastore.Batching, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, tktFn sealing.TicketFn) (*Miner, error) {
|
2020-01-10 02:11:00 +00:00
|
|
|
m := &Miner{
|
2020-03-03 22:19:22 +00:00
|
|
|
api: api,
|
|
|
|
h: h,
|
|
|
|
sealer: sealer,
|
|
|
|
ds: ds,
|
|
|
|
tktFn: tktFn,
|
2020-03-18 01:08:11 +00:00
|
|
|
sc: sc,
|
2019-11-01 13:58:48 +00:00
|
|
|
|
2020-02-03 20:09:21 +00:00
|
|
|
maddr: maddr,
|
|
|
|
worker: worker,
|
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 {
|
2019-11-22 16:20:56 +00:00
|
|
|
return xerrors.Errorf("miner preflight checks failed: %w", err)
|
2019-07-29 18:57:23 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 20:49:11 +00:00
|
|
|
evts := events.NewEvents(ctx, m.api)
|
2020-03-18 01:08:11 +00:00
|
|
|
m.sealing = sealing.New(m.api, evts, m.maddr, m.worker, m.ds, m.sealer, m.sc, 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 {
|
2020-01-15 20:49:11 +00:00
|
|
|
defer m.sealing.Stop(ctx)
|
2020-01-23 09:46:46 +00:00
|
|
|
return nil
|
2019-07-29 18:57:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Miner) runPreflightChecks(ctx context.Context) error {
|
2020-02-03 20:09:21 +00:00
|
|
|
has, err := m.api.WalletHas(ctx, m.worker)
|
2019-07-30 00:46:56 +00:00
|
|
|
if err != nil {
|
2019-11-22 16:20:56 +00:00
|
|
|
return xerrors.Errorf("failed to check wallet for worker key: %w", err)
|
2019-07-30 00:46:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !has {
|
|
|
|
return errors.New("key for worker not found in local wallet")
|
2019-07-29 18:57:23 +00:00
|
|
|
}
|
|
|
|
|
2019-07-30 00:46:56 +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-03-06 05:30:47 +00:00
|
|
|
prover storage.Prover
|
2020-03-18 01:08:11 +00:00
|
|
|
miner abi.ActorID
|
2019-11-25 04:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 01:08:11 +00:00
|
|
|
func NewElectionPoStProver(sb storage.Prover, miner dtypes.MinerID) *SectorBuilderEpp {
|
|
|
|
return &SectorBuilderEpp{sb, abi.ActorID(miner)}
|
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
|
|
|
|
2020-03-06 05:30:47 +00:00
|
|
|
func (epp *SectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi []abi.SectorInfo, rand abi.PoStRandomness) ([]storage.PoStCandidateWithTicket, error) {
|
2019-12-03 00:08:08 +00:00
|
|
|
start := time.Now()
|
2020-02-08 02:18:32 +00:00
|
|
|
var faults []abi.SectorNumber // TODO
|
2019-11-25 04:45:13 +00:00
|
|
|
|
2020-03-17 20:19:52 +00:00
|
|
|
cds, err := epp.prover.GenerateEPostCandidates(ctx, epp.miner, ssi, rand, faults)
|
2019-12-03 00:08:08 +00:00
|
|
|
if err != nil {
|
2020-02-28 18:01:43 +00:00
|
|
|
return nil, xerrors.Errorf("failed to generate candidates: %w", err)
|
2019-12-03 00:08:08 +00:00
|
|
|
}
|
|
|
|
log.Infof("Generate candidates took %s", time.Since(start))
|
|
|
|
return cds, nil
|
2019-11-25 04:45:13 +00:00
|
|
|
}
|
|
|
|
|
2020-03-06 05:30:47 +00:00
|
|
|
func (epp *SectorBuilderEpp) ComputeProof(ctx context.Context, ssi []abi.SectorInfo, rand []byte, winners []storage.PoStCandidateWithTicket) ([]abi.PoStProof, 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!")
|
2020-02-27 21:45:31 +00:00
|
|
|
return []abi.PoStProof{{ProofBytes: []byte("valid proof")}}, nil
|
2019-11-30 23:17:50 +00:00
|
|
|
}
|
2020-02-27 21:45:31 +00:00
|
|
|
|
|
|
|
owins := make([]abi.PoStCandidate, 0, len(winners))
|
|
|
|
for _, w := range winners {
|
|
|
|
owins = append(owins, w.Candidate)
|
|
|
|
}
|
|
|
|
|
2019-12-03 00:08:08 +00:00
|
|
|
start := time.Now()
|
2020-03-17 20:19:52 +00:00
|
|
|
proof, err := epp.prover.ComputeElectionPoSt(ctx, epp.miner, ssi, rand, owins)
|
2019-12-03 00:08:08 +00:00
|
|
|
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
|
|
|
}
|