lotus/chain/deals/provider_asks.go

161 lines
3.3 KiB
Go
Raw Normal View History

2019-09-13 21:00:36 +00:00
package deals
import (
"context"
"time"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/cborrpc"
2019-09-13 21:00:36 +00:00
datastore "github.com/ipfs/go-datastore"
cbor "github.com/ipfs/go-ipld-cbor"
inet "github.com/libp2p/go-libp2p-core/network"
"golang.org/x/xerrors"
)
func (p *Provider) SetPrice(price types.BigInt, ttlsecs int64) error {
p.askLk.Lock()
defer p.askLk.Unlock()
2019-09-13 21:00:36 +00:00
var seqno uint64
if p.ask != nil {
seqno = p.ask.Ask.SeqNo + 1
2019-09-13 21:00:36 +00:00
}
now := time.Now().Unix()
ask := &types.StorageAsk{
Price: price,
2019-10-22 10:20:43 +00:00
Timestamp: uint64(now),
Expiry: uint64(now + ttlsecs),
Miner: p.actor,
2019-09-13 21:00:36 +00:00
SeqNo: seqno,
MinPieceSize: p.minPieceSize,
2019-09-13 21:00:36 +00:00
}
ssa, err := p.signAsk(ask)
2019-09-13 21:00:36 +00:00
if err != nil {
return err
}
return p.saveAsk(ssa)
2019-09-13 21:00:36 +00:00
}
func (p *Provider) getAsk(m address.Address) *types.SignedStorageAsk {
p.askLk.Lock()
defer p.askLk.Unlock()
if m != p.actor {
2019-09-13 21:00:36 +00:00
return nil
}
return p.ask
2019-09-13 21:00:36 +00:00
}
func (p *Provider) HandleAskStream(s inet.Stream) {
2019-09-13 21:00:36 +00:00
defer s.Close()
var ar AskRequest
if err := cborrpc.ReadCborRPC(s, &ar); err != nil {
log.Errorf("failed to read AskRequest from incoming stream: %s", err)
return
}
resp := p.processAskRequest(&ar)
2019-09-13 21:00:36 +00:00
if err := cborrpc.WriteCborRPC(s, resp); err != nil {
log.Errorf("failed to write ask response: %s", err)
return
}
}
func (p *Provider) processAskRequest(ar *AskRequest) *AskResponse {
2019-09-13 21:00:36 +00:00
return &AskResponse{
Ask: p.getAsk(ar.Miner),
2019-09-13 21:00:36 +00:00
}
}
var bestAskKey = datastore.NewKey("latest-ask")
func (p *Provider) tryLoadAsk() error {
p.askLk.Lock()
defer p.askLk.Unlock()
2019-09-13 21:00:36 +00:00
err := p.loadAsk()
2019-09-13 21:00:36 +00:00
if err != nil {
if xerrors.Is(err, datastore.ErrNotFound) {
log.Warn("no previous ask found, miner will not accept deals until a price is set")
return nil
}
return err
}
return nil
}
func (p *Provider) loadAsk() error {
askb, err := p.ds.Get(datastore.NewKey("latest-ask"))
2019-09-13 21:00:36 +00:00
if err != nil {
return xerrors.Errorf("failed to load most recent ask from disk: %w", err)
}
var ssa types.SignedStorageAsk
if err := cbor.DecodeInto(askb, &ssa); err != nil {
return err
}
p.ask = &ssa
2019-09-13 21:00:36 +00:00
return nil
}
func (p *Provider) signAsk(a *types.StorageAsk) (*types.SignedStorageAsk, error) {
2019-09-13 21:00:36 +00:00
b, err := cbor.DumpObject(a)
if err != nil {
return nil, err
}
worker, err := p.getWorker(p.actor)
2019-09-13 21:00:36 +00:00
if err != nil {
return nil, xerrors.Errorf("failed to get worker to sign ask: %w", err)
}
sig, err := p.full.WalletSign(context.TODO(), worker, b)
2019-09-13 21:00:36 +00:00
if err != nil {
return nil, err
}
return &types.SignedStorageAsk{
Ask: a,
Signature: sig,
}, nil
}
func (p *Provider) saveAsk(a *types.SignedStorageAsk) error {
2019-09-13 21:00:36 +00:00
b, err := cbor.DumpObject(a)
if err != nil {
return err
}
if err := p.ds.Put(bestAskKey, b); err != nil {
2019-09-13 21:00:36 +00:00
return err
}
p.ask = a
2019-09-13 21:00:36 +00:00
return nil
}
func (c *Client) checkAskSignature(ask *types.SignedStorageAsk) error {
2019-10-02 20:03:27 +00:00
tss := c.sm.ChainStore().GetHeaviestTipSet().ParentState()
2019-09-13 21:00:36 +00:00
w, err := stmgr.GetMinerWorker(context.TODO(), c.sm, tss, ask.Ask.Miner)
if err != nil {
return xerrors.Errorf("failed to get worker for miner in ask", err)
}
sigb, err := cbor.DumpObject(ask.Ask)
if err != nil {
return xerrors.Errorf("failed to re-serialize ask")
}
return ask.Signature.Verify(w, sigb)
}