-
Notifications
You must be signed in to change notification settings - Fork 63
/
client.go
127 lines (109 loc) · 4.69 KB
/
client.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
package retrievaladapter
import (
"context"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multiaddr"
"github.com/filecoin-project/boost-gfm/retrievalmarket"
"github.com/filecoin-project/boost-gfm/shared"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/impl/full"
payapi "github.com/filecoin-project/lotus/node/impl/paych"
)
type retrievalClientNode struct {
forceOffChain bool
chainAPI full.ChainAPI
payAPI payapi.PaychAPI
stateAPI full.StateAPI
}
// NewRetrievalClientNode returns a new node adapter for a retrieval client that talks to the
// Lotus Node
func NewRetrievalClientNode(forceOffChain bool, payAPI payapi.PaychAPI, chainAPI full.ChainAPI, stateAPI full.StateAPI) retrievalmarket.RetrievalClientNode {
return &retrievalClientNode{
forceOffChain: forceOffChain,
chainAPI: chainAPI,
payAPI: payAPI,
stateAPI: stateAPI,
}
}
// GetOrCreatePaymentChannel sets up a new payment channel if one does not exist
// between a client and a miner and ensures 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 abi.TokenAmount, tok shared.TipSetToken) (address.Address, cid.Cid, error) {
// TODO: respect the provided TipSetToken (a serialized TipSetKey) when
// querying the chain
ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable, api.PaychGetOpts{
OffChain: rcn.forceOffChain,
})
if err != nil {
log.Errorw("paych get failed", "error", err)
return address.Undef, cid.Undef, err
}
return ci.Channel, ci.WaitSentinel, nil
}
// Allocate late creates a lane within a payment channel so that calls to
// CreatePaymentVoucher will automatically make vouchers only for the difference
// in total
func (rcn *retrievalClientNode) AllocateLane(ctx context.Context, paymentChannel address.Address) (uint64, error) {
return rcn.payAPI.PaychAllocateLane(ctx, paymentChannel)
}
// CreatePaymentVoucher creates a new payment voucher in the given lane for a
// 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)
func (rcn *retrievalClientNode) CreatePaymentVoucher(ctx context.Context, paymentChannel address.Address, amount abi.TokenAmount, lane uint64, tok shared.TipSetToken) (*paychtypes.SignedVoucher, error) {
// TODO: respect the provided TipSetToken (a serialized TipSetKey) when
// querying the chain
voucher, err := rcn.payAPI.PaychVoucherCreate(ctx, paymentChannel, amount, lane)
if err != nil {
return nil, err
}
if voucher.Voucher == nil {
return nil, retrievalmarket.NewShortfallError(voucher.Shortfall)
}
return voucher.Voucher, nil
}
func (rcn *retrievalClientNode) GetChainHead(ctx context.Context) (shared.TipSetToken, abi.ChainEpoch, error) {
head, err := rcn.chainAPI.ChainHead(ctx)
if err != nil {
return nil, 0, err
}
return head.Key().Bytes(), head.Height(), nil
}
func (rcn *retrievalClientNode) WaitForPaymentChannelReady(ctx context.Context, messageCID cid.Cid) (address.Address, error) {
return rcn.payAPI.PaychGetWaitReady(ctx, messageCID)
}
func (rcn *retrievalClientNode) CheckAvailableFunds(ctx context.Context, paymentChannel address.Address) (retrievalmarket.ChannelAvailableFunds, error) {
channelAvailableFunds, err := rcn.payAPI.PaychAvailableFunds(ctx, paymentChannel)
if err != nil {
return retrievalmarket.ChannelAvailableFunds{}, err
}
return retrievalmarket.ChannelAvailableFunds{
ConfirmedAmt: channelAvailableFunds.ConfirmedAmt,
PendingAmt: channelAvailableFunds.PendingAmt,
PendingWaitSentinel: channelAvailableFunds.PendingWaitSentinel,
QueuedAmt: channelAvailableFunds.QueuedAmt,
VoucherReedeemedAmt: channelAvailableFunds.VoucherReedeemedAmt,
}, nil
}
func (rcn *retrievalClientNode) GetKnownAddresses(ctx context.Context, p retrievalmarket.RetrievalPeer, encodedTs shared.TipSetToken) ([]multiaddr.Multiaddr, error) {
tsk, err := types.TipSetKeyFromBytes(encodedTs)
if err != nil {
return nil, err
}
mi, err := rcn.stateAPI.StateMinerInfo(ctx, p.Address, tsk)
if err != nil {
return nil, err
}
multiaddrs := make([]multiaddr.Multiaddr, 0, len(mi.Multiaddrs))
for _, a := range mi.Multiaddrs {
maddr, err := multiaddr.NewMultiaddrBytes(a)
if err != nil {
return nil, err
}
multiaddrs = append(multiaddrs, maddr)
}
return multiaddrs, nil
}