-
Notifications
You must be signed in to change notification settings - Fork 59
/
types.go
402 lines (337 loc) · 13.4 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
package retrievalmarket
import (
"bytes"
"errors"
"fmt"
"github.com/ipfs/go-cid"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/protocol"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-multistore"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
"github.com/filecoin-project/go-fil-markets/piecestore"
)
//go:generate cbor-gen-for --map-encoding Query QueryResponse DealProposal DealResponse Params QueryParams DealPayment ClientDealState ProviderDealState PaymentInfo RetrievalPeer Ask
// QueryProtocolID is the protocol for querying information about retrieval
// deal parameters
const QueryProtocolID = protocol.ID("/fil/retrieval/qry/1.0.0")
// OldQueryProtocolID is the old query protocol for tuple structs
const OldQueryProtocolID = protocol.ID("/fil/retrieval/qry/0.0.1")
// Unsubscribe is a function that unsubscribes a subscriber for either the
// client or the provider
type Unsubscribe func()
// PaymentInfo is the payment channel and lane for a deal, once it is setup
type PaymentInfo struct {
PayCh address.Address
Lane uint64
}
// ClientDealState is the current state of a deal from the point of view
// of a retrieval client
type ClientDealState struct {
DealProposal
StoreID *multistore.StoreID
// Set when the data transfer is started
ChannelID *datatransfer.ChannelID
LastPaymentRequested bool
AllBlocksReceived bool
TotalFunds abi.TokenAmount
ClientWallet address.Address
MinerWallet address.Address
PaymentInfo *PaymentInfo
Status DealStatus
Sender peer.ID
TotalReceived uint64
Message string
BytesPaidFor uint64
CurrentInterval uint64
PaymentRequested abi.TokenAmount
FundsSpent abi.TokenAmount
UnsealFundsPaid abi.TokenAmount
WaitMsgCID *cid.Cid // the CID of any message the client deal is waiting for
VoucherShortfall abi.TokenAmount
LegacyProtocol bool
}
// ProviderDealState is the current state of a deal from the point of view
// of a retrieval provider
type ProviderDealState struct {
DealProposal
StoreID multistore.StoreID
ChannelID *datatransfer.ChannelID
PieceInfo *piecestore.PieceInfo
Status DealStatus
Receiver peer.ID
TotalSent uint64
FundsReceived abi.TokenAmount
Message string
CurrentInterval uint64
LegacyProtocol bool
}
// Identifier provides a unique id for this provider deal
func (pds ProviderDealState) Identifier() ProviderDealIdentifier {
return ProviderDealIdentifier{Receiver: pds.Receiver, DealID: pds.ID}
}
// ProviderDealIdentifier is a value that uniquely identifies a deal
type ProviderDealIdentifier struct {
Receiver peer.ID
DealID DealID
}
func (p ProviderDealIdentifier) String() string {
return fmt.Sprintf("%v/%v", p.Receiver, p.DealID)
}
// RetrievalPeer is a provider address/peer.ID pair (everything needed to make
// deals for with a miner)
type RetrievalPeer struct {
Address address.Address
ID peer.ID // optional
PieceCID *cid.Cid
}
// QueryResponseStatus indicates whether a queried piece is available
type QueryResponseStatus uint64
const (
// QueryResponseAvailable indicates a provider has a piece and is prepared to
// return it
QueryResponseAvailable QueryResponseStatus = iota
// QueryResponseUnavailable indicates a provider either does not have or cannot
// serve the queried piece to the client
QueryResponseUnavailable
// QueryResponseError indicates something went wrong generating a query response
QueryResponseError
)
// QueryItemStatus (V1) indicates whether the requested part of a piece (payload or selector)
// is available for retrieval
type QueryItemStatus uint64
const (
// QueryItemAvailable indicates requested part of the piece is available to be
// served
QueryItemAvailable QueryItemStatus = iota
// QueryItemUnavailable indicates the piece either does not contain the requested
// item or it cannot be served
QueryItemUnavailable
// QueryItemUnknown indicates the provider cannot determine if the given item
// is part of the requested piece (for example, if the piece is sealed and the
// miner does not maintain a payload CID index)
QueryItemUnknown
)
// QueryParams - V1 - indicate what specific information about a piece that a retrieval
// client is interested in, as well as specific parameters the client is seeking
// for the retrieval deal
type QueryParams struct {
PieceCID *cid.Cid // optional, query if miner has this cid in this piece. some miners may not be able to respond.
//Selector ipld.Node // optional, query if miner has this cid in this piece. some miners may not be able to respond.
//MaxPricePerByte abi.TokenAmount // optional, tell miner uninterested if more expensive than this
//MinPaymentInterval uint64 // optional, tell miner uninterested unless payment interval is greater than this
//MinPaymentIntervalIncrease uint64 // optional, tell miner uninterested unless payment interval increase is greater than this
}
// Query is a query to a given provider to determine information about a piece
// they may have available for retrieval
type Query struct {
PayloadCID cid.Cid // V0
QueryParams // V1
}
// QueryUndefined is a query with no values
var QueryUndefined = Query{}
// NewQueryV0 creates a V0 query (which only specifies a payload)
func NewQueryV0(payloadCID cid.Cid) Query {
return Query{PayloadCID: payloadCID}
}
// NewQueryV1 creates a V1 query (which has an optional pieceCID)
func NewQueryV1(payloadCID cid.Cid, pieceCID *cid.Cid) Query {
return Query{
PayloadCID: payloadCID,
QueryParams: QueryParams{
PieceCID: pieceCID,
},
}
}
// QueryResponse is a miners response to a given retrieval query
type QueryResponse struct {
Status QueryResponseStatus
PieceCIDFound QueryItemStatus // V1 - if a PieceCID was requested, the result
//SelectorFound QueryItemStatus // V1 - if a Selector was requested, the result
Size uint64 // Total size of piece in bytes
//ExpectedPayloadSize uint64 // V1 - optional, if PayloadCID + selector are specified and miner knows, can offer an expected size
PaymentAddress address.Address // address to send funds to -- may be different than miner addr
MinPricePerByte abi.TokenAmount
MaxPaymentInterval uint64
MaxPaymentIntervalIncrease uint64
Message string
UnsealPrice abi.TokenAmount
}
// QueryResponseUndefined is an empty QueryResponse
var QueryResponseUndefined = QueryResponse{}
// PieceRetrievalPrice is the total price to retrieve the piece (size * MinPricePerByte + UnsealedPrice)
func (qr QueryResponse) PieceRetrievalPrice() abi.TokenAmount {
return big.Add(big.Mul(qr.MinPricePerByte, abi.NewTokenAmount(int64(qr.Size))), qr.UnsealPrice)
}
// PayloadRetrievalPrice is the expected price to retrieve just the given payload
// & selector (V1)
//func (qr QueryResponse) PayloadRetrievalPrice() abi.TokenAmount {
// return types.BigMul(qr.MinPricePerByte, types.NewInt(qr.ExpectedPayloadSize))
//}
// IsTerminalError returns true if this status indicates processing of this deal
// is complete with an error
func IsTerminalError(status DealStatus) bool {
return status == DealStatusDealNotFound ||
status == DealStatusFailing ||
status == DealStatusRejected
}
// IsTerminalSuccess returns true if this status indicates processing of this deal
// is complete with a success
func IsTerminalSuccess(status DealStatus) bool {
return status == DealStatusCompleted
}
// IsTerminalStatus returns true if this status indicates processing of a deal is
// complete (either success or error)
func IsTerminalStatus(status DealStatus) bool {
return IsTerminalError(status) || IsTerminalSuccess(status)
}
// Params are the parameters requested for a retrieval deal proposal
type Params struct {
Selector *cbg.Deferred // V1
PieceCID *cid.Cid
PricePerByte abi.TokenAmount
PaymentInterval uint64 // when to request payment
PaymentIntervalIncrease uint64
UnsealPrice abi.TokenAmount
}
func (p Params) SelectorSpecified() bool {
return p.Selector != nil && !bytes.Equal(p.Selector.Raw, cbg.CborNull)
}
// NewParamsV0 generates parameters for a retrieval deal, which is always a whole piece deal
func NewParamsV0(pricePerByte abi.TokenAmount, paymentInterval uint64, paymentIntervalIncrease uint64) Params {
return Params{
PricePerByte: pricePerByte,
PaymentInterval: paymentInterval,
PaymentIntervalIncrease: paymentIntervalIncrease,
UnsealPrice: big.Zero(),
}
}
// NewParamsV1 generates parameters for a retrieval deal, including a selector
func NewParamsV1(pricePerByte abi.TokenAmount, paymentInterval uint64, paymentIntervalIncrease uint64, sel ipld.Node, pieceCid *cid.Cid, unsealPrice abi.TokenAmount) (Params, error) {
var buffer bytes.Buffer
if sel == nil {
return Params{}, xerrors.New("selector required for NewParamsV1")
}
err := dagcbor.Encoder(sel, &buffer)
if err != nil {
return Params{}, xerrors.Errorf("error encoding selector: %w", err)
}
return Params{
Selector: &cbg.Deferred{Raw: buffer.Bytes()},
PieceCID: pieceCid,
PricePerByte: pricePerByte,
PaymentInterval: paymentInterval,
PaymentIntervalIncrease: paymentIntervalIncrease,
UnsealPrice: unsealPrice,
}, nil
}
// DealID is an identifier for a retrieval deal (unique to a client)
type DealID uint64
func (d DealID) String() string {
return fmt.Sprintf("%d", d)
}
// DealProposal is a proposal for a new retrieval deal
type DealProposal struct {
PayloadCID cid.Cid
ID DealID
Params
}
// Type method makes DealProposal usable as a voucher
func (dp *DealProposal) Type() datatransfer.TypeIdentifier {
return "RetrievalDealProposal/1"
}
// DealProposalUndefined is an undefined deal proposal
var DealProposalUndefined = DealProposal{}
// DealResponse is a response to a retrieval deal proposal
type DealResponse struct {
Status DealStatus
ID DealID
// payment required to proceed
PaymentOwed abi.TokenAmount
Message string
}
// Type method makes DealResponse usable as a voucher result
func (dr *DealResponse) Type() datatransfer.TypeIdentifier {
return "RetrievalDealResponse/1"
}
// DealResponseUndefined is an undefined deal response
var DealResponseUndefined = DealResponse{}
// DealPayment is a payment for an in progress retrieval deal
type DealPayment struct {
ID DealID
PaymentChannel address.Address
PaymentVoucher *paych.SignedVoucher
}
// Type method makes DealPayment usable as a voucher
func (dr *DealPayment) Type() datatransfer.TypeIdentifier {
return "RetrievalDealPayment/1"
}
// DealPaymentUndefined is an undefined deal payment
var DealPaymentUndefined = DealPayment{}
var (
// ErrNotFound means a piece was not found during retrieval
ErrNotFound = errors.New("not found")
// ErrVerification means a retrieval contained a block response that did not verify
ErrVerification = errors.New("Error when verify data")
)
type Ask struct {
PricePerByte abi.TokenAmount
UnsealPrice abi.TokenAmount
PaymentInterval uint64
PaymentIntervalIncrease uint64
}
// ShortfallErorr is an error that indicates a short fall of funds
type ShortfallError struct {
shortfall abi.TokenAmount
}
// NewShortfallError returns a new error indicating a shortfall of funds
func NewShortfallError(shortfall abi.TokenAmount) error {
return ShortfallError{shortfall}
}
// Shortfall returns the numerical value of the shortfall
func (se ShortfallError) Shortfall() abi.TokenAmount {
return se.shortfall
}
func (se ShortfallError) Error() string {
return fmt.Sprintf("Inssufficient Funds. Shortfall: %s", se.shortfall.String())
}
// ChannelAvailableFunds provides information about funds in a channel
type ChannelAvailableFunds struct {
// ConfirmedAmt is the amount of funds that have been confirmed on-chain
// for the channel
ConfirmedAmt abi.TokenAmount
// PendingAmt is the amount of funds that are pending confirmation on-chain
PendingAmt abi.TokenAmount
// PendingWaitSentinel can be used with PaychGetWaitReady to wait for
// confirmation of pending funds
PendingWaitSentinel *cid.Cid
// QueuedAmt is the amount that is queued up behind a pending request
QueuedAmt abi.TokenAmount
// VoucherRedeemedAmt is the amount that is redeemed by vouchers on-chain
// and in the local datastore
VoucherReedeemedAmt abi.TokenAmount
}
// PricingInput provides input parameters required to price a retrieval deal.
type PricingInput struct {
// PayloadCID is the cid of the payload to retrieve.
PayloadCID cid.Cid
// PieceCID is the cid of the Piece from which the Payload will be retrieved.
PieceCID cid.Cid
// PieceSize is the size of the Piece from which the payload will be retrieved.
PieceSize abi.UnpaddedPieceSize
// Client is the peerID of the retrieval client.
Client peer.ID
// VerifiedDeal is true if there exists a verified storage deal for the PayloadCID.
VerifiedDeal bool
// Unsealed is true if there exists an unsealed sector from which we can retrieve the given payload.
Unsealed bool
// CurrentAsk is the current configured ask in the ask-store.
CurrentAsk Ask
}