# Dependencies

Name Kind APIs
Data Transfer required ManagerAPI
Payment Channel Manager required default

# Roadmap

V0: Existing or 3 months

Retrieval Protocol V1 is the current implementation of Exchange in Filecoin. It operates through a system of incremental payments, with the data provider sending small chunks then asking for payment before sending more.

V0.5: 6 months

The proposed API below represents a slightly more semantic and clean design than the current implementation. It may make sense to conform to the proposed API in preparation for adding other exchange protocols in the future.

V1: 1 Year

In a more traditional CDN context, a content provider is often pays for bandwidth and resources on a servers so that a client is able to download data quickly. The client themselves often does not pay anything for this data. To support this kind of usage, we will likely have to augment the Exchange Protocol to support this kind of 3-way transaction. A client might in this scenario instead send a proof to the content provider that they have received the data causing the content provider to unlock payment to the miner.

V2: Future

Fair exchange is a hard problem and out existing retrieval protocol is very much an "MVP". While it may be sufficient for some time, improved protocols might unlock superior performance, particularly if they become tied to crtypographic incentires.

# Preliminary API

This API is primarily based on the Filecoin Retrieval Protocol implementation in go-fil-markets (opens new window)

package exchange

import (
	"github.com/filecoin-project/retrieval-market-spec/docs/components/datatransfer"
	"github.com/ipfs/go-cid"
	"github.com/ipld/go-ipld-prime"
	peer "github.com/libp2p/go-libp2p-core/peer"
)

type DealID uint64

// ClientDealState is the state of an in progress deal
// fields are dependent on the exchange protocol
type ClientDealState ipld.Node

// ClientEvent is an event that occurs in a deal lifecycle on the client
type ClientEvent uint64

type ClientEventData struct {
	Event ClientEvent
	State ClientDealState
}

// ExchangeProtocolName identifies a given exchange protocol
// This probably will need to be more than a string in actuality,
// this is just a placeholder
type ExchangeProtocolName string

// ExchangeClientAPI is exposed the party paying to receive or send data
type ExchangeClientAPI interface {
	ProtocolName() ExchangeProtocolName

	// RequestData requests data in exchange for payment (a traditional
	// retrieval
	// deal)
	RequestData(
		payloadCID cid.Cid,
		selector ipld.Node,
		parameters ipld.Node,
	) (DealID, error)

	// SendData requests to send someone data in excahgne for payment - probably
	// unused for some time
	SendData(
		payloadCID cid.Cid,
		selector ipld.Node,
		parameters ipld.Node,
	) (DealID, error)

	// CancelDeal attempts to cancel an inprogress deal
	CancelDeal(id DealID) error

	// GetDeal returns a given deal by deal ID, if it exists
	GetDeal(dealID DealID) (ClientDealState, error)

	// ListDeals returns all deals
	ListDeals() (map[DealID]ClientDealState, error)

	// get notified when certain types of events happen
	EventsNotify() <-chan ClientEventData
}

// ProviderDealState is the state of an in progress deal
// fields are dependent on the exchange protocol
type ProviderDealState ipld.Node

// ProviderEvent is an event that occurs in a deal lifecycle on the provider
type ProviderEvent uint64

type ProviderEventData struct {
	Event ProviderEvent
	State ProviderDealState
}

// ProviderDealID is a value that uniquely identifies a deal for a provider
type ProviderDealID struct {
	Receiver peer.ID
	DealID   DealID
}

// Ask specifies the parameters that will be accepted for incoming deals
// the specific fields will depend on the exchange protocol
type Ask ipld.Node

// ExchangeProviderAPI is exposed to the party sending or receiving data in
// exchange for payment
type ExchangeProviderAPI interface {
	ProtocolName() ExchangeProtocolName

	// SetAsk sets the payment parameters for this
	SetAsk(ask Ask)

	// GetAsk returns the retrieval providers pricing information
	GetAsk() Ask

	// get notified when certain types of events happen
	EventsNotify() <-chan ProviderEventData

	// ListDeals shows the in progress deals for this exchange protocol
	ListDeals() map[ProviderDealID]ProviderDealState
}

// ExchangeValidatorAPI is an interface provided to data transfer to validate
// incoming transfers by the party sending or receiving data in exchange for
// payment
type ExchangeValidatorAPI interface {
	// ValidatePush validates an incoming data transfer push request received
	// for
	// this exchange protocol
	ValidatePush(
		sender peer.ID,
		voucher datatransfer.Voucher,
		baseCid cid.Cid,
		selector ipld.Node,
	) (datatransfer.VoucherResult, error)

	// ValidatePull validates an incoming data transfer pull request received
	// for
	// this exchange protocol
	ValidatePull(
		receiver peer.ID,
		voucher datatransfer.Voucher,
		baseCid cid.Cid,
		selector ipld.Node,
	) (datatransfer.VoucherResult, error)
}

// ExchangeCheckpointValidatorAPI is for exchange providers that want to
// checkpoint payments. Data transfer uses this to pause and resume
// This is based on the existing data transfer revalidator interface but
// made slightly more high leve For ease of use
type ExchangeCheckpointValidatorAPI interface {

	// NextCheckPoint specifies the next point at which data transfer should
	// pause transfer
	// return values are:
	// byteOffset = minimum next offset at which checkpoint reached should be
	// called
	// err = abort request if not nil
	NextCheckPoint(
		channelID datatransfer.ChannelID,
	) (byteOffset uint64, err error)

	// CheckpointReached allows an exchange to produce a request for payment
	// after a checkpoint has
	// been passed
	// Note: checkpoint is not exact for some protocols -- the byteOffs may be
	// slightly larger than
	// the one requested
	// return values are:
	// voucher result = information about payment requested, if any
	// err = error
	// - nil = no payment needed, continue request
	// - error = abort this request
	// - err == ErrPause - pause for payment
	CheckpointReached(
		channelID datatransfer.ChannelID,
		actualByteOffset uint64,
	) (datatransfer.VoucherResult, error)

	// EndOfDataReached allows for a final last request for payment
	// return values are:
	// voucher result = information about payment requested, if any
	// err = error
	// - nil = no payment needed, completed request
	// - error = terminate request with error
	// - err == ErrPause - pause for final payment
	EndOfDataReached(
		channelID datatransfer.ChannelID,
		actualByteOffset uint64,
	) (datatransfer.VoucherResult, error)

	// Revalidate processes a new voucher (likely a payment) intended to resume
	// transfer
	// return values are:
	// voucher result = information about why the payment succeeded or failed
	// err = error
	// - nil = resume the request
	// - error = abort this request
	// - err == ErrPause - leave this request paused
	Revalidate(
		channelID datatransfer.ChannelID,
		voucher datatransfer.Voucher,
	) (datatransfer.VoucherResult, error)
}