2019-12-10 04:19:59 +00:00
|
|
|
package retrievaladapter
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2020-09-01 14:33:44 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
|
|
|
2019-12-17 03:17:46 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
2020-01-10 17:13:12 +00:00
|
|
|
"github.com/filecoin-project/go-fil-markets/retrievalmarket"
|
2020-03-18 17:44:54 +00:00
|
|
|
"github.com/filecoin-project/go-fil-markets/shared"
|
2020-09-07 03:49:10 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
2020-04-17 00:25:06 +00:00
|
|
|
"github.com/ipfs/go-cid"
|
2020-08-05 22:35:59 +00:00
|
|
|
"github.com/multiformats/go-multiaddr"
|
2020-03-18 17:44:54 +00:00
|
|
|
|
2020-08-05 22:35:59 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-03-18 17:44:54 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/impl/full"
|
|
|
|
payapi "github.com/filecoin-project/lotus/node/impl/paych"
|
2019-12-10 04:19:59 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type retrievalClientNode struct {
|
2020-08-05 22:35:59 +00:00
|
|
|
chainAPI full.ChainAPI
|
|
|
|
payAPI payapi.PaychAPI
|
|
|
|
stateAPI full.StateAPI
|
2019-12-10 04:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewRetrievalClientNode returns a new node adapter for a retrieval client that talks to the
|
|
|
|
// Lotus Node
|
2020-09-04 05:34:59 +00:00
|
|
|
func NewRetrievalClientNode(payAPI payapi.PaychAPI, chainAPI full.ChainAPI, stateAPI full.StateAPI) retrievalmarket.RetrievalClientNode {
|
|
|
|
return &retrievalClientNode{payAPI: payAPI, chainAPI: chainAPI, stateAPI: stateAPI}
|
2019-12-10 04:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetOrCreatePaymentChannel sets up a new payment channel if one does not exist
|
2020-03-18 17:44:54 +00:00
|
|
|
// between a client and a miner and ensures the client has the given amount of
|
|
|
|
// funds available in the channel.
|
2020-04-17 00:25:06 +00:00
|
|
|
func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, clientAddress address.Address, minerAddress address.Address, clientFundsAvailable abi.TokenAmount, tok shared.TipSetToken) (address.Address, cid.Cid, error) {
|
2020-03-18 17:44:54 +00:00
|
|
|
// TODO: respect the provided TipSetToken (a serialized TipSetKey) when
|
|
|
|
// querying the chain
|
2020-09-04 05:34:59 +00:00
|
|
|
ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable)
|
|
|
|
if err != nil {
|
|
|
|
return address.Undef, cid.Undef, err
|
|
|
|
}
|
|
|
|
return ci.Channel, ci.WaitSentinel, nil
|
2019-12-10 04:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate late creates a lane within a payment channel so that calls to
|
|
|
|
// CreatePaymentVoucher will automatically make vouchers only for the difference
|
|
|
|
// in total
|
2020-09-04 05:34:59 +00:00
|
|
|
func (rcn *retrievalClientNode) AllocateLane(ctx context.Context, paymentChannel address.Address) (uint64, error) {
|
|
|
|
return rcn.payAPI.PaychAllocateLane(ctx, paymentChannel)
|
2019-12-10 04:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
2020-03-18 17:44:54 +00:00
|
|
|
func (rcn *retrievalClientNode) CreatePaymentVoucher(ctx context.Context, paymentChannel address.Address, amount abi.TokenAmount, lane uint64, tok shared.TipSetToken) (*paych.SignedVoucher, error) {
|
|
|
|
// TODO: respect the provided TipSetToken (a serialized TipSetKey) when
|
|
|
|
// querying the chain
|
2020-08-05 22:35:59 +00:00
|
|
|
voucher, err := rcn.payAPI.PaychVoucherCreate(ctx, paymentChannel, amount, lane)
|
2019-12-17 03:17:46 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-09-01 14:33:44 +00:00
|
|
|
if voucher.Voucher == nil {
|
2020-09-04 05:34:59 +00:00
|
|
|
return nil, retrievalmarket.NewShortfallError(voucher.Shortfall)
|
2020-09-01 14:33:44 +00:00
|
|
|
}
|
|
|
|
return voucher.Voucher, nil
|
2019-12-10 04:19:59 +00:00
|
|
|
}
|
2020-03-18 17:44:54 +00:00
|
|
|
|
|
|
|
func (rcn *retrievalClientNode) GetChainHead(ctx context.Context) (shared.TipSetToken, abi.ChainEpoch, error) {
|
2020-08-05 22:35:59 +00:00
|
|
|
head, err := rcn.chainAPI.ChainHead(ctx)
|
2020-03-18 17:44:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return head.Key().Bytes(), head.Height(), nil
|
|
|
|
}
|
2020-04-17 00:25:06 +00:00
|
|
|
|
2020-09-04 05:34:59 +00:00
|
|
|
func (rcn *retrievalClientNode) WaitForPaymentChannelReady(ctx context.Context, messageCID cid.Cid) (address.Address, error) {
|
|
|
|
return rcn.payAPI.PaychGetWaitReady(ctx, messageCID)
|
2020-04-17 00:25:06 +00:00
|
|
|
}
|
|
|
|
|
2020-09-04 05:34:59 +00:00
|
|
|
func (rcn *retrievalClientNode) CheckAvailableFunds(ctx context.Context, paymentChannel address.Address) (retrievalmarket.ChannelAvailableFunds, error) {
|
2020-09-07 12:33:35 +00:00
|
|
|
|
2020-09-11 22:52:09 +00:00
|
|
|
channelAvailableFunds, err := rcn.payAPI.PaychAvailableFunds(ctx, paymentChannel)
|
2020-09-04 05:34:59 +00:00
|
|
|
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
|
2020-04-17 00:25:06 +00:00
|
|
|
}
|
2020-08-05 22:35:59 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|