feat(storagemarket): extract storage market
remove all shared components, point at go-fil-components repo
This commit is contained in:
parent
0a4eeb7cb1
commit
65ecb33630
@ -1,784 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
|
||||||
xerrors "golang.org/x/xerrors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT.
|
|
||||||
|
|
||||||
var _ = xerrors.Errorf
|
|
||||||
|
|
||||||
func (t *AskRequest) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{129}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Miner (address.Address) (struct)
|
|
||||||
if err := t.Miner.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *AskRequest) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 1 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Miner (address.Address) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.Miner.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *AskResponse) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{129}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Ask (types.SignedStorageAsk) (struct)
|
|
||||||
if err := t.Ask.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *AskResponse) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 1 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Ask (types.SignedStorageAsk) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
pb, err := br.PeekByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pb == cbg.CborNull[0] {
|
|
||||||
var nbuf [1]byte
|
|
||||||
if _, err := br.Read(nbuf[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Ask = new(types.SignedStorageAsk)
|
|
||||||
if err := t.Ask.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Proposal) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{130}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.DealProposal (actors.StorageDealProposal) (struct)
|
|
||||||
if err := t.DealProposal.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Piece (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.Piece); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.Piece: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Proposal) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 2 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.DealProposal (actors.StorageDealProposal) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
pb, err := br.PeekByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pb == cbg.CborNull[0] {
|
|
||||||
var nbuf [1]byte
|
|
||||||
if _, err := br.Read(nbuf[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.DealProposal = new(actors.StorageDealProposal)
|
|
||||||
if err := t.DealProposal.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.Piece (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.Piece: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Piece = c
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Response) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{132}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.State))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Message (string) (string)
|
|
||||||
if len(t.Message) > cbg.MaxLength {
|
|
||||||
return xerrors.Errorf("Value in field t.Message was too long")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Message)))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte(t.Message)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Proposal (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.Proposal); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.Proposal: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.PublishMessage (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if t.PublishMessage == nil {
|
|
||||||
if _, err := w.Write(cbg.CborNull); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := cbg.WriteCid(w, *t.PublishMessage); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.PublishMessage: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Response) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 4 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.State = uint64(extra)
|
|
||||||
// t.Message (string) (string)
|
|
||||||
|
|
||||||
{
|
|
||||||
sval, err := cbg.ReadString(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Message = string(sval)
|
|
||||||
}
|
|
||||||
// t.Proposal (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.Proposal: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Proposal = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.PublishMessage (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
pb, err := br.PeekByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pb == cbg.CborNull[0] {
|
|
||||||
var nbuf [1]byte
|
|
||||||
if _, err := br.Read(nbuf[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.PublishMessage: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.PublishMessage = &c
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *SignedResponse) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{130}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Response (deals.Response) (struct)
|
|
||||||
if err := t.Response.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Signature (types.Signature) (struct)
|
|
||||||
if err := t.Signature.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *SignedResponse) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 2 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Response (deals.Response) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.Response.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.Signature (types.Signature) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
pb, err := br.PeekByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pb == cbg.CborNull[0] {
|
|
||||||
var nbuf [1]byte
|
|
||||||
if _, err := br.Read(nbuf[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Signature = new(types.Signature)
|
|
||||||
if err := t.Signature.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ClientDealProposal) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{136}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Data (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.Data); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.Data: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.PricePerEpoch (types.BigInt) (struct)
|
|
||||||
if err := t.PricePerEpoch.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ProposalExpiration (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ProposalExpiration))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Duration (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Duration))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ProviderAddress (address.Address) (struct)
|
|
||||||
if err := t.ProviderAddress.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Client (address.Address) (struct)
|
|
||||||
if err := t.Client.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.MinerWorker (address.Address) (struct)
|
|
||||||
if err := t.MinerWorker.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.MinerID (peer.ID) (string)
|
|
||||||
if len(t.MinerID) > cbg.MaxLength {
|
|
||||||
return xerrors.Errorf("Value in field t.MinerID was too long")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.MinerID)))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte(t.MinerID)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ClientDealProposal) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 8 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Data (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.Data: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Data = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.PricePerEpoch (types.BigInt) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.PricePerEpoch.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.ProposalExpiration (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.ProposalExpiration = uint64(extra)
|
|
||||||
// t.Duration (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.Duration = uint64(extra)
|
|
||||||
// t.ProviderAddress (address.Address) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.ProviderAddress.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.Client (address.Address) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.Client.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.MinerWorker (address.Address) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.MinerWorker.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.MinerID (peer.ID) (string)
|
|
||||||
|
|
||||||
{
|
|
||||||
sval, err := cbg.ReadString(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t.MinerID = peer.ID(sval)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ClientDeal) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{129}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ClientDeal (storagemarket.ClientDeal) (struct)
|
|
||||||
if err := t.ClientDeal.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ClientDeal) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 1 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ClientDeal (storagemarket.ClientDeal) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.ClientDeal.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *MinerDeal) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{135}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Client (peer.ID) (string)
|
|
||||||
if len(t.Client) > cbg.MaxLength {
|
|
||||||
return xerrors.Errorf("Value in field t.Client was too long")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Client)))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte(t.Client)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Proposal (actors.StorageDealProposal) (struct)
|
|
||||||
if err := t.Proposal.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ProposalCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.ProposalCid); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.ProposalCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.State))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Ref (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.Ref); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.Ref: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.DealID))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.SectorID (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *MinerDeal) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 7 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Client (peer.ID) (string)
|
|
||||||
|
|
||||||
{
|
|
||||||
sval, err := cbg.ReadString(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Client = peer.ID(sval)
|
|
||||||
}
|
|
||||||
// t.Proposal (actors.StorageDealProposal) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.Proposal.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.ProposalCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.ProposalCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.ProposalCid = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.State = uint64(extra)
|
|
||||||
// t.Ref (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.Ref: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Ref = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.DealID = uint64(extra)
|
|
||||||
// t.SectorID (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.SectorID = uint64(extra)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *StorageDataTransferVoucher) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{130}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Proposal (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.Proposal); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.Proposal: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.DealID))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *StorageDataTransferVoucher) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 2 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Proposal (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.Proposal: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Proposal = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.DealID = uint64(extra)
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,293 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
logging "github.com/ipfs/go-log/v2"
|
|
||||||
"github.com/libp2p/go-libp2p-core/host"
|
|
||||||
inet "github.com/libp2p/go-libp2p-core/network"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket/discovery"
|
|
||||||
"github.com/filecoin-project/go-statestore"
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log = logging.Logger("deals")
|
|
||||||
|
|
||||||
type ClientDeal struct {
|
|
||||||
storagemarket.ClientDeal
|
|
||||||
|
|
||||||
s inet.Stream
|
|
||||||
}
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
h host.Host
|
|
||||||
|
|
||||||
// dataTransfer
|
|
||||||
// TODO: once the data transfer module is complete, the
|
|
||||||
// client will listen to events on the data transfer module
|
|
||||||
// Because we are using only a fake DAGService
|
|
||||||
// implementation, there's no validation or events on the client side
|
|
||||||
dataTransfer dtypes.ClientDataTransfer
|
|
||||||
dag dtypes.ClientDAG
|
|
||||||
discovery *discovery.Local
|
|
||||||
|
|
||||||
node storagemarket.StorageClientNode
|
|
||||||
|
|
||||||
deals *statestore.StateStore
|
|
||||||
conns map[cid.Cid]inet.Stream
|
|
||||||
|
|
||||||
incoming chan *ClientDeal
|
|
||||||
updated chan clientDealUpdate
|
|
||||||
|
|
||||||
stop chan struct{}
|
|
||||||
stopped chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientDealUpdate struct {
|
|
||||||
newState api.DealState
|
|
||||||
id cid.Cid
|
|
||||||
err error
|
|
||||||
mut func(*ClientDeal)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(h host.Host, dag dtypes.ClientDAG, dataTransfer dtypes.ClientDataTransfer, discovery *discovery.Local, deals dtypes.ClientDealStore, scn storagemarket.StorageClientNode) *Client {
|
|
||||||
c := &Client{
|
|
||||||
h: h,
|
|
||||||
dataTransfer: dataTransfer,
|
|
||||||
dag: dag,
|
|
||||||
discovery: discovery,
|
|
||||||
node: scn,
|
|
||||||
|
|
||||||
deals: deals,
|
|
||||||
conns: map[cid.Cid]inet.Stream{},
|
|
||||||
|
|
||||||
incoming: make(chan *ClientDeal, 16),
|
|
||||||
updated: make(chan clientDealUpdate, 16),
|
|
||||||
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
stopped: make(chan struct{}),
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) Run(ctx context.Context) {
|
|
||||||
go func() {
|
|
||||||
defer close(c.stopped)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case deal := <-c.incoming:
|
|
||||||
c.onIncoming(deal)
|
|
||||||
case update := <-c.updated:
|
|
||||||
c.onUpdated(ctx, update)
|
|
||||||
case <-c.stop:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) onIncoming(deal *ClientDeal) {
|
|
||||||
log.Info("incoming deal")
|
|
||||||
|
|
||||||
if _, ok := c.conns[deal.ProposalCid]; ok {
|
|
||||||
log.Errorf("tracking deal connection: already tracking connection for deal %s", deal.ProposalCid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.conns[deal.ProposalCid] = deal.s
|
|
||||||
|
|
||||||
if err := c.deals.Begin(deal.ProposalCid, deal); err != nil {
|
|
||||||
// We may have re-sent the proposal
|
|
||||||
log.Errorf("deal tracking failed: %s", err)
|
|
||||||
c.failDeal(deal.ProposalCid, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
c.updated <- clientDealUpdate{
|
|
||||||
newState: api.DealUnknown,
|
|
||||||
id: deal.ProposalCid,
|
|
||||||
err: nil,
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) onUpdated(ctx context.Context, update clientDealUpdate) {
|
|
||||||
log.Infof("Client deal %s updated state to %s", update.id, api.DealStates[update.newState])
|
|
||||||
var deal ClientDeal
|
|
||||||
err := c.deals.Mutate(update.id, func(d *ClientDeal) error {
|
|
||||||
d.State = update.newState
|
|
||||||
if update.mut != nil {
|
|
||||||
update.mut(d)
|
|
||||||
}
|
|
||||||
deal = *d
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if update.err != nil {
|
|
||||||
log.Errorf("deal %s failed: %s", update.id, update.err)
|
|
||||||
c.failDeal(update.id, update.err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.failDeal(update.id, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch update.newState {
|
|
||||||
case api.DealUnknown: // new
|
|
||||||
c.handle(ctx, deal, c.new, api.DealAccepted)
|
|
||||||
case api.DealAccepted:
|
|
||||||
c.handle(ctx, deal, c.accepted, api.DealStaged)
|
|
||||||
case api.DealStaged:
|
|
||||||
c.handle(ctx, deal, c.staged, api.DealSealing)
|
|
||||||
case api.DealSealing:
|
|
||||||
c.handle(ctx, deal, c.sealing, api.DealNoUpdate)
|
|
||||||
// TODO: DealComplete -> watch for faults, expiration, etc.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ClientDealProposal struct {
|
|
||||||
Data cid.Cid
|
|
||||||
|
|
||||||
PricePerEpoch types.BigInt
|
|
||||||
ProposalExpiration uint64
|
|
||||||
Duration uint64
|
|
||||||
|
|
||||||
ProviderAddress address.Address
|
|
||||||
Client address.Address
|
|
||||||
MinerWorker address.Address
|
|
||||||
MinerID peer.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) Start(ctx context.Context, p ClientDealProposal) (cid.Cid, error) {
|
|
||||||
amount := types.BigMul(p.PricePerEpoch, types.NewInt(p.Duration))
|
|
||||||
if err := c.node.EnsureFunds(ctx, p.Client, storagemarket.TokenAmount(amount)); err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("adding market funds failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
commP, pieceSize, err := c.commP(ctx, p.Data)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("computing commP failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dealProposal := &actors.StorageDealProposal{
|
|
||||||
PieceRef: commP,
|
|
||||||
PieceSize: uint64(pieceSize),
|
|
||||||
Client: p.Client,
|
|
||||||
Provider: p.ProviderAddress,
|
|
||||||
ProposalExpiration: p.ProposalExpiration,
|
|
||||||
Duration: p.Duration,
|
|
||||||
StoragePricePerEpoch: p.PricePerEpoch,
|
|
||||||
StorageCollateral: types.NewInt(uint64(pieceSize)), // TODO: real calc
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.node.SignProposal(ctx, p.Client, dealProposal); err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("signing deal proposal failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
proposalNd, err := cborutil.AsIpld(dealProposal)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("getting proposal node failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := c.h.NewStream(ctx, p.MinerID, storagemarket.DealProtocolID)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("connecting to storage provider failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
proposal := &Proposal{
|
|
||||||
DealProposal: dealProposal,
|
|
||||||
Piece: p.Data,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cborutil.WriteCborRPC(s, proposal); err != nil {
|
|
||||||
s.Reset()
|
|
||||||
return cid.Undef, xerrors.Errorf("sending proposal to storage provider failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
deal := &ClientDeal{
|
|
||||||
ClientDeal: storagemarket.ClientDeal{
|
|
||||||
ProposalCid: proposalNd.Cid(),
|
|
||||||
Proposal: *dealProposal,
|
|
||||||
State: api.DealUnknown,
|
|
||||||
Miner: p.MinerID,
|
|
||||||
MinerWorker: p.MinerWorker,
|
|
||||||
PayloadCid: p.Data,
|
|
||||||
},
|
|
||||||
|
|
||||||
s: s,
|
|
||||||
}
|
|
||||||
|
|
||||||
c.incoming <- deal
|
|
||||||
|
|
||||||
return deal.ProposalCid, c.discovery.AddPeer(p.Data, retrievalmarket.RetrievalPeer{
|
|
||||||
Address: dealProposal.Provider,
|
|
||||||
ID: deal.Miner,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) QueryAsk(ctx context.Context, p peer.ID, a address.Address) (*types.SignedStorageAsk, error) {
|
|
||||||
s, err := c.h.NewStream(ctx, p, storagemarket.AskProtocolID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to open stream to miner: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &AskRequest{
|
|
||||||
Miner: a,
|
|
||||||
}
|
|
||||||
if err := cborutil.WriteCborRPC(s, req); err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to send ask request: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out AskResponse
|
|
||||||
if err := cborutil.ReadCborRPC(s, &out); err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to read ask response: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if out.Ask == nil {
|
|
||||||
return nil, xerrors.Errorf("got no ask back")
|
|
||||||
}
|
|
||||||
|
|
||||||
if out.Ask.Ask.Miner != a {
|
|
||||||
return nil, xerrors.Errorf("got back ask for wrong miner")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.checkAskSignature(out.Ask); err != nil {
|
|
||||||
return nil, xerrors.Errorf("ask was not properly signed")
|
|
||||||
}
|
|
||||||
|
|
||||||
return out.Ask, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) List() ([]ClientDeal, error) {
|
|
||||||
var out []ClientDeal
|
|
||||||
if err := c.deals.List(&out); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetDeal(d cid.Cid) (*ClientDeal, error) {
|
|
||||||
var out ClientDeal
|
|
||||||
if err := c.deals.Get(d, &out); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) Stop() {
|
|
||||||
close(c.stop)
|
|
||||||
<-c.stopped
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
type clientHandlerFunc func(ctx context.Context, deal ClientDeal) (func(*ClientDeal), error)
|
|
||||||
|
|
||||||
func (c *Client) handle(ctx context.Context, deal ClientDeal, cb clientHandlerFunc, next api.DealState) {
|
|
||||||
go func() {
|
|
||||||
mut, err := cb(ctx, deal)
|
|
||||||
if err != nil {
|
|
||||||
next = api.DealError
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil && next == api.DealNoUpdate {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case c.updated <- clientDealUpdate{
|
|
||||||
newState: next,
|
|
||||||
id: deal.ProposalCid,
|
|
||||||
err: err,
|
|
||||||
mut: mut,
|
|
||||||
}:
|
|
||||||
case <-c.stop:
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) new(ctx context.Context, deal ClientDeal) (func(*ClientDeal), error) {
|
|
||||||
resp, err := c.readStorageDealResp(deal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: verify StorageDealSubmission
|
|
||||||
|
|
||||||
if err := c.disconnect(deal); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
/* data transfer happens */
|
|
||||||
if resp.State != api.DealAccepted {
|
|
||||||
return nil, xerrors.Errorf("deal wasn't accepted (State=%d)", resp.State)
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(info *ClientDeal) {
|
|
||||||
info.PublishMessage = resp.PublishMessage
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) accepted(ctx context.Context, deal ClientDeal) (func(*ClientDeal), error) {
|
|
||||||
log.Infow("DEAL ACCEPTED!")
|
|
||||||
|
|
||||||
dealId, err := c.node.ValidatePublishedDeal(ctx, deal.ClientDeal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(info *ClientDeal) {
|
|
||||||
info.DealID = dealId
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) staged(ctx context.Context, deal ClientDeal) (func(*ClientDeal), error) {
|
|
||||||
// TODO: Maybe wait for pre-commit
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) sealing(ctx context.Context, deal ClientDeal) (func(*ClientDeal), error) {
|
|
||||||
cb := func(err error) {
|
|
||||||
select {
|
|
||||||
case c.updated <- clientDealUpdate{
|
|
||||||
newState: api.DealComplete,
|
|
||||||
id: deal.ProposalCid,
|
|
||||||
err: err,
|
|
||||||
}:
|
|
||||||
case <-c.stop:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := c.node.OnDealSectorCommitted(ctx, deal.Proposal.Provider, deal.DealID, cb)
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) checkAskSignature(ask *types.SignedStorageAsk) error {
|
|
||||||
return c.node.ValidateAskSignature(ask)
|
|
||||||
}
|
|
@ -1,118 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
// this file implements storagemarket.StorageClient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) ListProviders(ctx context.Context) (<-chan storagemarket.StorageProviderInfo, error) {
|
|
||||||
providers, err := c.node.ListStorageProviders(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
out := make(chan storagemarket.StorageProviderInfo)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for _, p := range providers {
|
|
||||||
select {
|
|
||||||
case out <- *p:
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ListDeals(ctx context.Context, addr address.Address) ([]actors.OnChainDeal, error) {
|
|
||||||
return c.node.ListClientDeals(ctx, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ListInProgressDeals(ctx context.Context) ([]storagemarket.ClientDeal, error) {
|
|
||||||
deals, err := c.List()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
out := make([]storagemarket.ClientDeal, len(deals))
|
|
||||||
for k, v := range deals {
|
|
||||||
out[k] = storagemarket.ClientDeal{
|
|
||||||
ProposalCid: v.ProposalCid,
|
|
||||||
Proposal: v.Proposal,
|
|
||||||
State: v.State,
|
|
||||||
Miner: v.Miner,
|
|
||||||
MinerWorker: v.MinerWorker,
|
|
||||||
DealID: v.DealID,
|
|
||||||
PublishMessage: v.PublishMessage,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetInProgressDeal(ctx context.Context, cid cid.Cid) (storagemarket.ClientDeal, error) {
|
|
||||||
deals, err := c.ListInProgressDeals(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return storagemarket.ClientDeal{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, deal := range deals {
|
|
||||||
if deal.ProposalCid == cid {
|
|
||||||
return deal, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return storagemarket.ClientDeal{}, xerrors.Errorf("couldn't find client deal")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetAsk(ctx context.Context, info storagemarket.StorageProviderInfo) (*storagemarket.StorageAsk, error) {
|
|
||||||
return c.QueryAsk(ctx, info.PeerID, info.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ProposeStorageDeal(ctx context.Context, addr address.Address, info *storagemarket.StorageProviderInfo, payloadCid cid.Cid, proposalExpiration storagemarket.Epoch, duration storagemarket.Epoch, price storagemarket.TokenAmount, collateral storagemarket.TokenAmount) (*storagemarket.ProposeStorageDealResult, error) {
|
|
||||||
|
|
||||||
proposal := ClientDealProposal{
|
|
||||||
Data: payloadCid,
|
|
||||||
PricePerEpoch: types.BigInt(price),
|
|
||||||
ProposalExpiration: uint64(proposalExpiration),
|
|
||||||
Duration: uint64(duration),
|
|
||||||
Client: addr,
|
|
||||||
ProviderAddress: info.Address,
|
|
||||||
MinerWorker: info.Worker,
|
|
||||||
MinerID: info.PeerID,
|
|
||||||
}
|
|
||||||
|
|
||||||
proposalCid, err := c.Start(ctx, proposal)
|
|
||||||
|
|
||||||
result := &storagemarket.ProposeStorageDealResult{
|
|
||||||
ProposalCid: proposalCid,
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetPaymentEscrow(ctx context.Context, addr address.Address) (storagemarket.Balance, error) {
|
|
||||||
|
|
||||||
balance, err := c.node.GetBalance(ctx, addr)
|
|
||||||
|
|
||||||
return balance, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) AddPaymentEscrow(ctx context.Context, addr address.Address, amount storagemarket.TokenAmount) error {
|
|
||||||
|
|
||||||
return c.node.AddFunds(ctx, addr, amount)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ storagemarket.StorageClient = &Client{}
|
|
@ -1,170 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
files "github.com/ipfs/go-ipfs-files"
|
|
||||||
unixfile "github.com/ipfs/go-unixfs/file"
|
|
||||||
"github.com/ipld/go-ipld-prime"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
cborutil "github.com/filecoin-project/go-cbor-util"
|
|
||||||
"github.com/filecoin-project/go-data-transfer"
|
|
||||||
"github.com/filecoin-project/go-statestore"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/lib/padreader"
|
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) failDeal(id cid.Cid, cerr error) {
|
|
||||||
if cerr == nil {
|
|
||||||
_, f, l, _ := runtime.Caller(1)
|
|
||||||
cerr = xerrors.Errorf("unknown error (fail called at %s:%d)", f, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
s, ok := c.conns[id]
|
|
||||||
if ok {
|
|
||||||
_ = s.Reset()
|
|
||||||
delete(c.conns, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: store in some sort of audit log
|
|
||||||
log.Errorf("deal %s failed: %+v", id, cerr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) commP(ctx context.Context, data cid.Cid) ([]byte, uint64, error) {
|
|
||||||
root, err := c.dag.Get(ctx, data)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to get file root for deal: %s", err)
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := unixfile.NewUnixfsFile(ctx, c.dag, root)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("cannot open unixfs file: %s", err)
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uf, ok := n.(files.File)
|
|
||||||
if !ok {
|
|
||||||
// TODO: we probably got directory, how should we handle this in unixfs mode?
|
|
||||||
return nil, 0, xerrors.New("unsupported unixfs type")
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := uf.Size()
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pr, psize := padreader.New(uf, uint64(s))
|
|
||||||
|
|
||||||
commp, err := sectorbuilder.GeneratePieceCommitment(pr, psize)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, xerrors.Errorf("generating CommP: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return commp[:], psize, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) readStorageDealResp(deal ClientDeal) (*Response, error) {
|
|
||||||
s, ok := c.conns[deal.ProposalCid]
|
|
||||||
if !ok {
|
|
||||||
// TODO: Try to re-establish the connection using query protocol
|
|
||||||
return nil, xerrors.Errorf("no connection to miner")
|
|
||||||
}
|
|
||||||
|
|
||||||
var resp SignedResponse
|
|
||||||
if err := cborutil.ReadCborRPC(s, &resp); err != nil {
|
|
||||||
log.Errorw("failed to read Response message", "error", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := resp.Verify(deal.MinerWorker); err != nil {
|
|
||||||
return nil, xerrors.Errorf("verifying response signature failed", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Response.Proposal != deal.ProposalCid {
|
|
||||||
return nil, xerrors.Errorf("miner responded to a wrong proposal: %s != %s", resp.Response.Proposal, deal.ProposalCid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &resp.Response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) disconnect(deal ClientDeal) error {
|
|
||||||
s, ok := c.conns[deal.ProposalCid]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := s.Close()
|
|
||||||
delete(c.conns, deal.ProposalCid)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ datatransfer.RequestValidator = &ClientRequestValidator{}
|
|
||||||
|
|
||||||
// ClientRequestValidator validates data transfer requests for the client
|
|
||||||
// in a storage market
|
|
||||||
type ClientRequestValidator struct {
|
|
||||||
deals *statestore.StateStore
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientRequestValidator returns a new client request validator for the
|
|
||||||
// given datastore
|
|
||||||
func NewClientRequestValidator(deals dtypes.ClientDealStore) *ClientRequestValidator {
|
|
||||||
crv := &ClientRequestValidator{
|
|
||||||
deals: deals,
|
|
||||||
}
|
|
||||||
return crv
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidatePush validates a push request received from the peer that will send data
|
|
||||||
// Will always error because clients should not accept push requests from a provider
|
|
||||||
// in a storage deal (i.e. send data to client).
|
|
||||||
func (c *ClientRequestValidator) ValidatePush(
|
|
||||||
sender peer.ID,
|
|
||||||
voucher datatransfer.Voucher,
|
|
||||||
baseCid cid.Cid,
|
|
||||||
Selector ipld.Node) error {
|
|
||||||
return ErrNoPushAccepted
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidatePull validates a pull request received from the peer that will receive data
|
|
||||||
// Will succeed only if:
|
|
||||||
// - voucher has correct type
|
|
||||||
// - voucher references an active deal
|
|
||||||
// - referenced deal matches the receiver (miner)
|
|
||||||
// - referenced deal matches the given base CID
|
|
||||||
// - referenced deal is in an acceptable state
|
|
||||||
func (c *ClientRequestValidator) ValidatePull(
|
|
||||||
receiver peer.ID,
|
|
||||||
voucher datatransfer.Voucher,
|
|
||||||
baseCid cid.Cid,
|
|
||||||
Selector ipld.Node) error {
|
|
||||||
dealVoucher, ok := voucher.(*StorageDataTransferVoucher)
|
|
||||||
if !ok {
|
|
||||||
return xerrors.Errorf("voucher type %s: %w", voucher.Type(), ErrWrongVoucherType)
|
|
||||||
}
|
|
||||||
|
|
||||||
var deal ClientDeal
|
|
||||||
err := c.deals.Get(dealVoucher.Proposal, &deal)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("Proposal CID %s: %w", dealVoucher.Proposal.String(), ErrNoDeal)
|
|
||||||
}
|
|
||||||
if deal.Miner != receiver {
|
|
||||||
return xerrors.Errorf("Deal Peer %s, Data Transfer Peer %s: %w", deal.Miner.String(), receiver.String(), ErrWrongPeer)
|
|
||||||
}
|
|
||||||
if !deal.PayloadCid.Equals(baseCid) {
|
|
||||||
return xerrors.Errorf("Deal Payload CID %s, Data Transfer CID %s: %w", string(deal.Proposal.PieceRef), baseCid.String(), ErrWrongPiece)
|
|
||||||
}
|
|
||||||
for _, state := range DataTransferStates {
|
|
||||||
if deal.State == state {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return xerrors.Errorf("Deal State %s: %w", deal.State, ErrInacceptableDealState)
|
|
||||||
}
|
|
@ -1,293 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
"github.com/ipfs/go-datastore"
|
|
||||||
"github.com/ipfs/go-datastore/namespace"
|
|
||||||
"github.com/libp2p/go-libp2p-core/host"
|
|
||||||
inet "github.com/libp2p/go-libp2p-core/network"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-cbor-util"
|
|
||||||
"github.com/filecoin-project/go-data-transfer"
|
|
||||||
"github.com/filecoin-project/go-statestore"
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ProviderDsPrefix = "/deals/provider"
|
|
||||||
|
|
||||||
type MinerDeal struct {
|
|
||||||
Client peer.ID
|
|
||||||
Proposal actors.StorageDealProposal
|
|
||||||
ProposalCid cid.Cid
|
|
||||||
State api.DealState
|
|
||||||
|
|
||||||
Ref cid.Cid
|
|
||||||
|
|
||||||
DealID uint64
|
|
||||||
SectorID uint64 // Set when State >= DealStaged
|
|
||||||
|
|
||||||
s inet.Stream
|
|
||||||
}
|
|
||||||
|
|
||||||
type Provider struct {
|
|
||||||
pricePerByteBlock types.BigInt // how much we want for storing one byte for one block
|
|
||||||
minPieceSize uint64
|
|
||||||
|
|
||||||
ask *types.SignedStorageAsk
|
|
||||||
askLk sync.Mutex
|
|
||||||
|
|
||||||
spn storagemarket.StorageProviderNode
|
|
||||||
|
|
||||||
// TODO: This will go away once storage market module + CAR
|
|
||||||
// is implemented
|
|
||||||
dag dtypes.StagingDAG
|
|
||||||
|
|
||||||
// dataTransfer is the manager of data transfers used by this storage provider
|
|
||||||
dataTransfer dtypes.ProviderDataTransfer
|
|
||||||
|
|
||||||
deals *statestore.StateStore
|
|
||||||
ds dtypes.MetadataDS
|
|
||||||
|
|
||||||
conns map[cid.Cid]inet.Stream
|
|
||||||
|
|
||||||
actor address.Address
|
|
||||||
|
|
||||||
incoming chan MinerDeal
|
|
||||||
updated chan minerDealUpdate
|
|
||||||
stop chan struct{}
|
|
||||||
stopped chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type minerDealUpdate struct {
|
|
||||||
newState api.DealState
|
|
||||||
id cid.Cid
|
|
||||||
err error
|
|
||||||
mut func(*MinerDeal)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrDataTransferFailed means a data transfer for a deal failed
|
|
||||||
ErrDataTransferFailed = errors.New("deal data transfer failed")
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewProvider(ds dtypes.MetadataDS, dag dtypes.StagingDAG, dataTransfer dtypes.ProviderDataTransfer, spn storagemarket.StorageProviderNode) (storagemarket.StorageProvider, error) {
|
|
||||||
addr, err := ds.Get(datastore.NewKey("miner-address"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
minerAddress, err := address.NewFromBytes(addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
h := &Provider{
|
|
||||||
dag: dag,
|
|
||||||
dataTransfer: dataTransfer,
|
|
||||||
spn: spn,
|
|
||||||
|
|
||||||
pricePerByteBlock: types.NewInt(3), // TODO: allow setting
|
|
||||||
minPieceSize: 256, // TODO: allow setting (BUT KEEP MIN 256! (because of how we fill sectors up))
|
|
||||||
|
|
||||||
conns: map[cid.Cid]inet.Stream{},
|
|
||||||
|
|
||||||
incoming: make(chan MinerDeal),
|
|
||||||
updated: make(chan minerDealUpdate),
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
stopped: make(chan struct{}),
|
|
||||||
|
|
||||||
actor: minerAddress,
|
|
||||||
|
|
||||||
deals: statestore.New(namespace.Wrap(ds, datastore.NewKey(ProviderDsPrefix))),
|
|
||||||
ds: ds,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := h.tryLoadAsk(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if h.ask == nil {
|
|
||||||
// TODO: we should be fine with this state, and just say it means 'not actively accepting deals'
|
|
||||||
// for now... lets just set a price
|
|
||||||
if err := h.SetPrice(types.NewInt(500_000_000), 1000000); err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed setting a default price: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// register a data transfer event handler -- this will move deals from
|
|
||||||
// accepted to staged
|
|
||||||
h.dataTransfer.SubscribeToEvents(h.onDataTransferEvent)
|
|
||||||
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) Run(ctx context.Context, host host.Host) {
|
|
||||||
// TODO: restore state
|
|
||||||
|
|
||||||
host.SetStreamHandler(storagemarket.DealProtocolID, p.HandleStream)
|
|
||||||
host.SetStreamHandler(storagemarket.AskProtocolID, p.HandleAskStream)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer log.Warn("quitting deal provider loop")
|
|
||||||
defer close(p.stopped)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case deal := <-p.incoming: // DealAccepted
|
|
||||||
p.onIncoming(deal)
|
|
||||||
case update := <-p.updated: // DealStaged
|
|
||||||
p.onUpdated(ctx, update)
|
|
||||||
case <-p.stop:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) onIncoming(deal MinerDeal) {
|
|
||||||
log.Info("incoming deal")
|
|
||||||
|
|
||||||
p.conns[deal.ProposalCid] = deal.s
|
|
||||||
|
|
||||||
if err := p.deals.Begin(deal.ProposalCid, &deal); err != nil {
|
|
||||||
// This can happen when client re-sends proposal
|
|
||||||
p.failDeal(context.TODO(), deal.ProposalCid, err)
|
|
||||||
log.Errorf("deal tracking failed: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
p.updated <- minerDealUpdate{
|
|
||||||
newState: api.DealAccepted,
|
|
||||||
id: deal.ProposalCid,
|
|
||||||
err: nil,
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) onUpdated(ctx context.Context, update minerDealUpdate) {
|
|
||||||
log.Infof("Deal %s updated state to %s", update.id, api.DealStates[update.newState])
|
|
||||||
if update.err != nil {
|
|
||||||
log.Errorf("deal %s (newSt: %d) failed: %+v", update.id, update.newState, update.err)
|
|
||||||
p.failDeal(ctx, update.id, update.err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var deal MinerDeal
|
|
||||||
err := p.deals.Mutate(update.id, func(d *MinerDeal) error {
|
|
||||||
d.State = update.newState
|
|
||||||
if update.mut != nil {
|
|
||||||
update.mut(d)
|
|
||||||
}
|
|
||||||
deal = *d
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
p.failDeal(ctx, update.id, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch update.newState {
|
|
||||||
case api.DealAccepted:
|
|
||||||
p.handle(ctx, deal, p.accept, api.DealNoUpdate)
|
|
||||||
case api.DealStaged:
|
|
||||||
p.handle(ctx, deal, p.staged, api.DealSealing)
|
|
||||||
case api.DealSealing:
|
|
||||||
p.handle(ctx, deal, p.sealing, api.DealComplete)
|
|
||||||
case api.DealComplete:
|
|
||||||
p.handle(ctx, deal, p.complete, api.DealNoUpdate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// onDataTransferEvent is the function called when an event occurs in a data
|
|
||||||
// transfer -- it reads the voucher to verify this even occurred in a storage
|
|
||||||
// market deal, then, based on the data transfer event that occurred, it generates
|
|
||||||
// and update message for the deal -- either moving to staged for a completion
|
|
||||||
// event or moving to error if a data transfer error occurs
|
|
||||||
func (p *Provider) onDataTransferEvent(event datatransfer.Event, channelState datatransfer.ChannelState) {
|
|
||||||
voucher, ok := channelState.Voucher().(*StorageDataTransferVoucher)
|
|
||||||
// if this event is for a transfer not related to storage, ignore
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// data transfer events for opening and progress do not affect deal state
|
|
||||||
var next api.DealState
|
|
||||||
var err error
|
|
||||||
var mut func(*MinerDeal)
|
|
||||||
switch event.Code {
|
|
||||||
case datatransfer.Complete:
|
|
||||||
next = api.DealStaged
|
|
||||||
mut = func(deal *MinerDeal) {
|
|
||||||
deal.DealID = voucher.DealID
|
|
||||||
}
|
|
||||||
case datatransfer.Error:
|
|
||||||
next = api.DealFailed
|
|
||||||
err = ErrDataTransferFailed
|
|
||||||
default:
|
|
||||||
// the only events we care about are complete and error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case p.updated <- minerDealUpdate{
|
|
||||||
newState: next,
|
|
||||||
id: voucher.Proposal,
|
|
||||||
err: err,
|
|
||||||
mut: mut,
|
|
||||||
}:
|
|
||||||
case <-p.stop:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) newDeal(s inet.Stream, proposal Proposal) (MinerDeal, error) {
|
|
||||||
proposalNd, err := cborutil.AsIpld(proposal.DealProposal)
|
|
||||||
if err != nil {
|
|
||||||
return MinerDeal{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return MinerDeal{
|
|
||||||
Client: s.Conn().RemotePeer(),
|
|
||||||
Proposal: *proposal.DealProposal,
|
|
||||||
ProposalCid: proposalNd.Cid(),
|
|
||||||
State: api.DealUnknown,
|
|
||||||
|
|
||||||
Ref: proposal.Piece,
|
|
||||||
|
|
||||||
s: s,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) HandleStream(s inet.Stream) {
|
|
||||||
log.Info("Handling storage deal proposal!")
|
|
||||||
|
|
||||||
proposal, err := p.readProposal(s)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
s.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
deal, err := p.newDeal(s, proposal)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("%+v", err)
|
|
||||||
s.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p.incoming <- deal
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) Stop() {
|
|
||||||
close(p.stop)
|
|
||||||
<-p.stopped
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-datastore"
|
|
||||||
inet "github.com/libp2p/go-libp2p-core/network"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-cbor-util"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (p *Provider) SetPrice(price types.BigInt, ttlsecs int64) error {
|
|
||||||
p.askLk.Lock()
|
|
||||||
defer p.askLk.Unlock()
|
|
||||||
|
|
||||||
var seqno uint64
|
|
||||||
if p.ask != nil {
|
|
||||||
seqno = p.ask.Ask.SeqNo + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
now := time.Now().Unix()
|
|
||||||
ask := &types.StorageAsk{
|
|
||||||
Price: price,
|
|
||||||
Timestamp: uint64(now),
|
|
||||||
Expiry: uint64(now + ttlsecs),
|
|
||||||
Miner: p.actor,
|
|
||||||
SeqNo: seqno,
|
|
||||||
MinPieceSize: p.minPieceSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
ssa, err := p.signAsk(ask)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.saveAsk(ssa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) GetAsk(m address.Address) *types.SignedStorageAsk {
|
|
||||||
p.askLk.Lock()
|
|
||||||
defer p.askLk.Unlock()
|
|
||||||
if m != p.actor {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.ask
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) HandleAskStream(s inet.Stream) {
|
|
||||||
defer s.Close()
|
|
||||||
var ar AskRequest
|
|
||||||
if err := cborutil.ReadCborRPC(s, &ar); err != nil {
|
|
||||||
log.Errorf("failed to read AskRequest from incoming stream: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp := p.processAskRequest(&ar)
|
|
||||||
|
|
||||||
if err := cborutil.WriteCborRPC(s, resp); err != nil {
|
|
||||||
log.Errorf("failed to write ask response: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) processAskRequest(ar *AskRequest) *AskResponse {
|
|
||||||
return &AskResponse{
|
|
||||||
Ask: p.GetAsk(ar.Miner),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var bestAskKey = datastore.NewKey("latest-ask")
|
|
||||||
|
|
||||||
func (p *Provider) tryLoadAsk() error {
|
|
||||||
p.askLk.Lock()
|
|
||||||
defer p.askLk.Unlock()
|
|
||||||
|
|
||||||
err := p.loadAsk()
|
|
||||||
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"))
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to load most recent ask from disk: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ssa types.SignedStorageAsk
|
|
||||||
if err := cborutil.ReadCborRPC(bytes.NewReader(askb), &ssa); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.ask = &ssa
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) signAsk(a *types.StorageAsk) (*types.SignedStorageAsk, error) {
|
|
||||||
b, err := cborutil.Dump(a)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
worker, err := p.spn.GetMinerWorker(context.TODO(), p.actor)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to get worker to sign ask: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := p.spn.SignBytes(context.TODO(), worker, b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &types.SignedStorageAsk{
|
|
||||||
Ask: a,
|
|
||||||
Signature: sig,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) saveAsk(a *types.SignedStorageAsk) error {
|
|
||||||
b, err := cborutil.Dump(a)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.ds.Put(bestAskKey, b); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.ask = a
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,172 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
ipldfree "github.com/ipld/go-ipld-prime/impl/free"
|
|
||||||
"github.com/ipld/go-ipld-prime/traversal/selector"
|
|
||||||
"github.com/ipld/go-ipld-prime/traversal/selector/builder"
|
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
|
||||||
|
|
||||||
type providerHandlerFunc func(ctx context.Context, deal MinerDeal) (func(*MinerDeal), error)
|
|
||||||
|
|
||||||
func (p *Provider) handle(ctx context.Context, deal MinerDeal, cb providerHandlerFunc, next api.DealState) {
|
|
||||||
go func() {
|
|
||||||
mut, err := cb(ctx, deal)
|
|
||||||
|
|
||||||
if err == nil && next == api.DealNoUpdate {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case p.updated <- minerDealUpdate{
|
|
||||||
newState: next,
|
|
||||||
id: deal.ProposalCid,
|
|
||||||
err: err,
|
|
||||||
mut: mut,
|
|
||||||
}:
|
|
||||||
case <-p.stop:
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ACCEPTED
|
|
||||||
func (p *Provider) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal), error) {
|
|
||||||
|
|
||||||
head, err := p.spn.MostRecentStateId(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if head.Height() >= deal.Proposal.ProposalExpiration {
|
|
||||||
return nil, xerrors.Errorf("deal proposal already expired")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check StorageCollateral
|
|
||||||
|
|
||||||
minPrice := types.BigDiv(types.BigMul(p.ask.Ask.Price, types.NewInt(deal.Proposal.PieceSize)), types.NewInt(1<<30))
|
|
||||||
if deal.Proposal.StoragePricePerEpoch.LessThan(minPrice) {
|
|
||||||
return nil, xerrors.Errorf("storage price per epoch less than asking price: %s < %s", deal.Proposal.StoragePricePerEpoch, minPrice)
|
|
||||||
}
|
|
||||||
|
|
||||||
if deal.Proposal.PieceSize < p.ask.Ask.MinPieceSize {
|
|
||||||
return nil, xerrors.Errorf("piece size less than minimum required size: %d < %d", deal.Proposal.PieceSize, p.ask.Ask.MinPieceSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check market funds
|
|
||||||
clientMarketBalance, err := p.spn.GetBalance(ctx, deal.Proposal.Client)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("getting client market balance failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This doesn't guarantee that the client won't withdraw / lock those funds
|
|
||||||
// but it's a decent first filter
|
|
||||||
if clientMarketBalance.Available.LessThan(deal.Proposal.TotalStoragePrice()) {
|
|
||||||
return nil, xerrors.New("clientMarketBalance.Available too small")
|
|
||||||
}
|
|
||||||
|
|
||||||
waddr, err := p.spn.GetMinerWorker(ctx, deal.Proposal.Provider)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check StorageCollateral (may be too large (or too small))
|
|
||||||
if err := p.spn.EnsureFunds(ctx, waddr, storagemarket.TokenAmount(deal.Proposal.StorageCollateral)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
smDeal := storagemarket.MinerDeal{
|
|
||||||
Client: deal.Client,
|
|
||||||
Proposal: deal.Proposal,
|
|
||||||
ProposalCid: deal.ProposalCid,
|
|
||||||
State: deal.State,
|
|
||||||
Ref: deal.Ref,
|
|
||||||
SectorID: deal.SectorID,
|
|
||||||
}
|
|
||||||
|
|
||||||
dealId, mcid, err := p.spn.PublishDeals(ctx, smDeal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("fetching data for a deal %d", dealId)
|
|
||||||
err = p.sendSignedResponse(ctx, &Response{
|
|
||||||
State: api.DealAccepted,
|
|
||||||
|
|
||||||
Proposal: deal.ProposalCid,
|
|
||||||
PublishMessage: &mcid,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.disconnect(deal); err != nil {
|
|
||||||
log.Warnf("closing client connection: %+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ssb := builder.NewSelectorSpecBuilder(ipldfree.NodeBuilder())
|
|
||||||
|
|
||||||
// this is the selector for "get the whole DAG"
|
|
||||||
// TODO: support storage deals with custom payload selectors
|
|
||||||
allSelector := ssb.ExploreRecursive(selector.RecursionLimitNone(),
|
|
||||||
ssb.ExploreAll(ssb.ExploreRecursiveEdge())).Node()
|
|
||||||
|
|
||||||
// initiate a pull data transfer. This will complete asynchronously and the
|
|
||||||
// completion of the data transfer will trigger a change in deal state
|
|
||||||
// (see onDataTransferEvent)
|
|
||||||
_, err = p.dataTransfer.OpenPullDataChannel(ctx,
|
|
||||||
deal.Client,
|
|
||||||
&StorageDataTransferVoucher{Proposal: deal.ProposalCid, DealID: uint64(dealId)},
|
|
||||||
deal.Ref,
|
|
||||||
allSelector,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, xerrors.Errorf("failed to open pull data channel: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// STAGED
|
|
||||||
|
|
||||||
func (p *Provider) staged(ctx context.Context, deal MinerDeal) (func(*MinerDeal), error) {
|
|
||||||
sectorID, err := p.spn.OnDealComplete(
|
|
||||||
ctx,
|
|
||||||
storagemarket.MinerDeal{
|
|
||||||
Client: deal.Client,
|
|
||||||
Proposal: deal.Proposal,
|
|
||||||
ProposalCid: deal.ProposalCid,
|
|
||||||
State: deal.State,
|
|
||||||
Ref: deal.Ref,
|
|
||||||
DealID: deal.DealID,
|
|
||||||
},
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(deal *MinerDeal) {
|
|
||||||
deal.SectorID = sectorID
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SEALING
|
|
||||||
|
|
||||||
func (p *Provider) sealing(ctx context.Context, deal MinerDeal) (func(*MinerDeal), error) {
|
|
||||||
// TODO: consider waiting for seal to happen
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) complete(ctx context.Context, deal MinerDeal) (func(*MinerDeal), error) {
|
|
||||||
// TODO: observe sector lifecycle, status, expiration..
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
// this file implements storagemarket.StorageClient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (p *Provider) AddAsk(price storagemarket.TokenAmount, ttlsecs int64) error {
|
|
||||||
return p.SetPrice(types.BigInt(price), ttlsecs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) ListAsks(addr address.Address) []*types.SignedStorageAsk {
|
|
||||||
ask := p.GetAsk(addr)
|
|
||||||
|
|
||||||
if ask != nil {
|
|
||||||
return []*types.SignedStorageAsk{ask}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) ListDeals(ctx context.Context) ([]actors.OnChainDeal, error) {
|
|
||||||
return p.spn.ListProviderDeals(ctx, p.actor)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) AddStorageCollateral(ctx context.Context, amount storagemarket.TokenAmount) error {
|
|
||||||
return p.spn.AddFunds(ctx, p.actor, amount)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) GetStorageCollateral(ctx context.Context) (storagemarket.Balance, error) {
|
|
||||||
balance, err := p.spn.GetBalance(ctx, p.actor)
|
|
||||||
|
|
||||||
return balance, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) ListIncompleteDeals() ([]storagemarket.MinerDeal, error) {
|
|
||||||
var out []storagemarket.MinerDeal
|
|
||||||
|
|
||||||
var deals []MinerDeal
|
|
||||||
if err := p.deals.List(&deals); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, deal := range deals {
|
|
||||||
out = append(out, storagemarket.MinerDeal{
|
|
||||||
Client: deal.Client,
|
|
||||||
Proposal: deal.Proposal,
|
|
||||||
ProposalCid: deal.ProposalCid,
|
|
||||||
State: deal.State,
|
|
||||||
Ref: deal.Ref,
|
|
||||||
DealID: deal.DealID,
|
|
||||||
SectorID: deal.SectorID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ storagemarket.StorageProvider = &Provider{}
|
|
@ -1,180 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-cbor-util"
|
|
||||||
"github.com/filecoin-project/go-data-transfer"
|
|
||||||
"github.com/filecoin-project/go-statestore"
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
"github.com/ipld/go-ipld-prime"
|
|
||||||
inet "github.com/libp2p/go-libp2p-core/network"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (p *Provider) failDeal(ctx context.Context, id cid.Cid, cerr error) {
|
|
||||||
if err := p.deals.End(id); err != nil {
|
|
||||||
log.Warnf("deals.End: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if cerr == nil {
|
|
||||||
_, f, l, _ := runtime.Caller(1)
|
|
||||||
cerr = xerrors.Errorf("unknown error (fail called at %s:%d)", f, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Warnf("deal %s failed: %s", id, cerr)
|
|
||||||
|
|
||||||
err := p.sendSignedResponse(ctx, &Response{
|
|
||||||
State: api.DealFailed,
|
|
||||||
Message: cerr.Error(),
|
|
||||||
Proposal: id,
|
|
||||||
})
|
|
||||||
|
|
||||||
s, ok := p.conns[id]
|
|
||||||
if ok {
|
|
||||||
_ = s.Reset()
|
|
||||||
delete(p.conns, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("notifying client about deal failure: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) readProposal(s inet.Stream) (proposal Proposal, err error) {
|
|
||||||
if err := cborutil.ReadCborRPC(s, &proposal); err != nil {
|
|
||||||
log.Errorw("failed to read proposal message", "error", err)
|
|
||||||
return proposal, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if proposal.DealProposal.ProposerSignature == nil {
|
|
||||||
return proposal, xerrors.Errorf("incoming deal proposal has no signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := proposal.DealProposal.Verify(address.Undef); err != nil {
|
|
||||||
return proposal, xerrors.Errorf("verifying StorageDealProposal: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if proposal.DealProposal.Provider != p.actor {
|
|
||||||
log.Errorf("proposal with wrong ProviderAddress: %s", proposal.DealProposal.Provider)
|
|
||||||
return proposal, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) sendSignedResponse(ctx context.Context, resp *Response) error {
|
|
||||||
s, ok := p.conns[resp.Proposal]
|
|
||||||
if !ok {
|
|
||||||
return xerrors.New("couldn't send response: not connected")
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := cborutil.Dump(resp)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("serializing response: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
worker, err := p.spn.GetMinerWorker(ctx, p.actor)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := p.spn.SignBytes(ctx, worker, msg)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to sign response message: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
signedResponse := &SignedResponse{
|
|
||||||
Response: *resp,
|
|
||||||
Signature: sig,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cborutil.WriteCborRPC(s, signedResponse)
|
|
||||||
if err != nil {
|
|
||||||
// Assume client disconnected
|
|
||||||
s.Close()
|
|
||||||
delete(p.conns, resp.Proposal)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) disconnect(deal MinerDeal) error {
|
|
||||||
s, ok := p.conns[deal.ProposalCid]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := s.Close()
|
|
||||||
delete(p.conns, deal.ProposalCid)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ datatransfer.RequestValidator = &ProviderRequestValidator{}
|
|
||||||
|
|
||||||
// ProviderRequestValidator validates data transfer requests for the provider
|
|
||||||
// in a storage market
|
|
||||||
type ProviderRequestValidator struct {
|
|
||||||
deals *statestore.StateStore
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewProviderRequestValidator returns a new client request validator for the
|
|
||||||
// given datastore
|
|
||||||
func NewProviderRequestValidator(deals dtypes.ProviderDealStore) *ProviderRequestValidator {
|
|
||||||
return &ProviderRequestValidator{
|
|
||||||
deals: deals,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidatePush validates a push request received from the peer that will send data
|
|
||||||
// Will succeed only if:
|
|
||||||
// - voucher has correct type
|
|
||||||
// - voucher references an active deal
|
|
||||||
// - referenced deal matches the client
|
|
||||||
// - referenced deal matches the given base CID
|
|
||||||
// - referenced deal is in an acceptable state
|
|
||||||
func (m *ProviderRequestValidator) ValidatePush(
|
|
||||||
sender peer.ID,
|
|
||||||
voucher datatransfer.Voucher,
|
|
||||||
baseCid cid.Cid,
|
|
||||||
Selector ipld.Node) error {
|
|
||||||
dealVoucher, ok := voucher.(*StorageDataTransferVoucher)
|
|
||||||
if !ok {
|
|
||||||
return xerrors.Errorf("voucher type %s: %w", voucher.Type(), ErrWrongVoucherType)
|
|
||||||
}
|
|
||||||
|
|
||||||
var deal MinerDeal
|
|
||||||
err := m.deals.Get(dealVoucher.Proposal, &deal)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("Proposal CID %s: %w", dealVoucher.Proposal.String(), ErrNoDeal)
|
|
||||||
}
|
|
||||||
if deal.Client != sender {
|
|
||||||
return xerrors.Errorf("Deal Peer %s, Data Transfer Peer %s: %w", deal.Client.String(), sender.String(), ErrWrongPeer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !deal.Ref.Equals(baseCid) {
|
|
||||||
return xerrors.Errorf("Deal Payload CID %s, Data Transfer CID %s: %w", string(deal.Proposal.PieceRef), baseCid.String(), ErrWrongPiece)
|
|
||||||
}
|
|
||||||
for _, state := range DataTransferStates {
|
|
||||||
if deal.State == state {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return xerrors.Errorf("Deal State %s: %w", deal.State, ErrInacceptableDealState)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidatePull validates a pull request received from the peer that will receive data.
|
|
||||||
// Will always error because providers should not accept pull requests from a client
|
|
||||||
// in a storage deal (i.e. send data to client).
|
|
||||||
func (m *ProviderRequestValidator) ValidatePull(
|
|
||||||
receiver peer.ID,
|
|
||||||
voucher datatransfer.Voucher,
|
|
||||||
baseCid cid.Cid,
|
|
||||||
Selector ipld.Node) error {
|
|
||||||
return ErrNoPullAccepted
|
|
||||||
}
|
|
@ -1,274 +0,0 @@
|
|||||||
package deals_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
"github.com/ipfs/go-datastore"
|
|
||||||
"github.com/ipfs/go-datastore/namespace"
|
|
||||||
dss "github.com/ipfs/go-datastore/sync"
|
|
||||||
blocksutil "github.com/ipfs/go-ipfs-blocksutil"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
xerrors "golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-cbor-util"
|
|
||||||
"github.com/filecoin-project/go-statestore"
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/deals"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
|
||||||
|
|
||||||
var blockGenerator = blocksutil.NewBlockGenerator()
|
|
||||||
|
|
||||||
type wrongDTType struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wrongDTType) ToBytes() ([]byte, error) {
|
|
||||||
return []byte{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wrongDTType) FromBytes([]byte) error {
|
|
||||||
return fmt.Errorf("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wrongDTType) Type() string {
|
|
||||||
return "WrongDTTYPE"
|
|
||||||
}
|
|
||||||
|
|
||||||
func uniqueStorageDealProposal() (actors.StorageDealProposal, error) {
|
|
||||||
clientAddr, err := address.NewIDAddress(uint64(rand.Int()))
|
|
||||||
if err != nil {
|
|
||||||
return actors.StorageDealProposal{}, err
|
|
||||||
}
|
|
||||||
providerAddr, err := address.NewIDAddress(uint64(rand.Int()))
|
|
||||||
if err != nil {
|
|
||||||
return actors.StorageDealProposal{}, err
|
|
||||||
}
|
|
||||||
return actors.StorageDealProposal{
|
|
||||||
PieceRef: blockGenerator.Next().Cid().Bytes(),
|
|
||||||
Client: clientAddr,
|
|
||||||
Provider: providerAddr,
|
|
||||||
ProposerSignature: &types.Signature{
|
|
||||||
Data: []byte("foo bar cat dog"),
|
|
||||||
Type: types.KTBLS,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newClientDeal(minerID peer.ID, state api.DealState) (deals.ClientDeal, error) {
|
|
||||||
newProposal, err := uniqueStorageDealProposal()
|
|
||||||
if err != nil {
|
|
||||||
return deals.ClientDeal{}, err
|
|
||||||
}
|
|
||||||
proposalNd, err := cborutil.AsIpld(&newProposal)
|
|
||||||
if err != nil {
|
|
||||||
return deals.ClientDeal{}, err
|
|
||||||
}
|
|
||||||
minerAddr, err := address.NewIDAddress(uint64(rand.Int()))
|
|
||||||
if err != nil {
|
|
||||||
return deals.ClientDeal{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return deals.ClientDeal{
|
|
||||||
ClientDeal: storagemarket.ClientDeal{
|
|
||||||
Proposal: newProposal,
|
|
||||||
ProposalCid: proposalNd.Cid(),
|
|
||||||
PayloadCid: blockGenerator.Next().Cid(),
|
|
||||||
Miner: minerID,
|
|
||||||
MinerWorker: minerAddr,
|
|
||||||
State: state,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMinerDeal(clientID peer.ID, state api.DealState) (deals.MinerDeal, error) {
|
|
||||||
newProposal, err := uniqueStorageDealProposal()
|
|
||||||
if err != nil {
|
|
||||||
return deals.MinerDeal{}, err
|
|
||||||
}
|
|
||||||
proposalNd, err := cborutil.AsIpld(&newProposal)
|
|
||||||
if err != nil {
|
|
||||||
return deals.MinerDeal{}, err
|
|
||||||
}
|
|
||||||
ref := blockGenerator.Next().Cid()
|
|
||||||
|
|
||||||
return deals.MinerDeal{
|
|
||||||
Proposal: newProposal,
|
|
||||||
ProposalCid: proposalNd.Cid(),
|
|
||||||
Client: clientID,
|
|
||||||
State: state,
|
|
||||||
Ref: ref,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClientRequestValidation(t *testing.T) {
|
|
||||||
ds := dss.MutexWrap(datastore.NewMapDatastore())
|
|
||||||
state := statestore.New(namespace.Wrap(ds, datastore.NewKey("/deals/client")))
|
|
||||||
|
|
||||||
crv := deals.NewClientRequestValidator(state)
|
|
||||||
minerID := peer.ID("fakepeerid")
|
|
||||||
block := blockGenerator.Next()
|
|
||||||
t.Run("ValidatePush fails", func(t *testing.T) {
|
|
||||||
if !xerrors.Is(crv.ValidatePush(minerID, wrongDTType{}, block.Cid(), nil), deals.ErrNoPushAccepted) {
|
|
||||||
t.Fatal("Push should fail for the client request validator for storage deals")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePull fails deal not found", func(t *testing.T) {
|
|
||||||
proposal, err := uniqueStorageDealProposal()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating proposal")
|
|
||||||
}
|
|
||||||
proposalNd, err := cborutil.AsIpld(&proposal)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error serializing proposal")
|
|
||||||
}
|
|
||||||
pieceRef, err := cid.Cast(proposal.PieceRef)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("unable to construct piece cid")
|
|
||||||
}
|
|
||||||
if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{proposalNd.Cid(), 1}, pieceRef, nil), deals.ErrNoDeal) {
|
|
||||||
t.Fatal("Pull should fail if there is no deal stored")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePull fails wrong client", func(t *testing.T) {
|
|
||||||
otherMiner := peer.ID("otherminer")
|
|
||||||
clientDeal, err := newClientDeal(otherMiner, api.DealAccepted)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(clientDeal.ProposalCid, &clientDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
payloadCid := clientDeal.PayloadCid
|
|
||||||
if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, payloadCid, nil), deals.ErrWrongPeer) {
|
|
||||||
t.Fatal("Pull should fail if miner address is incorrect")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePull fails wrong piece ref", func(t *testing.T) {
|
|
||||||
clientDeal, err := newClientDeal(minerID, api.DealAccepted)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(clientDeal.ProposalCid, &clientDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, blockGenerator.Next().Cid(), nil), deals.ErrWrongPiece) {
|
|
||||||
t.Fatal("Pull should fail if piece ref is incorrect")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePull fails wrong deal state", func(t *testing.T) {
|
|
||||||
clientDeal, err := newClientDeal(minerID, api.DealComplete)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(clientDeal.ProposalCid, &clientDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
payloadCid := clientDeal.PayloadCid
|
|
||||||
if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, payloadCid, nil), deals.ErrInacceptableDealState) {
|
|
||||||
t.Fatal("Pull should fail if deal is in a state that cannot be data transferred")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePull succeeds", func(t *testing.T) {
|
|
||||||
clientDeal, err := newClientDeal(minerID, api.DealAccepted)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(clientDeal.ProposalCid, &clientDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
payloadCid := clientDeal.PayloadCid
|
|
||||||
if crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, payloadCid, nil) != nil {
|
|
||||||
t.Fatal("Pull should should succeed when all parameters are correct")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProviderRequestValidation(t *testing.T) {
|
|
||||||
ds := dss.MutexWrap(datastore.NewMapDatastore())
|
|
||||||
state := statestore.New(namespace.Wrap(ds, datastore.NewKey("/deals/client")))
|
|
||||||
|
|
||||||
mrv := deals.NewProviderRequestValidator(state)
|
|
||||||
clientID := peer.ID("fakepeerid")
|
|
||||||
block := blockGenerator.Next()
|
|
||||||
t.Run("ValidatePull fails", func(t *testing.T) {
|
|
||||||
if !xerrors.Is(mrv.ValidatePull(clientID, wrongDTType{}, block.Cid(), nil), deals.ErrNoPullAccepted) {
|
|
||||||
t.Fatal("Pull should fail for the provider request validator for storage deals")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("ValidatePush fails deal not found", func(t *testing.T) {
|
|
||||||
proposal, err := uniqueStorageDealProposal()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating proposal")
|
|
||||||
}
|
|
||||||
proposalNd, err := cborutil.AsIpld(&proposal)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error serializing proposal")
|
|
||||||
}
|
|
||||||
pieceRef, err := cid.Cast(proposal.PieceRef)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("unable to construct piece cid")
|
|
||||||
}
|
|
||||||
if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{proposalNd.Cid(), 1}, pieceRef, nil), deals.ErrNoDeal) {
|
|
||||||
t.Fatal("Push should fail if there is no deal stored")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePush fails wrong miner", func(t *testing.T) {
|
|
||||||
otherClient := peer.ID("otherclient")
|
|
||||||
minerDeal, err := newMinerDeal(otherClient, api.DealAccepted)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(minerDeal.ProposalCid, &minerDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
ref := minerDeal.Ref
|
|
||||||
if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, ref, nil), deals.ErrWrongPeer) {
|
|
||||||
t.Fatal("Push should fail if miner address is incorrect")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePush fails wrong piece ref", func(t *testing.T) {
|
|
||||||
minerDeal, err := newMinerDeal(clientID, api.DealAccepted)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(minerDeal.ProposalCid, &minerDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, blockGenerator.Next().Cid(), nil), deals.ErrWrongPiece) {
|
|
||||||
t.Fatal("Push should fail if piece ref is incorrect")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePush fails wrong deal state", func(t *testing.T) {
|
|
||||||
minerDeal, err := newMinerDeal(clientID, api.DealComplete)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(minerDeal.ProposalCid, &minerDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
ref := minerDeal.Ref
|
|
||||||
if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, ref, nil), deals.ErrInacceptableDealState) {
|
|
||||||
t.Fatal("Push should fail if deal is in a state that cannot be data transferred")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("ValidatePush succeeds", func(t *testing.T) {
|
|
||||||
minerDeal, err := newMinerDeal(clientID, api.DealAccepted)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error creating client deal")
|
|
||||||
}
|
|
||||||
if err := state.Begin(minerDeal.ProposalCid, &minerDeal); err != nil {
|
|
||||||
t.Fatal("deal tracking failed")
|
|
||||||
}
|
|
||||||
ref := minerDeal.Ref
|
|
||||||
if mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, ref, nil) != nil {
|
|
||||||
t.Fatal("Push should should succeed when all parameters are correct")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
package deals
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-cbor-util"
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrWrongVoucherType means the voucher was not the correct type can validate against
|
|
||||||
ErrWrongVoucherType = errors.New("cannot validate voucher type.")
|
|
||||||
|
|
||||||
// ErrNoPushAccepted just means clients do not accept pushes for storage deals
|
|
||||||
ErrNoPushAccepted = errors.New("client should not receive data for a storage deal.")
|
|
||||||
|
|
||||||
// ErrNoPullAccepted just means providers do not accept pulls for storage deals
|
|
||||||
ErrNoPullAccepted = errors.New("provider should not send data for a storage deal.")
|
|
||||||
|
|
||||||
// ErrNoDeal means no active deal was found for this vouchers proposal cid
|
|
||||||
ErrNoDeal = errors.New("no deal found for this proposal.")
|
|
||||||
|
|
||||||
// ErrWrongPeer means that the other peer for this data transfer request does not match
|
|
||||||
// the other peer for the deal
|
|
||||||
ErrWrongPeer = errors.New("data Transfer peer id and Deal peer id do not match.")
|
|
||||||
|
|
||||||
// ErrWrongPiece means that the pieceref for this data transfer request does not match
|
|
||||||
// the one specified in the deal
|
|
||||||
ErrWrongPiece = errors.New("base CID for deal does not match CID for piece.")
|
|
||||||
|
|
||||||
// ErrInacceptableDealState means the deal for this transfer is not in a deal state
|
|
||||||
// where transfer can be performed
|
|
||||||
ErrInacceptableDealState = errors.New("deal is not a in a state where deals are accepted.")
|
|
||||||
|
|
||||||
// DataTransferStates are the states in which it would make sense to actually start a data transfer
|
|
||||||
DataTransferStates = []api.DealState{api.DealAccepted, api.DealUnknown}
|
|
||||||
)
|
|
||||||
|
|
||||||
type Proposal struct {
|
|
||||||
DealProposal *actors.StorageDealProposal
|
|
||||||
|
|
||||||
Piece cid.Cid // Used for retrieving from the client
|
|
||||||
}
|
|
||||||
|
|
||||||
type Response struct {
|
|
||||||
State api.DealState
|
|
||||||
|
|
||||||
// DealProposalRejected
|
|
||||||
Message string
|
|
||||||
Proposal cid.Cid
|
|
||||||
|
|
||||||
// DealAccepted
|
|
||||||
PublishMessage *cid.Cid
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Do we actually need this to be signed?
|
|
||||||
type SignedResponse struct {
|
|
||||||
Response Response
|
|
||||||
|
|
||||||
Signature *types.Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *SignedResponse) Verify(addr address.Address) error {
|
|
||||||
b, err := cborutil.Dump(&r.Response)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.Signature.Verify(addr, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
type AskRequest struct {
|
|
||||||
Miner address.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
type AskResponse struct {
|
|
||||||
Ask *types.SignedStorageAsk
|
|
||||||
}
|
|
||||||
|
|
||||||
// StorageDataTransferVoucher is the voucher type for data transfers
|
|
||||||
// used by the storage market
|
|
||||||
type StorageDataTransferVoucher struct {
|
|
||||||
Proposal cid.Cid
|
|
||||||
DealID uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToBytes converts the StorageDataTransferVoucher to raw bytes
|
|
||||||
func (dv *StorageDataTransferVoucher) ToBytes() ([]byte, error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err := dv.MarshalCBOR(&buf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromBytes converts the StorageDataTransferVoucher to raw bytes
|
|
||||||
func (dv *StorageDataTransferVoucher) FromBytes(raw []byte) error {
|
|
||||||
r := bytes.NewReader(raw)
|
|
||||||
return dv.UnmarshalCBOR(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type is the unique string identifier for a StorageDataTransferVoucher
|
|
||||||
func (dv *StorageDataTransferVoucher) Type() string {
|
|
||||||
return "StorageDataTransferVoucher"
|
|
||||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/filecoin-project/lotus/storagemarketadapter"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -23,10 +24,11 @@ import (
|
|||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-cbor-util"
|
"github.com/filecoin-project/go-cbor-util"
|
||||||
"github.com/filecoin-project/go-sectorbuilder"
|
"github.com/filecoin-project/go-sectorbuilder"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
|
deals "github.com/filecoin-project/go-fil-markets/storagemarket/impl"
|
||||||
lapi "github.com/filecoin-project/lotus/api"
|
lapi "github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/deals"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
lcli "github.com/filecoin-project/lotus/cli"
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
"github.com/filecoin-project/lotus/genesis"
|
"github.com/filecoin-project/lotus/genesis"
|
||||||
@ -281,8 +283,13 @@ func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir strin
|
|||||||
|
|
||||||
dealKey := datastore.NewKey(deals.ProviderDsPrefix).ChildString(proposalCid.String())
|
dealKey := datastore.NewKey(deals.ProviderDsPrefix).ChildString(proposalCid.String())
|
||||||
|
|
||||||
|
proposal, err := storagemarketadapter.ToSharedStorageDealProposal(§or.Deal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
deal := &deals.MinerDeal{
|
deal := &deals.MinerDeal{
|
||||||
Proposal: sector.Deal,
|
MinerDeal: storagemarket.MinerDeal{
|
||||||
|
Proposal: *proposal,
|
||||||
ProposalCid: proposalCid,
|
ProposalCid: proposalCid,
|
||||||
State: lapi.DealComplete,
|
State: lapi.DealComplete,
|
||||||
Ref: proposalCid, // TODO: This is super wrong, but there
|
Ref: proposalCid, // TODO: This is super wrong, but there
|
||||||
@ -290,6 +297,7 @@ func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir strin
|
|||||||
// and this isn't even used after the deal enters Complete state
|
// and this isn't even used after the deal enters Complete state
|
||||||
DealID: dealID,
|
DealID: dealID,
|
||||||
SectorID: sector.SectorID,
|
SectorID: sector.SectorID,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err = cborutil.Dump(deal)
|
b, err = cborutil.Dump(deal)
|
||||||
|
27
gen/main.go
27
gen/main.go
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
gen "github.com/whyrusleeping/cbor-gen"
|
gen "github.com/whyrusleeping/cbor-gen"
|
||||||
@ -10,7 +9,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/blocksync"
|
"github.com/filecoin-project/lotus/chain/blocksync"
|
||||||
"github.com/filecoin-project/lotus/chain/deals"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/paych"
|
"github.com/filecoin-project/lotus/paych"
|
||||||
"github.com/filecoin-project/lotus/storage"
|
"github.com/filecoin-project/lotus/storage"
|
||||||
@ -123,31 +121,6 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gen.WriteTupleEncodersToFile("./storagemarket/cbor_gen.go", "storagemarket",
|
|
||||||
storagemarket.ClientDeal{},
|
|
||||||
storagemarket.MinerDeal{},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gen.WriteTupleEncodersToFile("./chain/deals/cbor_gen.go", "deals",
|
|
||||||
deals.AskRequest{},
|
|
||||||
deals.AskResponse{},
|
|
||||||
deals.Proposal{},
|
|
||||||
deals.Response{},
|
|
||||||
deals.SignedResponse{},
|
|
||||||
deals.ClientDealProposal{},
|
|
||||||
deals.ClientDeal{},
|
|
||||||
deals.MinerDeal{},
|
|
||||||
deals.StorageDataTransferVoucher{},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gen.WriteMapEncodersToFile("./storage/cbor_gen.go", "storage",
|
err = gen.WriteMapEncodersToFile("./storage/cbor_gen.go", "storage",
|
||||||
storage.SealTicket{},
|
storage.SealTicket{},
|
||||||
storage.SealSeed{},
|
storage.SealSeed{},
|
||||||
|
1
go.mod
1
go.mod
@ -39,7 +39,6 @@ require (
|
|||||||
github.com/ipfs/go-graphsync v0.0.4
|
github.com/ipfs/go-graphsync v0.0.4
|
||||||
github.com/ipfs/go-hamt-ipld v0.0.14-0.20191218031521-b2c774a54db1
|
github.com/ipfs/go-hamt-ipld v0.0.14-0.20191218031521-b2c774a54db1
|
||||||
github.com/ipfs/go-ipfs-blockstore v0.1.1
|
github.com/ipfs/go-ipfs-blockstore v0.1.1
|
||||||
github.com/ipfs/go-ipfs-blocksutil v0.0.1
|
|
||||||
github.com/ipfs/go-ipfs-chunker v0.0.1
|
github.com/ipfs/go-ipfs-chunker v0.0.1
|
||||||
github.com/ipfs/go-ipfs-ds-help v0.0.1
|
github.com/ipfs/go-ipfs-ds-help v0.0.1
|
||||||
github.com/ipfs/go-ipfs-exchange-interface v0.0.1
|
github.com/ipfs/go-ipfs-exchange-interface v0.0.1
|
||||||
|
101
lib/sharedutils/converters.go
Normal file
101
lib/sharedutils/converters.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package sharedutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
sharedamount "github.com/filecoin-project/go-fil-markets/shared/tokenamount"
|
||||||
|
sharedtypes "github.com/filecoin-project/go-fil-markets/shared/types"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func FromSharedTokenAmount(in sharedamount.TokenAmount) types.BigInt {
|
||||||
|
return types.BigInt{Int: in.Int}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSharedTokenAmount(in types.BigInt) sharedamount.TokenAmount {
|
||||||
|
return sharedamount.TokenAmount{Int: in.Int}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSharedSignedVoucher(in *types.SignedVoucher) (*sharedtypes.SignedVoucher, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := in.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out sharedtypes.SignedVoucher
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromSharedSignedVoucher(in *sharedtypes.SignedVoucher) (*types.SignedVoucher, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := in.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out types.SignedVoucher
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSharedSignature(in *types.Signature) (*sharedtypes.Signature, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := in.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out sharedtypes.Signature
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromSharedSignature(in *sharedtypes.Signature) (*types.Signature, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := in.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out types.Signature
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSharedStorageAsk(in *types.SignedStorageAsk) (*sharedtypes.SignedStorageAsk, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := in.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out sharedtypes.SignedStorageAsk
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromSignedStorageAsk(in *sharedtypes.SignedStorageAsk) (*types.SignedStorageAsk, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := in.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out types.SignedStorageAsk
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
@ -21,10 +21,11 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket/discovery"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket/discovery"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
|
deals "github.com/filecoin-project/go-fil-markets/storagemarket/impl"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain"
|
"github.com/filecoin-project/lotus/chain"
|
||||||
"github.com/filecoin-project/lotus/chain/blocksync"
|
"github.com/filecoin-project/lotus/chain/blocksync"
|
||||||
"github.com/filecoin-project/lotus/chain/deals"
|
|
||||||
"github.com/filecoin-project/lotus/chain/gen"
|
"github.com/filecoin-project/lotus/chain/gen"
|
||||||
"github.com/filecoin-project/lotus/chain/market"
|
"github.com/filecoin-project/lotus/chain/market"
|
||||||
"github.com/filecoin-project/lotus/chain/messagepool"
|
"github.com/filecoin-project/lotus/chain/messagepool"
|
||||||
@ -47,7 +48,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/peermgr"
|
"github.com/filecoin-project/lotus/peermgr"
|
||||||
"github.com/filecoin-project/lotus/storage"
|
"github.com/filecoin-project/lotus/storage"
|
||||||
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
"github.com/filecoin-project/lotus/storagemarketadapter"
|
"github.com/filecoin-project/lotus/storagemarketadapter"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -228,8 +228,8 @@ func Online() Option {
|
|||||||
Override(new(retrievalmarket.RetrievalClient), modules.RetrievalClient),
|
Override(new(retrievalmarket.RetrievalClient), modules.RetrievalClient),
|
||||||
Override(new(dtypes.ClientDealStore), modules.NewClientDealStore),
|
Override(new(dtypes.ClientDealStore), modules.NewClientDealStore),
|
||||||
Override(new(dtypes.ClientDataTransfer), modules.NewClientDAGServiceDataTransfer),
|
Override(new(dtypes.ClientDataTransfer), modules.NewClientDAGServiceDataTransfer),
|
||||||
Override(new(*deals.ClientRequestValidator), deals.NewClientRequestValidator),
|
Override(new(*deals.ClientRequestValidator), modules.NewClientRequestValidator),
|
||||||
Override(new(storagemarket.StorageClient), deals.NewClient),
|
Override(new(storagemarket.StorageClient), modules.StorageClient),
|
||||||
Override(new(storagemarket.StorageClientNode), storagemarketadapter.NewClientNodeAdapter),
|
Override(new(storagemarket.StorageClientNode), storagemarketadapter.NewClientNodeAdapter),
|
||||||
Override(RegisterClientValidatorKey, modules.RegisterClientValidator),
|
Override(RegisterClientValidatorKey, modules.RegisterClientValidator),
|
||||||
Override(RunDealClientKey, modules.RunDealClient),
|
Override(RunDealClientKey, modules.RunDealClient),
|
||||||
@ -252,8 +252,8 @@ func Online() Option {
|
|||||||
Override(new(retrievalmarket.RetrievalProvider), modules.RetrievalProvider),
|
Override(new(retrievalmarket.RetrievalProvider), modules.RetrievalProvider),
|
||||||
Override(new(dtypes.ProviderDealStore), modules.NewProviderDealStore),
|
Override(new(dtypes.ProviderDealStore), modules.NewProviderDealStore),
|
||||||
Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDAGServiceDataTransfer),
|
Override(new(dtypes.ProviderDataTransfer), modules.NewProviderDAGServiceDataTransfer),
|
||||||
Override(new(*deals.ProviderRequestValidator), deals.NewProviderRequestValidator),
|
Override(new(*deals.ProviderRequestValidator), modules.NewProviderRequestValidator),
|
||||||
Override(new(storagemarket.StorageProvider), deals.NewProvider),
|
Override(new(storagemarket.StorageProvider), modules.StorageProvider),
|
||||||
Override(new(storagemarket.StorageProviderNode), storagemarketadapter.NewProviderNodeAdapter),
|
Override(new(storagemarket.StorageProviderNode), storagemarketadapter.NewProviderNodeAdapter),
|
||||||
Override(RegisterProviderValidatorKey, modules.RegisterProviderValidator),
|
Override(RegisterProviderValidatorKey, modules.RegisterProviderValidator),
|
||||||
Override(HandleRetrievalKey, modules.HandleRetrieval),
|
Override(HandleRetrievalKey, modules.HandleRetrieval),
|
||||||
|
@ -26,15 +26,18 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/shared/tokenamount"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sharedutils"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
"github.com/filecoin-project/lotus/node/impl/paych"
|
"github.com/filecoin-project/lotus/node/impl/paych"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/retrievaladapter"
|
"github.com/filecoin-project/lotus/retrievaladapter"
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
"github.com/filecoin-project/lotus/storagemarketadapter"
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
@ -73,20 +76,16 @@ func (a *API) ClientStartDeal(ctx context.Context, data cid.Cid, addr address.Ad
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed getting miner worker: %w", err)
|
return nil, xerrors.Errorf("failed getting miner worker: %w", err)
|
||||||
}
|
}
|
||||||
providerInfo := storagemarket.StorageProviderInfo{
|
providerInfo := storagemarketadapter.NewStorageProviderInfo(miner, mw, 0, pid)
|
||||||
Address: miner,
|
|
||||||
Worker: mw,
|
|
||||||
PeerID: pid,
|
|
||||||
}
|
|
||||||
result, err := a.SMDealClient.ProposeStorageDeal(
|
result, err := a.SMDealClient.ProposeStorageDeal(
|
||||||
ctx,
|
ctx,
|
||||||
addr,
|
sharedutils.ToSharedAddress(addr),
|
||||||
&providerInfo,
|
&providerInfo,
|
||||||
data,
|
data,
|
||||||
storagemarket.Epoch(math.MaxUint64),
|
storagemarket.Epoch(math.MaxUint64),
|
||||||
storagemarket.Epoch(blocksDuration),
|
storagemarket.Epoch(blocksDuration),
|
||||||
storagemarket.TokenAmount(epochPrice),
|
sharedutils.ToSharedTokenAmount(epochPrice),
|
||||||
storagemarket.TokenAmount(storagemarket.EmptyInt))
|
tokenamount.Empty)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to start deal: %w", err)
|
return nil, xerrors.Errorf("failed to start deal: %w", err)
|
||||||
@ -106,12 +105,12 @@ func (a *API) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) {
|
|||||||
out[k] = api.DealInfo{
|
out[k] = api.DealInfo{
|
||||||
ProposalCid: v.ProposalCid,
|
ProposalCid: v.ProposalCid,
|
||||||
State: v.State,
|
State: v.State,
|
||||||
Provider: v.Proposal.Provider,
|
Provider: sharedutils.FromSharedAddress(v.Proposal.Provider),
|
||||||
|
|
||||||
PieceRef: v.Proposal.PieceRef,
|
PieceRef: v.Proposal.PieceRef,
|
||||||
Size: v.Proposal.PieceSize,
|
Size: v.Proposal.PieceSize,
|
||||||
|
|
||||||
PricePerEpoch: v.Proposal.StoragePricePerEpoch,
|
PricePerEpoch: sharedutils.FromSharedTokenAmount(v.Proposal.StoragePricePerEpoch),
|
||||||
Duration: v.Proposal.Duration,
|
Duration: v.Proposal.Duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,10 +127,10 @@ func (a *API) ClientGetDealInfo(ctx context.Context, d cid.Cid) (*api.DealInfo,
|
|||||||
return &api.DealInfo{
|
return &api.DealInfo{
|
||||||
ProposalCid: v.ProposalCid,
|
ProposalCid: v.ProposalCid,
|
||||||
State: v.State,
|
State: v.State,
|
||||||
Provider: v.Proposal.Provider,
|
Provider: sharedutils.FromSharedAddress(v.Proposal.Provider),
|
||||||
PieceRef: v.Proposal.PieceRef,
|
PieceRef: v.Proposal.PieceRef,
|
||||||
Size: v.Proposal.PieceSize,
|
Size: v.Proposal.PieceSize,
|
||||||
PricePerEpoch: v.Proposal.StoragePricePerEpoch,
|
PricePerEpoch: sharedutils.FromSharedTokenAmount(v.Proposal.StoragePricePerEpoch),
|
||||||
Duration: v.Proposal.Duration,
|
Duration: v.Proposal.Duration,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -160,13 +159,13 @@ func (a *API) ClientFindData(ctx context.Context, root cid.Cid) ([]api.QueryOffe
|
|||||||
for k, p := range peers {
|
for k, p := range peers {
|
||||||
queryResponse, err := a.Retrieval.Query(ctx, p, root.Bytes(), retrievalmarket.QueryParams{})
|
queryResponse, err := a.Retrieval.Query(ctx, p, root.Bytes(), retrievalmarket.QueryParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out[k] = api.QueryOffer{Err: err.Error(), Miner: p.Address, MinerPeerID: p.ID}
|
out[k] = api.QueryOffer{Err: err.Error(), Miner: retrievaladapter.FromSharedAddress(p.Address), MinerPeerID: p.ID}
|
||||||
} else {
|
} else {
|
||||||
out[k] = api.QueryOffer{
|
out[k] = api.QueryOffer{
|
||||||
Root: root,
|
Root: root,
|
||||||
Size: queryResponse.Size,
|
Size: queryResponse.Size,
|
||||||
MinPrice: retrievaladapter.FromSharedTokenAmount(queryResponse.PieceRetrievalPrice()),
|
MinPrice: retrievaladapter.FromSharedTokenAmount(queryResponse.PieceRetrievalPrice()),
|
||||||
Miner: p.Address, // TODO: check
|
Miner: retrievaladapter.FromSharedAddress(p.Address), // TODO: check
|
||||||
MinerPeerID: p.ID,
|
MinerPeerID: p.ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,10 +295,10 @@ func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, path
|
|||||||
ctx,
|
ctx,
|
||||||
order.Root.Bytes(),
|
order.Root.Bytes(),
|
||||||
retrievalmarket.NewParamsV0(types.BigDiv(order.Total, types.NewInt(order.Size)).Int, 0, 0),
|
retrievalmarket.NewParamsV0(types.BigDiv(order.Total, types.NewInt(order.Size)).Int, 0, 0),
|
||||||
retrievaladapter.ToSharedTokenAmount(order.Total),
|
sharedutils.ToSharedTokenAmount(order.Total),
|
||||||
order.MinerPeerID,
|
order.MinerPeerID,
|
||||||
order.Client,
|
retrievaladapter.ToSharedAddress(order.Client),
|
||||||
order.Miner)
|
retrievaladapter.ToSharedAddress(order.Miner))
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return xerrors.New("Retrieval Timed Out")
|
return xerrors.New("Retrieval Timed Out")
|
||||||
@ -323,6 +322,10 @@ func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, path
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) {
|
func (a *API) ClientQueryAsk(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) {
|
||||||
info := storagemarket.StorageProviderInfo{Address: miner, PeerID: p}
|
info := storagemarketadapter.NewStorageProviderInfo(miner, address.Undef, 0, p)
|
||||||
return a.SMDealClient.GetAsk(ctx, info)
|
signedAsk, err := a.SMDealClient.GetAsk(ctx, info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sharedutils.FromSignedStorageAsk(signedAsk)
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,18 @@ package modules
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/filecoin-project/lotus/retrievaladapter"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/retrievaladapter"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket/discovery"
|
||||||
retrievalimpl "github.com/filecoin-project/go-fil-markets/retrievalmarket/impl"
|
retrievalimpl "github.com/filecoin-project/go-fil-markets/retrievalmarket/impl"
|
||||||
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-statestore"
|
"github.com/filecoin-project/go-statestore"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||||
"github.com/filecoin-project/lotus/paych"
|
"github.com/filecoin-project/lotus/paych"
|
||||||
|
|
||||||
@ -30,7 +35,8 @@ import (
|
|||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-data-transfer/impl/graphsync"
|
"github.com/filecoin-project/go-data-transfer/impl/graphsync"
|
||||||
"github.com/filecoin-project/lotus/chain/deals"
|
deals "github.com/filecoin-project/go-fil-markets/storagemarket/impl"
|
||||||
|
storageimpl "github.com/filecoin-project/go-fil-markets/storagemarket/impl"
|
||||||
payapi "github.com/filecoin-project/lotus/node/impl/paych"
|
payapi "github.com/filecoin-project/lotus/node/impl/paych"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
@ -104,6 +110,14 @@ func ClientGraphsync(mctx helpers.MetricsCtx, lc fx.Lifecycle, ibs dtypes.Client
|
|||||||
return gs
|
return gs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewClientRequestValidator(deals dtypes.ClientDealStore) *storageimpl.ClientRequestValidator {
|
||||||
|
return storageimpl.NewClientRequestValidator(deals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StorageClient(h host.Host, dag dtypes.ClientDAG, dataTransfer dtypes.ClientDataTransfer, discovery *discovery.Local, deals dtypes.ClientDealStore, scn storagemarket.StorageClientNode) storagemarket.StorageClient {
|
||||||
|
return storageimpl.NewClient(h, dag, dataTransfer, discovery, deals, scn)
|
||||||
|
}
|
||||||
|
|
||||||
// RetrievalClient creates a new retrieval client attached to the client blockstore
|
// RetrievalClient creates a new retrieval client attached to the client blockstore
|
||||||
func RetrievalClient(h host.Host, bs dtypes.ClientBlockstore, pmgr *paych.Manager, payapi payapi.PaychAPI) retrievalmarket.RetrievalClient {
|
func RetrievalClient(h host.Host, bs dtypes.ClientBlockstore, pmgr *paych.Manager, payapi payapi.PaychAPI) retrievalmarket.RetrievalClient {
|
||||||
adapter := retrievaladapter.NewRetrievalClientNode(pmgr, payapi)
|
adapter := retrievaladapter.NewRetrievalClientNode(pmgr, payapi)
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||||
"github.com/filecoin-project/lotus/peermgr"
|
"github.com/filecoin-project/lotus/peermgr"
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
"github.com/filecoin-project/go-fil-components/storagemarket"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunHello(mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host, svc *hello.Service) {
|
func RunHello(mctx helpers.MetricsCtx, lc fx.Lifecycle, h host.Host, svc *hello.Service) {
|
||||||
|
@ -27,21 +27,26 @@ import (
|
|||||||
dtgraphsync "github.com/filecoin-project/go-data-transfer/impl/graphsync"
|
dtgraphsync "github.com/filecoin-project/go-data-transfer/impl/graphsync"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
retrievalimpl "github.com/filecoin-project/go-fil-markets/retrievalmarket/impl"
|
retrievalimpl "github.com/filecoin-project/go-fil-markets/retrievalmarket/impl"
|
||||||
|
deals "github.com/filecoin-project/go-fil-markets/storagemarket/impl"
|
||||||
|
storageimpl "github.com/filecoin-project/go-fil-markets/storagemarket/impl"
|
||||||
"github.com/filecoin-project/go-sectorbuilder"
|
"github.com/filecoin-project/go-sectorbuilder"
|
||||||
"github.com/filecoin-project/go-statestore"
|
"github.com/filecoin-project/go-statestore"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/address"
|
||||||
"github.com/filecoin-project/lotus/chain/deals"
|
"github.com/filecoin-project/lotus/chain/deals"
|
||||||
"github.com/filecoin-project/lotus/chain/gen"
|
"github.com/filecoin-project/lotus/chain/gen"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sectorbuilder"
|
||||||
|
"github.com/filecoin-project/lotus/lib/statestore"
|
||||||
"github.com/filecoin-project/lotus/miner"
|
"github.com/filecoin-project/lotus/miner"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/modules/helpers"
|
"github.com/filecoin-project/lotus/node/modules/helpers"
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-fil-components/storagemarket"
|
||||||
"github.com/filecoin-project/lotus/retrievaladapter"
|
"github.com/filecoin-project/lotus/retrievaladapter"
|
||||||
"github.com/filecoin-project/lotus/storage"
|
"github.com/filecoin-project/lotus/storage"
|
||||||
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func minerAddrFromDS(ds dtypes.MetadataDS) (address.Address, error) {
|
func minerAddrFromDS(ds dtypes.MetadataDS) (address.Address, error) {
|
||||||
@ -264,6 +269,14 @@ func SealTicketGen(api api.FullNode) storage.TicketFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewProviderRequestValidator(deals dtypes.ProviderDealStore) *storageimpl.ProviderRequestValidator {
|
||||||
|
return storageimpl.NewProviderRequestValidator(deals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StorageProvider(ds dtypes.MetadataDS, dag dtypes.StagingDAG, dataTransfer dtypes.ProviderDataTransfer, spn storagemarket.StorageProviderNode) (storagemarket.StorageProvider, error) {
|
||||||
|
return storageimpl.NewProvider(ds, dag, dataTransfer, spn)
|
||||||
|
}
|
||||||
|
|
||||||
// RetrievalProvider creates a new retrieval provider attached to the provider blockstore
|
// RetrievalProvider creates a new retrieval provider attached to the provider blockstore
|
||||||
func RetrievalProvider(sblks *sectorblocks.SectorBlocks, full api.FullNode) retrievalmarket.RetrievalProvider {
|
func RetrievalProvider(sblks *sectorblocks.SectorBlocks, full api.FullNode) retrievalmarket.RetrievalProvider {
|
||||||
adapter := retrievaladapter.NewRetrievalProviderNode(sblks, full)
|
adapter := retrievaladapter.NewRetrievalProviderNode(sblks, full)
|
||||||
|
@ -2,6 +2,7 @@ package retrievaladapter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sharedutils"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
@ -26,7 +27,7 @@ func NewRetrievalClientNode(pmgr *paych.Manager, payapi payapi.PaychAPI) retriev
|
|||||||
// GetOrCreatePaymentChannel sets up a new payment channel if one does not exist
|
// GetOrCreatePaymentChannel sets up a new payment channel if one does not exist
|
||||||
// between a client and a miner and insures the client has the given amount of funds available in the channel
|
// between a client and a miner and insures the client has the given amount of funds available in the channel
|
||||||
func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, clientAddress address.Address, minerAddress address.Address, clientFundsAvailable retrievaltoken.TokenAmount) (address.Address, error) {
|
func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, clientAddress address.Address, minerAddress address.Address, clientFundsAvailable retrievaltoken.TokenAmount) (address.Address, error) {
|
||||||
paych, _, err := rcn.pmgr.GetPaych(ctx, clientAddress, minerAddress, FromSharedTokenAmount(clientFundsAvailable))
|
paych, _, err := rcn.pmgr.GetPaych(ctx, clientAddress, minerAddress, sharedutils.FromSharedTokenAmount(clientFundsAvailable))
|
||||||
return paych, err
|
return paych, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,9 +42,9 @@ func (rcn *retrievalClientNode) AllocateLane(paymentChannel address.Address) (ui
|
|||||||
// given payment channel so that all the payment vouchers in the lane add up
|
// given payment channel so that all the payment vouchers in the lane add up
|
||||||
// to the given amount (so the payment voucher will be for the difference)
|
// to the given amount (so the payment voucher will be for the difference)
|
||||||
func (rcn *retrievalClientNode) CreatePaymentVoucher(ctx context.Context, paymentChannel address.Address, amount retrievaltoken.TokenAmount, lane uint64) (*retrievaltypes.SignedVoucher, error) {
|
func (rcn *retrievalClientNode) CreatePaymentVoucher(ctx context.Context, paymentChannel address.Address, amount retrievaltoken.TokenAmount, lane uint64) (*retrievaltypes.SignedVoucher, error) {
|
||||||
voucher, err := rcn.payapi.PaychVoucherCreate(ctx, paymentChannel, FromSharedTokenAmount(amount), lane)
|
voucher, err := rcn.payapi.PaychVoucherCreate(ctx, paymentChannel, sharedutils.FromSharedTokenAmount(amount), lane)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return ToSharedSignedVoucher(voucher)
|
return sharedutils.ToSharedSignedVoucher(voucher)
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
package retrievaladapter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
sharedamount "github.com/filecoin-project/go-fil-markets/shared/tokenamount"
|
|
||||||
sharedtypes "github.com/filecoin-project/go-fil-markets/shared/types"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func FromSharedTokenAmount(in sharedamount.TokenAmount) types.BigInt {
|
|
||||||
return types.BigInt{Int: in.Int}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToSharedTokenAmount(in types.BigInt) sharedamount.TokenAmount {
|
|
||||||
return sharedamount.TokenAmount{Int: in.Int}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToSharedSignedVoucher(in *types.SignedVoucher) (*sharedtypes.SignedVoucher, error) {
|
|
||||||
var encoded bytes.Buffer
|
|
||||||
err := in.MarshalCBOR(&encoded)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var out sharedtypes.SignedVoucher
|
|
||||||
err = out.UnmarshalCBOR(&encoded)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromSharedSignedVoucher(in *sharedtypes.SignedVoucher) (*types.SignedVoucher, error) {
|
|
||||||
var encoded bytes.Buffer
|
|
||||||
err := in.MarshalCBOR(&encoded)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var out types.SignedVoucher
|
|
||||||
err = out.UnmarshalCBOR(&encoded)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &out, nil
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package retrievaladapter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sharedutils"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
||||||
@ -37,10 +38,10 @@ func (rpn *retrievalProviderNode) SealedBlockstore(approveUnseal func() error) b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rpn *retrievalProviderNode) SavePaymentVoucher(ctx context.Context, paymentChannel address.Address, voucher *retrievaltypes.SignedVoucher, proof []byte, expectedAmount retrievaltoken.TokenAmount) (retrievaltoken.TokenAmount, error) {
|
func (rpn *retrievalProviderNode) SavePaymentVoucher(ctx context.Context, paymentChannel address.Address, voucher *retrievaltypes.SignedVoucher, proof []byte, expectedAmount retrievaltoken.TokenAmount) (retrievaltoken.TokenAmount, error) {
|
||||||
localVoucher, err := FromSharedSignedVoucher(voucher)
|
localVoucher, err := sharedutils.FromSharedSignedVoucher(voucher)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return retrievaltoken.FromInt(0), err
|
return retrievaltoken.FromInt(0), err
|
||||||
}
|
}
|
||||||
added, err := rpn.full.PaychVoucherAdd(ctx, paymentChannel, localVoucher, proof, FromSharedTokenAmount(expectedAmount))
|
added, err := rpn.full.PaychVoucherAdd(ctx, paymentChannel, localVoucher, proof, sharedutils.FromSharedTokenAmount(expectedAmount))
|
||||||
return ToSharedTokenAmount(added), err
|
return sharedutils.ToSharedTokenAmount(added), err
|
||||||
}
|
}
|
||||||
|
@ -1,241 +0,0 @@
|
|||||||
// Copied from lotus until this can be extracted into shared types
|
|
||||||
|
|
||||||
package storagemarket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
|
||||||
"github.com/polydawn/refmt/obj/atlas"
|
|
||||||
|
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
)
|
|
||||||
|
|
||||||
const BigIntMaxSerializedLen = 128 // is this big enough? or too big?
|
|
||||||
|
|
||||||
var TotalFilecoinInt = FromFil(build.TotalFilecoin)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).Transform().
|
|
||||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
|
||||||
func(i BigInt) ([]byte, error) {
|
|
||||||
return i.cborBytes(), nil
|
|
||||||
})).
|
|
||||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
|
||||||
func(x []byte) (BigInt, error) {
|
|
||||||
return fromCborBytes(x)
|
|
||||||
})).
|
|
||||||
Complete())
|
|
||||||
}
|
|
||||||
|
|
||||||
var EmptyInt = BigInt{}
|
|
||||||
|
|
||||||
type BigInt struct {
|
|
||||||
*big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewInt(i uint64) BigInt {
|
|
||||||
return BigInt{big.NewInt(0).SetUint64(i)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromFil(i uint64) BigInt {
|
|
||||||
return BigMul(NewInt(i), NewInt(build.FilecoinPrecision))
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigFromBytes(b []byte) BigInt {
|
|
||||||
i := big.NewInt(0).SetBytes(b)
|
|
||||||
return BigInt{i}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigFromString(s string) (BigInt, error) {
|
|
||||||
v, ok := big.NewInt(0).SetString(s, 10)
|
|
||||||
if !ok {
|
|
||||||
return BigInt{}, fmt.Errorf("failed to parse string as a big int")
|
|
||||||
}
|
|
||||||
|
|
||||||
return BigInt{v}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigMul(a, b BigInt) BigInt {
|
|
||||||
return BigInt{big.NewInt(0).Mul(a.Int, b.Int)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigDiv(a, b BigInt) BigInt {
|
|
||||||
return BigInt{big.NewInt(0).Div(a.Int, b.Int)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigMod(a, b BigInt) BigInt {
|
|
||||||
return BigInt{big.NewInt(0).Mod(a.Int, b.Int)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigAdd(a, b BigInt) BigInt {
|
|
||||||
return BigInt{big.NewInt(0).Add(a.Int, b.Int)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigSub(a, b BigInt) BigInt {
|
|
||||||
return BigInt{big.NewInt(0).Sub(a.Int, b.Int)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BigCmp(a, b BigInt) int {
|
|
||||||
return a.Int.Cmp(b.Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bi BigInt) Nil() bool {
|
|
||||||
return bi.Int == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LessThan returns true if bi < o
|
|
||||||
func (bi BigInt) LessThan(o BigInt) bool {
|
|
||||||
return BigCmp(bi, o) < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GreaterThan returns true if bi > o
|
|
||||||
func (bi BigInt) GreaterThan(o BigInt) bool {
|
|
||||||
return BigCmp(bi, o) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equals returns true if bi == o
|
|
||||||
func (bi BigInt) Equals(o BigInt) bool {
|
|
||||||
return BigCmp(bi, o) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bi *BigInt) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(bi.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bi *BigInt) UnmarshalJSON(b []byte) error {
|
|
||||||
var s string
|
|
||||||
if err := json.Unmarshal(b, &s); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
i, ok := big.NewInt(0).SetString(s, 10)
|
|
||||||
if !ok {
|
|
||||||
if string(s) == "<nil>" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return xerrors.Errorf("failed to parse bigint string: '%s'", string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
bi.Int = i
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bi *BigInt) Scan(value interface{}) error {
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
i, ok := big.NewInt(0).SetString(value, 10)
|
|
||||||
if !ok {
|
|
||||||
if value == "<nil>" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return xerrors.Errorf("failed to parse bigint string: '%s'", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
bi.Int = i
|
|
||||||
|
|
||||||
return nil
|
|
||||||
case int64:
|
|
||||||
bi.Int = big.NewInt(value)
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return xerrors.Errorf("non-string types unsupported: %T", value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bi *BigInt) cborBytes() []byte {
|
|
||||||
if bi.Int == nil {
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case bi.Sign() > 0:
|
|
||||||
return append([]byte{0}, bi.Bytes()...)
|
|
||||||
case bi.Sign() < 0:
|
|
||||||
return append([]byte{1}, bi.Bytes()...)
|
|
||||||
default: // bi.Sign() == 0:
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fromCborBytes(buf []byte) (BigInt, error) {
|
|
||||||
if len(buf) == 0 {
|
|
||||||
return NewInt(0), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var negative bool
|
|
||||||
switch buf[0] {
|
|
||||||
case 0:
|
|
||||||
negative = false
|
|
||||||
case 1:
|
|
||||||
negative = true
|
|
||||||
default:
|
|
||||||
return EmptyInt, fmt.Errorf("big int prefix should be either 0 or 1, got %d", buf[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
i := big.NewInt(0).SetBytes(buf[1:])
|
|
||||||
if negative {
|
|
||||||
i.Neg(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return BigInt{i}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bi *BigInt) MarshalCBOR(w io.Writer) error {
|
|
||||||
if bi.Int == nil {
|
|
||||||
zero := NewInt(0)
|
|
||||||
return zero.MarshalCBOR(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
enc := bi.cborBytes()
|
|
||||||
|
|
||||||
header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(enc)))
|
|
||||||
if _, err := w.Write(header); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := w.Write(enc); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (bi *BigInt) UnmarshalCBOR(br io.Reader) error {
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if maj != cbg.MajByteString {
|
|
||||||
return fmt.Errorf("cbor input for fil big int was not a byte string (%x)", maj)
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra == 0 {
|
|
||||||
bi.Int = big.NewInt(0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra > BigIntMaxSerializedLen {
|
|
||||||
return fmt.Errorf("big integer byte array too long")
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, extra)
|
|
||||||
if _, err := io.ReadFull(br, buf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
i, err := fromCborBytes(buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*bi = i
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,352 +0,0 @@
|
|||||||
package storagemarket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
|
||||||
xerrors "golang.org/x/xerrors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT.
|
|
||||||
|
|
||||||
var _ = xerrors.Errorf
|
|
||||||
|
|
||||||
func (t *ClientDeal) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{136}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ProposalCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.ProposalCid); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.ProposalCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Proposal (actors.StorageDealProposal) (struct)
|
|
||||||
if err := t.Proposal.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.State))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Miner (peer.ID) (string)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Miner)))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte(t.Miner)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.MinerWorker (address.Address) (struct)
|
|
||||||
if err := t.MinerWorker.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.DealID))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.PayloadCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.PayloadCid); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.PayloadCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.PublishMessage (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if t.PublishMessage == nil {
|
|
||||||
if _, err := w.Write(cbg.CborNull); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := cbg.WriteCid(w, *t.PublishMessage); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.PublishMessage: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ClientDeal) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 8 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ProposalCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.ProposalCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.ProposalCid = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.Proposal (actors.StorageDealProposal) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.Proposal.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.State = uint64(extra)
|
|
||||||
// t.Miner (peer.ID) (string)
|
|
||||||
|
|
||||||
{
|
|
||||||
sval, err := cbg.ReadString(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Miner = peer.ID(sval)
|
|
||||||
}
|
|
||||||
// t.MinerWorker (address.Address) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.MinerWorker.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.DealID = uint64(extra)
|
|
||||||
// t.PayloadCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.PayloadCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.PayloadCid = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.PublishMessage (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
pb, err := br.PeekByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if pb == cbg.CborNull[0] {
|
|
||||||
var nbuf [1]byte
|
|
||||||
if _, err := br.Read(nbuf[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.PublishMessage: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.PublishMessage = &c
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *MinerDeal) MarshalCBOR(w io.Writer) error {
|
|
||||||
if t == nil {
|
|
||||||
_, err := w.Write(cbg.CborNull)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte{136}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ProposalCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.ProposalCid); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.ProposalCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Proposal (actors.StorageDealProposal) (struct)
|
|
||||||
if err := t.Proposal.MarshalCBOR(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Miner (peer.ID) (string)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Miner)))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte(t.Miner)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Client (peer.ID) (string)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Client)))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := w.Write([]byte(t.Client)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.State))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.Ref (cid.Cid) (struct)
|
|
||||||
|
|
||||||
if err := cbg.WriteCid(w, t.Ref); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write cid field t.Ref: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.DealID))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.SectorID (uint64) (uint64)
|
|
||||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *MinerDeal) UnmarshalCBOR(r io.Reader) error {
|
|
||||||
br := cbg.GetPeeker(r)
|
|
||||||
|
|
||||||
maj, extra, err := cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajArray {
|
|
||||||
return fmt.Errorf("cbor input should be of type array")
|
|
||||||
}
|
|
||||||
|
|
||||||
if extra != 8 {
|
|
||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
// t.ProposalCid (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.ProposalCid: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.ProposalCid = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.Proposal (actors.StorageDealProposal) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
if err := t.Proposal.UnmarshalCBOR(br); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.Miner (peer.ID) (string)
|
|
||||||
|
|
||||||
{
|
|
||||||
sval, err := cbg.ReadString(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Miner = peer.ID(sval)
|
|
||||||
}
|
|
||||||
// t.Client (peer.ID) (string)
|
|
||||||
|
|
||||||
{
|
|
||||||
sval, err := cbg.ReadString(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Client = peer.ID(sval)
|
|
||||||
}
|
|
||||||
// t.State (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.State = uint64(extra)
|
|
||||||
// t.Ref (cid.Cid) (struct)
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
c, err := cbg.ReadCid(br)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to read cid field t.Ref: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Ref = c
|
|
||||||
|
|
||||||
}
|
|
||||||
// t.DealID (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.DealID = uint64(extra)
|
|
||||||
// t.SectorID (uint64) (uint64)
|
|
||||||
|
|
||||||
maj, extra, err = cbg.CborReadHeader(br)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if maj != cbg.MajUnsignedInt {
|
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
|
||||||
}
|
|
||||||
t.SectorID = uint64(extra)
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,199 +0,0 @@
|
|||||||
package storagemarket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
"github.com/libp2p/go-libp2p-core/host"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
const DealProtocolID = "/fil/storage/mk/1.0.1"
|
|
||||||
const AskProtocolID = "/fil/storage/ask/1.0.1"
|
|
||||||
|
|
||||||
// type shims - used during migration into separate module
|
|
||||||
type Balance = actors.StorageParticipantBalance
|
|
||||||
type DealID uint64
|
|
||||||
type Signature = types.Signature
|
|
||||||
type StorageDeal = actors.OnChainDeal
|
|
||||||
type StorageAsk = types.SignedStorageAsk
|
|
||||||
type StateKey = *types.TipSet
|
|
||||||
type Epoch uint64
|
|
||||||
type TokenAmount BigInt
|
|
||||||
|
|
||||||
// Duplicated from deals package for now
|
|
||||||
type MinerDeal struct {
|
|
||||||
ProposalCid cid.Cid
|
|
||||||
Proposal actors.StorageDealProposal
|
|
||||||
Miner peer.ID
|
|
||||||
Client peer.ID
|
|
||||||
State api.DealState
|
|
||||||
|
|
||||||
Ref cid.Cid
|
|
||||||
|
|
||||||
DealID uint64
|
|
||||||
SectorID uint64 // Set when sm >= DealStaged
|
|
||||||
}
|
|
||||||
|
|
||||||
type ClientDeal struct {
|
|
||||||
ProposalCid cid.Cid
|
|
||||||
Proposal actors.StorageDealProposal
|
|
||||||
State api.DealState
|
|
||||||
Miner peer.ID
|
|
||||||
MinerWorker address.Address
|
|
||||||
DealID uint64
|
|
||||||
PayloadCid cid.Cid
|
|
||||||
PublishMessage *cid.Cid
|
|
||||||
}
|
|
||||||
|
|
||||||
// The interface provided for storage providers
|
|
||||||
type StorageProvider interface {
|
|
||||||
Run(ctx context.Context, host host.Host)
|
|
||||||
|
|
||||||
Stop()
|
|
||||||
|
|
||||||
AddAsk(price TokenAmount, ttlsecs int64) error
|
|
||||||
|
|
||||||
// ListAsks lists current asks
|
|
||||||
ListAsks(addr address.Address) []*StorageAsk
|
|
||||||
|
|
||||||
// ListDeals lists on-chain deals associated with this provider
|
|
||||||
ListDeals(ctx context.Context) ([]StorageDeal, error)
|
|
||||||
|
|
||||||
// ListIncompleteDeals lists deals that are in progress or rejected
|
|
||||||
ListIncompleteDeals() ([]MinerDeal, error)
|
|
||||||
|
|
||||||
// AddStorageCollateral adds storage collateral
|
|
||||||
AddStorageCollateral(ctx context.Context, amount TokenAmount) error
|
|
||||||
|
|
||||||
// GetStorageCollateral returns the current collateral balance
|
|
||||||
GetStorageCollateral(ctx context.Context) (Balance, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node dependencies for a StorageProvider
|
|
||||||
type StorageProviderNode interface {
|
|
||||||
MostRecentStateId(ctx context.Context) (StateKey, error)
|
|
||||||
|
|
||||||
// Adds funds with the StorageMinerActor for a storage participant. Used by both providers and clients.
|
|
||||||
AddFunds(ctx context.Context, addr address.Address, amount TokenAmount) error
|
|
||||||
|
|
||||||
// Ensures that a storage market participant has a certain amount of available funds
|
|
||||||
EnsureFunds(ctx context.Context, addr address.Address, amount TokenAmount) error
|
|
||||||
|
|
||||||
// GetBalance returns locked/unlocked for a storage participant. Used by both providers and clients.
|
|
||||||
GetBalance(ctx context.Context, addr address.Address) (Balance, error)
|
|
||||||
|
|
||||||
// Publishes deal on chain
|
|
||||||
PublishDeals(ctx context.Context, deal MinerDeal) (DealID, cid.Cid, error)
|
|
||||||
|
|
||||||
// ListProviderDeals lists all deals associated with a storage provider
|
|
||||||
ListProviderDeals(ctx context.Context, addr address.Address) ([]StorageDeal, error)
|
|
||||||
|
|
||||||
// Called when a deal is complete and on chain, and data has been transferred and is ready to be added to a sector
|
|
||||||
// returns sector id
|
|
||||||
OnDealComplete(ctx context.Context, deal MinerDeal, piecePath string) (uint64, error)
|
|
||||||
|
|
||||||
// returns the worker address associated with a miner
|
|
||||||
GetMinerWorker(ctx context.Context, miner address.Address) (address.Address, error)
|
|
||||||
|
|
||||||
// Signs bytes
|
|
||||||
SignBytes(ctx context.Context, signer address.Address, b []byte) (*types.Signature, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type DealSectorCommittedCallback func(error)
|
|
||||||
|
|
||||||
// Node dependencies for a StorageClient
|
|
||||||
type StorageClientNode interface {
|
|
||||||
MostRecentStateId(ctx context.Context) (StateKey, error)
|
|
||||||
|
|
||||||
// Adds funds with the StorageMinerActor for a storage participant. Used by both providers and clients.
|
|
||||||
AddFunds(ctx context.Context, addr address.Address, amount TokenAmount) error
|
|
||||||
|
|
||||||
EnsureFunds(ctx context.Context, addr address.Address, amount TokenAmount) error
|
|
||||||
|
|
||||||
// GetBalance returns locked/unlocked for a storage participant. Used by both providers and clients.
|
|
||||||
GetBalance(ctx context.Context, addr address.Address) (Balance, error)
|
|
||||||
|
|
||||||
//// ListClientDeals lists all on-chain deals associated with a storage client
|
|
||||||
ListClientDeals(ctx context.Context, addr address.Address) ([]StorageDeal, error)
|
|
||||||
|
|
||||||
// GetProviderInfo returns information about a single storage provider
|
|
||||||
//GetProviderInfo(stateId StateID, addr Address) *StorageProviderInfo
|
|
||||||
|
|
||||||
// GetStorageProviders returns information about known miners
|
|
||||||
ListStorageProviders(ctx context.Context) ([]*StorageProviderInfo, error)
|
|
||||||
|
|
||||||
// Subscribes to storage market actor state changes for a given address.
|
|
||||||
// TODO: Should there be a timeout option for this? In the case that we are waiting for funds to be deposited and it never happens?
|
|
||||||
//SubscribeStorageMarketEvents(addr Address, handler StorageMarketEventHandler) (SubID, error)
|
|
||||||
|
|
||||||
// Cancels a subscription
|
|
||||||
//UnsubscribeStorageMarketEvents(subId SubID)
|
|
||||||
ValidatePublishedDeal(ctx context.Context, deal ClientDeal) (uint64, error)
|
|
||||||
|
|
||||||
// SignProposal signs a proposal
|
|
||||||
SignProposal(ctx context.Context, signer address.Address, proposal *actors.StorageDealProposal) error
|
|
||||||
|
|
||||||
GetDefaultWalletAddress(ctx context.Context) (address.Address, error)
|
|
||||||
|
|
||||||
OnDealSectorCommitted(ctx context.Context, provider address.Address, dealId uint64, cb DealSectorCommittedCallback) error
|
|
||||||
|
|
||||||
ValidateAskSignature(ask *StorageAsk) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type StorageClientProofs interface {
|
|
||||||
//GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (CommP, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Closely follows the MinerInfo struct in the spec
|
|
||||||
type StorageProviderInfo struct {
|
|
||||||
Address address.Address // actor address
|
|
||||||
Owner address.Address
|
|
||||||
Worker address.Address // signs messages
|
|
||||||
SectorSize uint64
|
|
||||||
PeerID peer.ID
|
|
||||||
// probably more like how much storage power, available collateral etc
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProposeStorageDealResult struct {
|
|
||||||
ProposalCid cid.Cid
|
|
||||||
}
|
|
||||||
|
|
||||||
// The interface provided by the module to the outside world for storage clients.
|
|
||||||
type StorageClient interface {
|
|
||||||
Run(ctx context.Context)
|
|
||||||
|
|
||||||
Stop()
|
|
||||||
|
|
||||||
// ListProviders queries chain state and returns active storage providers
|
|
||||||
ListProviders(ctx context.Context) (<-chan StorageProviderInfo, error)
|
|
||||||
|
|
||||||
// ListDeals lists on-chain deals associated with this provider
|
|
||||||
ListDeals(ctx context.Context, addr address.Address) ([]StorageDeal, error)
|
|
||||||
|
|
||||||
// ListInProgressDeals lists deals that are in progress or rejected
|
|
||||||
ListInProgressDeals(ctx context.Context) ([]ClientDeal, error)
|
|
||||||
|
|
||||||
// ListInProgressDeals lists deals that are in progress or rejected
|
|
||||||
GetInProgressDeal(ctx context.Context, cid cid.Cid) (ClientDeal, error)
|
|
||||||
|
|
||||||
// GetAsk returns the current ask for a storage provider
|
|
||||||
GetAsk(ctx context.Context, info StorageProviderInfo) (*StorageAsk, error)
|
|
||||||
|
|
||||||
//// FindStorageOffers lists providers and queries them to find offers that satisfy some criteria based on price, duration, etc.
|
|
||||||
//FindStorageOffers(criteria AskCriteria, limit uint) []*StorageOffer
|
|
||||||
|
|
||||||
// ProposeStorageDeal initiates deal negotiation with a Storage Provider
|
|
||||||
ProposeStorageDeal(ctx context.Context, addr address.Address, info *StorageProviderInfo, payloadCid cid.Cid, proposalExpiration Epoch, duration Epoch, price TokenAmount, collateral TokenAmount) (*ProposeStorageDealResult, error)
|
|
||||||
|
|
||||||
// GetPaymentEscrow returns the current funds available for deal payment
|
|
||||||
GetPaymentEscrow(ctx context.Context, addr address.Address) (Balance, error)
|
|
||||||
|
|
||||||
// AddStorageCollateral adds storage collateral
|
|
||||||
AddPaymentEscrow(ctx context.Context, addr address.Address, amount TokenAmount) error
|
|
||||||
}
|
|
@ -5,11 +5,14 @@ package storagemarketadapter
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sharedutils"
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-cbor-util"
|
"github.com/filecoin-project/go-cbor-util"
|
||||||
|
sharedtypes "github.com/filecoin-project/go-fil-markets/shared/types"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
@ -19,7 +22,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientNodeAdapter struct {
|
type ClientNodeAdapter struct {
|
||||||
@ -79,13 +81,8 @@ func (n *ClientNodeAdapter) ListStorageProviders(ctx context.Context) ([]*storag
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
storageProviderInfo := NewStorageProviderInfo(addr, workerAddr, sectorSize, peerId)
|
||||||
out = append(out, &storagemarket.StorageProviderInfo{
|
out = append(out, &storageProviderInfo)
|
||||||
Address: addr,
|
|
||||||
Worker: workerAddr,
|
|
||||||
SectorSize: sectorSize,
|
|
||||||
PeerID: peerId,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
@ -97,11 +94,12 @@ func (n *ClientNodeAdapter) ListClientDeals(ctx context.Context, addr address.Ad
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var out []actors.OnChainDeal
|
var out []storagemarket.StorageDeal
|
||||||
|
|
||||||
for _, deal := range allDeals {
|
for _, deal := range allDeals {
|
||||||
if deal.Client == addr {
|
storageDeal := FromOnChainDeal(deal)
|
||||||
out = append(out, deal)
|
if storageDeal.Client == addr {
|
||||||
|
out = append(out, storageDeal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,12 +111,12 @@ func (n *ClientNodeAdapter) MostRecentStateId(ctx context.Context) (storagemarke
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adds funds with the StorageMinerActor for a storage participant. Used by both providers and clients.
|
// Adds funds with the StorageMinerActor for a storage participant. Used by both providers and clients.
|
||||||
func (n *ClientNodeAdapter) AddFunds(ctx context.Context, addr address.Address, amount storagemarket.TokenAmount) error {
|
func (n *ClientNodeAdapter) AddFunds(ctx context.Context, addr address.Address, amount tokenamount.TokenAmount) error {
|
||||||
// (Provider Node API)
|
// (Provider Node API)
|
||||||
smsg, err := n.MpoolPushMessage(ctx, &types.Message{
|
smsg, err := n.MpoolPushMessage(ctx, &types.Message{
|
||||||
To: actors.StorageMarketAddress,
|
To: actors.StorageMarketAddress,
|
||||||
From: addr,
|
From: sharedutils.FromSharedAddress(addr),
|
||||||
Value: types.BigInt(amount),
|
Value: sharedutils.FromSharedTokenAmount(amount),
|
||||||
GasPrice: types.NewInt(0),
|
GasPrice: types.NewInt(0),
|
||||||
GasLimit: types.NewInt(1000000),
|
GasLimit: types.NewInt(1000000),
|
||||||
Method: actors.SMAMethods.AddBalance,
|
Method: actors.SMAMethods.AddBalance,
|
||||||
@ -139,17 +137,17 @@ func (n *ClientNodeAdapter) AddFunds(ctx context.Context, addr address.Address,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ClientNodeAdapter) EnsureFunds(ctx context.Context, addr address.Address, amount storagemarket.TokenAmount) error {
|
func (n *ClientNodeAdapter) EnsureFunds(ctx context.Context, addr address.Address, amount tokenamount.TokenAmount) error {
|
||||||
return n.fm.EnsureAvailable(ctx, addr, types.BigInt(amount))
|
return n.fm.EnsureAvailable(ctx, sharedutils.FromSharedAddress(addr), sharedutils.FromSharedTokenAmount(amount))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ClientNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) {
|
func (n *ClientNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) {
|
||||||
bal, err := n.StateMarketBalance(ctx, addr, nil)
|
bal, err := n.StateMarketBalance(ctx, sharedutils.FromSharedAddress(addr), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return storagemarket.Balance{}, err
|
return storagemarket.Balance{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bal, nil
|
return ToSharedBalance(bal), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidatePublishedDeal validates that the provided deal has appeared on chain and references the same ClientDeal
|
// ValidatePublishedDeal validates that the provided deal has appeared on chain and references the same ClientDeal
|
||||||
@ -162,7 +160,7 @@ func (c *ClientNodeAdapter) ValidatePublishedDeal(ctx context.Context, deal stor
|
|||||||
return 0, xerrors.Errorf("getting deal pubsish message: %w", err)
|
return 0, xerrors.Errorf("getting deal pubsish message: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pw, err := stmgr.GetMinerWorker(ctx, c.sm, nil, deal.Proposal.Provider)
|
pw, err := stmgr.GetMinerWorker(ctx, c.sm, nil, sharedutils.FromSharedAddress(deal.Proposal.Provider))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, xerrors.Errorf("getting miner worker failed: %w", err)
|
return 0, xerrors.Errorf("getting miner worker failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -270,7 +268,7 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider
|
|||||||
}
|
}
|
||||||
|
|
||||||
matchEvent := func(msg *types.Message) (bool, error) {
|
matchEvent := func(msg *types.Message) (bool, error) {
|
||||||
if msg.To != provider {
|
if msg.To != sharedutils.FromSharedAddress(provider) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,18 +299,23 @@ func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Address, proposal *actors.StorageDealProposal) error {
|
func (n *ClientNodeAdapter) SignProposal(ctx context.Context, signer address.Address, proposal *storagemarket.StorageDealProposal) error {
|
||||||
return api.SignWith(ctx, n.Wallet.Sign, signer, proposal)
|
localProposal, err := FromSharedStorageDealProposal(proposal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return api.SignWith(ctx, n.Wallet.Sign, sharedutils.FromSharedAddress(signer), localProposal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ClientNodeAdapter) GetDefaultWalletAddress(ctx context.Context) (address.Address, error) {
|
func (n *ClientNodeAdapter) GetDefaultWalletAddress(ctx context.Context) (address.Address, error) {
|
||||||
return n.Wallet.GetDefault()
|
addr, err := n.Wallet.GetDefault()
|
||||||
|
return sharedutils.ToSharedAddress(addr), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ClientNodeAdapter) ValidateAskSignature(ask *types.SignedStorageAsk) error {
|
func (n *ClientNodeAdapter) ValidateAskSignature(ask *sharedtypes.SignedStorageAsk) error {
|
||||||
tss := n.cs.GetHeaviestTipSet().ParentState()
|
tss := n.cs.GetHeaviestTipSet().ParentState()
|
||||||
|
|
||||||
w, err := stmgr.GetMinerWorkerRaw(context.TODO(), n.StateManager, tss, ask.Ask.Miner)
|
w, err := stmgr.GetMinerWorkerRaw(context.TODO(), n.StateManager, tss, sharedutils.FromSharedAddress(ask.Ask.Miner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to get worker for miner in ask", err)
|
return xerrors.Errorf("failed to get worker for miner in ask", err)
|
||||||
}
|
}
|
||||||
@ -322,7 +325,7 @@ func (n *ClientNodeAdapter) ValidateAskSignature(ask *types.SignedStorageAsk) er
|
|||||||
return xerrors.Errorf("failed to re-serialize ask")
|
return xerrors.Errorf("failed to re-serialize ask")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ask.Signature.Verify(w, sigb)
|
return ask.Signature.Verify(sharedutils.ToSharedAddress(w), sigb)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ storagemarket.StorageClientNode = &ClientNodeAdapter{}
|
var _ storagemarket.StorageClientNode = &ClientNodeAdapter{}
|
||||||
|
@ -6,19 +6,23 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/lib/sharedutils"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
unixfile "github.com/ipfs/go-unixfs/file"
|
unixfile "github.com/ipfs/go-unixfs/file"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/shared/tokenamount"
|
||||||
|
sharedtypes "github.com/filecoin-project/go-fil-markets/shared/types"
|
||||||
|
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/lib/padreader"
|
"github.com/filecoin-project/lotus/lib/padreader"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
||||||
"github.com/filecoin-project/lotus/storagemarket"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = logging.Logger("provideradapter")
|
var log = logging.Logger("provideradapter")
|
||||||
@ -43,13 +47,17 @@ func NewProviderNodeAdapter(dag dtypes.StagingDAG, secb *sectorblocks.SectorBloc
|
|||||||
func (n *ProviderNodeAdapter) PublishDeals(ctx context.Context, deal storagemarket.MinerDeal) (storagemarket.DealID, cid.Cid, error) {
|
func (n *ProviderNodeAdapter) PublishDeals(ctx context.Context, deal storagemarket.MinerDeal) (storagemarket.DealID, cid.Cid, error) {
|
||||||
log.Info("publishing deal")
|
log.Info("publishing deal")
|
||||||
|
|
||||||
worker, err := n.StateMinerWorker(ctx, deal.Proposal.Provider, nil)
|
worker, err := n.StateMinerWorker(ctx, sharedutils.FromSharedAddress(deal.Proposal.Provider), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, cid.Undef, err
|
return 0, cid.Undef, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
localProposal, err := FromSharedStorageDealProposal(&deal.Proposal)
|
||||||
|
if err != nil {
|
||||||
|
return 0, cid.Undef, err
|
||||||
|
}
|
||||||
params, err := actors.SerializeParams(&actors.PublishStorageDealsParams{
|
params, err := actors.SerializeParams(&actors.PublishStorageDealsParams{
|
||||||
Deals: []actors.StorageDealProposal{deal.Proposal},
|
Deals: []actors.StorageDealProposal{*localProposal},
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -124,17 +132,18 @@ func (n *ProviderNodeAdapter) OnDealComplete(ctx context.Context, deal storagema
|
|||||||
return sectorID, nil
|
return sectorID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ProviderNodeAdapter) ListProviderDeals(ctx context.Context, addr address.Address) ([]actors.OnChainDeal, error) {
|
func (n *ProviderNodeAdapter) ListProviderDeals(ctx context.Context, addr address.Address) ([]storagemarket.StorageDeal, error) {
|
||||||
allDeals, err := n.StateMarketDeals(ctx, nil)
|
allDeals, err := n.StateMarketDeals(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var out []actors.OnChainDeal
|
var out []storagemarket.StorageDeal
|
||||||
|
|
||||||
for _, deal := range allDeals {
|
for _, deal := range allDeals {
|
||||||
if deal.Provider == addr {
|
sharedDeal := FromOnChainDeal(deal)
|
||||||
out = append(out, deal)
|
if sharedDeal.Provider == addr {
|
||||||
|
out = append(out, sharedDeal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,15 +151,20 @@ func (n *ProviderNodeAdapter) ListProviderDeals(ctx context.Context, addr addres
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *ProviderNodeAdapter) GetMinerWorker(ctx context.Context, miner address.Address) (address.Address, error) {
|
func (n *ProviderNodeAdapter) GetMinerWorker(ctx context.Context, miner address.Address) (address.Address, error) {
|
||||||
return n.StateMinerWorker(ctx, miner, nil)
|
addr, err := n.StateMinerWorker(ctx, sharedutils.FromSharedAddress(miner), nil)
|
||||||
|
return sharedutils.ToSharedAddress(addr), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ProviderNodeAdapter) SignBytes(ctx context.Context, signer address.Address, b []byte) (*types.Signature, error) {
|
func (n *ProviderNodeAdapter) SignBytes(ctx context.Context, signer address.Address, b []byte) (*sharedtypes.Signature, error) {
|
||||||
return n.WalletSign(ctx, signer, b)
|
localSignature, err := n.WalletSign(ctx, sharedutils.FromSharedAddress(signer), b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sharedutils.ToSharedSignature(localSignature)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ProviderNodeAdapter) EnsureFunds(ctx context.Context, addr address.Address, amt storagemarket.TokenAmount) error {
|
func (n *ProviderNodeAdapter) EnsureFunds(ctx context.Context, addr address.Address, amt tokenamount.TokenAmount) error {
|
||||||
return n.MarketEnsureAvailable(ctx, addr, types.BigInt(amt))
|
return n.MarketEnsureAvailable(ctx, sharedutils.FromSharedAddress(addr), sharedutils.FromSharedTokenAmount(amt))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *ProviderNodeAdapter) MostRecentStateId(ctx context.Context) (storagemarket.StateKey, error) {
|
func (n *ProviderNodeAdapter) MostRecentStateId(ctx context.Context) (storagemarket.StateKey, error) {
|
||||||
@ -158,12 +172,12 @@ func (n *ProviderNodeAdapter) MostRecentStateId(ctx context.Context) (storagemar
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adds funds with the StorageMinerActor for a storage participant. Used by both providers and clients.
|
// Adds funds with the StorageMinerActor for a storage participant. Used by both providers and clients.
|
||||||
func (n *ProviderNodeAdapter) AddFunds(ctx context.Context, addr address.Address, amount storagemarket.TokenAmount) error {
|
func (n *ProviderNodeAdapter) AddFunds(ctx context.Context, addr address.Address, amount tokenamount.TokenAmount) error {
|
||||||
// (Provider Node API)
|
// (Provider Node API)
|
||||||
smsg, err := n.MpoolPushMessage(ctx, &types.Message{
|
smsg, err := n.MpoolPushMessage(ctx, &types.Message{
|
||||||
To: actors.StorageMarketAddress,
|
To: actors.StorageMarketAddress,
|
||||||
From: addr,
|
From: sharedutils.FromSharedAddress(addr),
|
||||||
Value: types.BigInt(amount),
|
Value: sharedutils.FromSharedTokenAmount(amount),
|
||||||
GasPrice: types.NewInt(0),
|
GasPrice: types.NewInt(0),
|
||||||
GasLimit: types.NewInt(1000000),
|
GasLimit: types.NewInt(1000000),
|
||||||
Method: actors.SMAMethods.AddBalance,
|
Method: actors.SMAMethods.AddBalance,
|
||||||
@ -185,12 +199,12 @@ func (n *ProviderNodeAdapter) AddFunds(ctx context.Context, addr address.Address
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *ProviderNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) {
|
func (n *ProviderNodeAdapter) GetBalance(ctx context.Context, addr address.Address) (storagemarket.Balance, error) {
|
||||||
bal, err := n.StateMarketBalance(ctx, addr, nil)
|
bal, err := n.StateMarketBalance(ctx, sharedutils.FromSharedAddress(addr), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return storagemarket.Balance{}, err
|
return storagemarket.Balance{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return bal, nil
|
return ToSharedBalance(bal), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ storagemarket.StorageProviderNode = &ProviderNodeAdapter{}
|
var _ storagemarket.StorageProviderNode = &ProviderNodeAdapter{}
|
||||||
|
79
storagemarketadapter/utilities.go
Normal file
79
storagemarketadapter/utilities.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package storagemarketadapter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-fil-components/storagemarket"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
|
"github.com/filecoin-project/lotus/chain/address"
|
||||||
|
"github.com/filecoin-project/lotus/lib/sharedutils"
|
||||||
|
peer "github.com/libp2p/go-libp2p-peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewStorageProviderInfo(address address.Address, miner address.Address, sectorSize uint64, peer peer.ID) storagemarket.StorageProviderInfo {
|
||||||
|
return storagemarket.StorageProviderInfo{
|
||||||
|
Address: sharedutils.ToSharedAddress(address),
|
||||||
|
Worker: sharedutils.ToSharedAddress(miner),
|
||||||
|
SectorSize: sectorSize,
|
||||||
|
PeerID: peer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromOnChainDeal(deal actors.OnChainDeal) storagemarket.StorageDeal {
|
||||||
|
return storagemarket.StorageDeal{
|
||||||
|
PieceRef: deal.PieceRef,
|
||||||
|
PieceSize: deal.PieceSize,
|
||||||
|
Client: sharedutils.ToSharedAddress(deal.Client),
|
||||||
|
Provider: sharedutils.ToSharedAddress(deal.Provider),
|
||||||
|
StoragePricePerEpoch: sharedutils.ToSharedTokenAmount(deal.StoragePricePerEpoch),
|
||||||
|
StorageCollateral: sharedutils.ToSharedTokenAmount(deal.StorageCollateral),
|
||||||
|
ActivationEpoch: deal.ActivationEpoch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToOnChainDeal(deal storagemarket.StorageDeal) actors.OnChainDeal {
|
||||||
|
return actors.OnChainDeal{
|
||||||
|
PieceRef: deal.PieceRef,
|
||||||
|
PieceSize: deal.PieceSize,
|
||||||
|
Client: sharedutils.FromSharedAddress(deal.Client),
|
||||||
|
Provider: sharedutils.FromSharedAddress(deal.Provider),
|
||||||
|
StoragePricePerEpoch: sharedutils.FromSharedTokenAmount(deal.StoragePricePerEpoch),
|
||||||
|
StorageCollateral: sharedutils.FromSharedTokenAmount(deal.StorageCollateral),
|
||||||
|
ActivationEpoch: deal.ActivationEpoch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSharedBalance(balance actors.StorageParticipantBalance) storagemarket.Balance {
|
||||||
|
return storagemarket.Balance{
|
||||||
|
Locked: sharedutils.ToSharedTokenAmount(balance.Locked),
|
||||||
|
Available: sharedutils.ToSharedTokenAmount(balance.Available),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSharedStorageDealProposal(proposal *actors.StorageDealProposal) (*storagemarket.StorageDealProposal, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := proposal.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out storagemarket.StorageDealProposal
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromSharedStorageDealProposal(proposal *storagemarket.StorageDealProposal) (*actors.StorageDealProposal, error) {
|
||||||
|
var encoded bytes.Buffer
|
||||||
|
err := proposal.MarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var out actors.StorageDealProposal
|
||||||
|
err = out.UnmarshalCBOR(&encoded)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user