forked from filecoin-project/boost
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeal_acceptance.go
165 lines (132 loc) · 5.73 KB
/
deal_acceptance.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
package storagemarket
import (
"errors"
"fmt"
"github.com/filecoin-project/boost/storagemarket/types"
"github.com/filecoin-project/go-fil-markets/shared"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market"
)
const DealMaxLabelSize = 256
// ValidateDealProposal validates a proposed deal against the provider criteria
func (p *Provider) validateDealProposal(deal types.ProviderDealState) error {
tok, curEpoch, err := p.adapter.GetChainHead(p.ctx)
if err != nil {
return fmt.Errorf("node error getting most recent state id: %w", err)
}
if err := p.validateSignature(tok, deal); err != nil {
return fmt.Errorf("validateSignature failed: %w", err)
}
// validate deal proposal
proposal := deal.ClientDealProposal.Proposal
if proposal.Provider != p.Address {
return fmt.Errorf("incorrect provider for deal")
}
if len(proposal.Label) > DealMaxLabelSize {
return fmt.Errorf("deal label can be at most %d bytes, is %d", DealMaxLabelSize, len(proposal.Label))
}
if err := proposal.PieceSize.Validate(); err != nil {
return fmt.Errorf("proposal piece size is invalid: %w", err)
}
if !proposal.PieceCID.Defined() {
return fmt.Errorf("proposal PieceCID undefined")
}
if proposal.PieceCID.Prefix() != market.PieceCIDPrefix {
return fmt.Errorf("proposal PieceCID had wrong prefix")
}
if proposal.EndEpoch <= proposal.StartEpoch {
return fmt.Errorf("proposal end before proposal start")
}
if curEpoch > proposal.StartEpoch {
return fmt.Errorf("deal start epoch has already elapsed")
}
// Check that the delta between the start and end epochs (the deal
// duration) is within acceptable bounds
minDuration, maxDuration := market2.DealDurationBounds(proposal.PieceSize)
if proposal.Duration() < minDuration || proposal.Duration() > maxDuration {
return fmt.Errorf("deal duration out of bounds (min, max, provided): %d, %d, %d", minDuration, maxDuration, proposal.Duration())
}
// Check that the proposed end epoch isn't too far beyond the current epoch
maxEndEpoch := curEpoch + miner.MaxSectorExpirationExtension
if proposal.EndEpoch > maxEndEpoch {
return fmt.Errorf("invalid deal end epoch %d: cannot be more than %d past current epoch %d", proposal.EndEpoch, miner.MaxSectorExpirationExtension, curEpoch)
}
pcMin, pcMax, err := p.adapter.DealProviderCollateralBounds(p.ctx, proposal.PieceSize, proposal.VerifiedDeal)
if err != nil {
return fmt.Errorf("node error getting collateral bounds: %w", err)
}
if proposal.ProviderCollateral.LessThan(pcMin) {
return fmt.Errorf("proposed provider collateral below minimum: %s < %s", proposal.ProviderCollateral, pcMin)
}
if proposal.ProviderCollateral.GreaterThan(pcMax) {
return fmt.Errorf("proposed provider collateral above maximum: %s > %s", proposal.ProviderCollateral, pcMax)
}
if err := p.validateAsk(deal); err != nil {
return fmt.Errorf("validateAsk failed: %w", err)
}
// TODO: Uncomment when client has been implemented
//// check market funds
//clientMarketBalance, err := p.adapter.GetBalance(p.ctx, proposal.Client, tok)
//if err != nil {
// return fmt.Errorf("node error 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(proposal.ClientBalanceRequirement()) {
// return fmt.Errorf("clientMarketBalance.Available too small: %d < %d", clientMarketBalance.Available, proposal.ClientBalanceRequirement())
//}
// Verified deal checks
if proposal.VerifiedDeal {
dataCap, err := p.adapter.GetDataCap(p.ctx, proposal.Client, tok)
if err != nil {
return fmt.Errorf("node error fetching verified data cap: %w", err)
}
if dataCap == nil {
return errors.New("node error fetching verified data cap: data cap missing -- client not verified")
}
pieceSize := big.NewIntUnsigned(uint64(proposal.PieceSize))
if dataCap.LessThan(pieceSize) {
return errors.New("verified deal DataCap too small for proposed piece size")
}
}
return nil
}
func (p *Provider) validateAsk(deal types.ProviderDealState) error {
ask := p.GetAsk()
askPrice := ask.Price
if deal.ClientDealProposal.Proposal.VerifiedDeal {
askPrice = ask.VerifiedPrice
}
proposal := deal.ClientDealProposal.Proposal
minPrice := big.Div(big.Mul(askPrice, abi.NewTokenAmount(int64(proposal.PieceSize))), abi.NewTokenAmount(1<<30))
if proposal.StoragePricePerEpoch.LessThan(minPrice) {
return fmt.Errorf("storage price per epoch less than asking price: %s < %s", proposal.StoragePricePerEpoch, minPrice)
}
if proposal.PieceSize < ask.MinPieceSize {
return fmt.Errorf("piece size less than minimum required size: %d < %d", proposal.PieceSize, ask.MinPieceSize)
}
if proposal.PieceSize > ask.MaxPieceSize {
return fmt.Errorf("piece size more than maximum allowed size: %d > %d", proposal.PieceSize, ask.MaxPieceSize)
}
return nil
}
func (p *Provider) validateSignature(tok shared.TipSetToken, deal types.ProviderDealState) error {
// TODO: do proper signature validation once the client side of deal making is set up
return nil
//b, err := cborutil.Dump(&deal.ClientDealProposal.Proposal)
//if err != nil {
//return fmt.Errorf("failed to serialize client deal proposal: %w", err)
//}
//verified, err := p.adapter.VerifySignature(p.ctx, deal.ClientDealProposal.ClientSignature, deal.ClientDealProposal.Proposal.Client, b, tok)
//if err != nil {
//return fmt.Errorf("error verifying signature: %w", err)
//}
//if !verified {
//return errors.New("could not verify signature")
//}
//return nil
}