2019-09-13 21:00:36 +00:00
|
|
|
package deals
|
|
|
|
|
|
|
|
import (
|
2019-10-22 17:34:59 +00:00
|
|
|
"bytes"
|
2019-09-13 21:00:36 +00:00
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
2019-11-04 19:57:54 +00:00
|
|
|
"github.com/ipfs/go-datastore"
|
|
|
|
inet "github.com/libp2p/go-libp2p-core/network"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
2019-12-19 20:13:17 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
2020-01-07 14:00:10 +00:00
|
|
|
"github.com/filecoin-project/go-cbor-util"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2019-09-13 21:00:36 +00:00
|
|
|
)
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
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
|
2019-10-21 18:12:11 +00:00
|
|
|
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{
|
2019-10-21 18:12:11 +00:00
|
|
|
Price: price,
|
2019-10-22 10:20:43 +00:00
|
|
|
Timestamp: uint64(now),
|
|
|
|
Expiry: uint64(now + ttlsecs),
|
2019-10-21 18:12:11 +00:00
|
|
|
Miner: p.actor,
|
2019-09-13 21:00:36 +00:00
|
|
|
SeqNo: seqno,
|
2019-10-21 18:12:11 +00:00
|
|
|
MinPieceSize: p.minPieceSize,
|
2019-09-13 21:00:36 +00:00
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
ssa, err := p.signAsk(ask)
|
2019-09-13 21:00:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
return p.saveAsk(ssa)
|
2019-09-13 21:00:36 +00:00
|
|
|
}
|
|
|
|
|
2019-11-04 19:57:54 +00:00
|
|
|
func (p *Provider) GetAsk(m address.Address) *types.SignedStorageAsk {
|
2019-10-21 18:12:11 +00:00
|
|
|
p.askLk.Lock()
|
|
|
|
defer p.askLk.Unlock()
|
|
|
|
if m != p.actor {
|
2019-09-13 21:00:36 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
return p.ask
|
2019-09-13 21:00:36 +00:00
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
func (p *Provider) HandleAskStream(s inet.Stream) {
|
2019-09-13 21:00:36 +00:00
|
|
|
defer s.Close()
|
|
|
|
var ar AskRequest
|
2019-11-07 14:11:39 +00:00
|
|
|
if err := cborutil.ReadCborRPC(s, &ar); err != nil {
|
2019-09-13 21:00:36 +00:00
|
|
|
log.Errorf("failed to read AskRequest from incoming stream: %s", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
resp := p.processAskRequest(&ar)
|
2019-09-13 21:00:36 +00:00
|
|
|
|
2019-11-07 14:11:39 +00:00
|
|
|
if err := cborutil.WriteCborRPC(s, resp); err != nil {
|
2019-09-13 21:00:36 +00:00
|
|
|
log.Errorf("failed to write ask response: %s", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
func (p *Provider) processAskRequest(ar *AskRequest) *AskResponse {
|
2019-09-13 21:00:36 +00:00
|
|
|
return &AskResponse{
|
2019-11-04 19:57:54 +00:00
|
|
|
Ask: p.GetAsk(ar.Miner),
|
2019-09-13 21:00:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var bestAskKey = datastore.NewKey("latest-ask")
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
func (p *Provider) tryLoadAsk() error {
|
|
|
|
p.askLk.Lock()
|
|
|
|
defer p.askLk.Unlock()
|
2019-09-13 21:00:36 +00:00
|
|
|
|
2019-10-21 18:12:11 +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
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
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
|
2019-11-07 14:11:39 +00:00
|
|
|
if err := cborutil.ReadCborRPC(bytes.NewReader(askb), &ssa); err != nil {
|
2019-09-13 21:00:36 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
p.ask = &ssa
|
2019-09-13 21:00:36 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
func (p *Provider) signAsk(a *types.StorageAsk) (*types.SignedStorageAsk, error) {
|
2019-11-07 14:11:39 +00:00
|
|
|
b, err := cborutil.Dump(a)
|
2019-09-13 21:00:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-11-04 19:57:54 +00:00
|
|
|
worker, err := p.spn.GetMinerWorker(context.TODO(), 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)
|
|
|
|
}
|
|
|
|
|
2019-11-04 19:57:54 +00:00
|
|
|
sig, err := p.spn.SignBytes(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
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
func (p *Provider) saveAsk(a *types.SignedStorageAsk) error {
|
2019-11-07 14:11:39 +00:00
|
|
|
b, err := cborutil.Dump(a)
|
2019-09-13 21:00:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
if err := p.ds.Put(bestAskKey, b); err != nil {
|
2019-09-13 21:00:36 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
p.ask = a
|
2019-09-13 21:00:36 +00:00
|
|
|
return nil
|
|
|
|
}
|