From 72cb130e1777e83c51f781ae77a5fd77e1bf31a8 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Tue, 8 Dec 2020 15:18:47 +0100 Subject: [PATCH] feat: show data transfer ID in list-deals --- api/api_full.go | 3 + cli/client.go | 36 +++++++++- cmd/lotus-storage-miner/market.go | 7 +- documentation/en/api-methods.md | 40 ++++++++++- go.mod | 4 +- go.sum | 8 +-- node/impl/client/client.go | 112 ++++++++++++++++++------------ 7 files changed, 152 insertions(+), 58 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 4cda4716260..b91ecd3e79b 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -594,6 +594,9 @@ type DealInfo struct { CreationTime time.Time Verified bool + + TransferChannelID *datatransfer.ChannelID + DataTransfer *DataTransferChannel } type MsgLookup struct { diff --git a/cli/client.go b/cli/client.go index c3cde8bc39d..0dc117eeb17 100644 --- a/cli/client.go +++ b/cli/client.go @@ -1524,7 +1524,7 @@ var clientListDeals = &cli.Command{ } } - return outputStorageDeals(ctx, cctx.App.Writer, api, localDeals, cctx.Bool("verbose"), cctx.Bool("color"), showFailed) + return outputStorageDeals(ctx, cctx.App.Writer, api, localDeals, verbose, color, showFailed) }, } @@ -1566,7 +1566,7 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full lapi.FullNode, if verbose { w := tabwriter.NewWriter(out, 2, 4, 2, ' ', 0) - fmt.Fprintf(w, "Created\tDealCid\tDealId\tProvider\tState\tOn Chain?\tSlashed?\tPieceCID\tSize\tPrice\tDuration\tVerified\tMessage\n") + fmt.Fprintf(w, "Created\tDealCid\tDealId\tProvider\tState\tOn Chain?\tSlashed?\tPieceCID\tSize\tPrice\tDuration\tTransferChannelID\tTransferStatus\tVerified\tMessage\n") for _, d := range deals { onChain := "N" if d.OnChainDealState.SectorStartEpoch != -1 { @@ -1579,7 +1579,37 @@ func outputStorageDeals(ctx context.Context, out io.Writer, full lapi.FullNode, } price := types.FIL(types.BigMul(d.LocalDeal.PricePerEpoch, types.NewInt(d.LocalDeal.Duration))) - fmt.Fprintf(w, "%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%v\t%s\n", d.LocalDeal.CreationTime.Format(time.Stamp), d.LocalDeal.ProposalCid, d.LocalDeal.DealID, d.LocalDeal.Provider, dealStateString(color, d.LocalDeal.State), onChain, slashed, d.LocalDeal.PieceCID, types.SizeStr(types.NewInt(d.LocalDeal.Size)), price, d.LocalDeal.Duration, d.LocalDeal.Verified, d.LocalDeal.Message) + transferChannelID := "" + if d.LocalDeal.TransferChannelID != nil { + transferChannelID = d.LocalDeal.TransferChannelID.String() + } + transferStatus := "" + if d.LocalDeal.DataTransfer != nil { + transferStatus = datatransfer.Statuses[d.LocalDeal.DataTransfer.Status] + // TODO: Include the transferred percentage once this bug is fixed: + // https://github.com/ipfs/go-graphsync/issues/126 + //fmt.Printf("transferred: %d / size: %d\n", d.LocalDeal.DataTransfer.Transferred, d.LocalDeal.Size) + //if d.LocalDeal.Size > 0 { + // pct := (100 * d.LocalDeal.DataTransfer.Transferred) / d.LocalDeal.Size + // transferPct = fmt.Sprintf("%d%%", pct) + //} + } + fmt.Fprintf(w, "%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%s\t%s\t%v\t%s\n", + d.LocalDeal.CreationTime.Format(time.Stamp), + d.LocalDeal.ProposalCid, + d.LocalDeal.DealID, + d.LocalDeal.Provider, + dealStateString(color, d.LocalDeal.State), + onChain, + slashed, + d.LocalDeal.PieceCID, + types.SizeStr(types.NewInt(d.LocalDeal.Size)), + price, + d.LocalDeal.Duration, + transferChannelID, + transferStatus, + d.LocalDeal.Verified, + d.LocalDeal.Message) } return w.Flush() } diff --git a/cmd/lotus-storage-miner/market.go b/cmd/lotus-storage-miner/market.go index 15a3c8b649d..f7c49d54419 100644 --- a/cmd/lotus-storage-miner/market.go +++ b/cmd/lotus-storage-miner/market.go @@ -421,7 +421,7 @@ func outputStorageDeals(out io.Writer, deals []storagemarket.MinerDeal, verbose w := tabwriter.NewWriter(out, 2, 4, 2, ' ', 0) if verbose { - _, _ = fmt.Fprintf(w, "Creation\tProposalCid\tDealId\tState\tClient\tSize\tPrice\tDuration\tMessage\n") + _, _ = fmt.Fprintf(w, "Creation\tProposalCid\tDealId\tState\tClient\tSize\tPrice\tDuration\tTransferChannelID\tMessage\n") } else { _, _ = fmt.Fprintf(w, "ProposalCid\tDealId\tState\tClient\tSize\tPrice\tDuration\n") } @@ -440,6 +440,11 @@ func outputStorageDeals(out io.Writer, deals []storagemarket.MinerDeal, verbose _, _ = fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\t%s", propcid, deal.DealID, storagemarket.DealStates[deal.State], deal.Proposal.Client, units.BytesSize(float64(deal.Proposal.PieceSize)), fil, deal.Proposal.Duration()) if verbose { + tchid := "" + if deal.TransferChannelId != nil { + tchid = deal.TransferChannelId.String() + } + _, _ = fmt.Fprintf(w, "\t%s", tchid) _, _ = fmt.Fprintf(w, "\t%s", deal.Message) } diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 5ddaddb350e..9f46460f105 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -1034,7 +1034,25 @@ Response: "Duration": 42, "DealID": 5432, "CreationTime": "0001-01-01T00:00:00Z", - "Verified": true + "Verified": true, + "TransferChannelID": { + "Initiator": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + "Responder": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + "ID": 3 + }, + "DataTransfer": { + "TransferID": 3, + "Status": 1, + "BaseCID": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "IsInitiator": true, + "IsSender": true, + "Voucher": "string value", + "Message": "string value", + "OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + "Transferred": 42 + } } ``` @@ -1086,7 +1104,25 @@ Response: "Duration": 42, "DealID": 5432, "CreationTime": "0001-01-01T00:00:00Z", - "Verified": true + "Verified": true, + "TransferChannelID": { + "Initiator": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + "Responder": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + "ID": 3 + }, + "DataTransfer": { + "TransferID": 3, + "Status": 1, + "BaseCID": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "IsInitiator": true, + "IsSender": true, + "Voucher": "string value", + "Message": "string value", + "OtherPeer": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf", + "Transferred": 42 + } } ``` diff --git a/go.mod b/go.mod index 801042f71f4..e6bc14a1bc7 100644 --- a/go.mod +++ b/go.mod @@ -31,9 +31,9 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v1.2.2 + github.com/filecoin-project/go-data-transfer v1.2.3 github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a - github.com/filecoin-project/go-fil-markets v1.0.9 + github.com/filecoin-project/go-fil-markets v1.0.10 github.com/filecoin-project/go-jsonrpc v0.1.2 github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 diff --git a/go.sum b/go.sum index 3d8dad54bde..644904013cf 100644 --- a/go.sum +++ b/go.sum @@ -255,8 +255,8 @@ github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMX github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1 h1:5sYKDbstyDsdJpVP4UGUW6+BgCNfgnH8hQgf0E3ZAno= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.2.2 h1:zBeUNqSXgYbHqyl3mnwQU5GdOM1h0ecbqc6yvqmHsCQ= -github.com/filecoin-project/go-data-transfer v1.2.2/go.mod h1:ZAH51JZFR8NZC4FPiDPG+swjgui0q6zTMJbztc6pHhY= +github.com/filecoin-project/go-data-transfer v1.2.3 h1:rM/HgGOOMsKvmeQjY7CVR3v7Orxf04LJSSczSpGlhg4= +github.com/filecoin-project/go-data-transfer v1.2.3/go.mod h1:ZAH51JZFR8NZC4FPiDPG+swjgui0q6zTMJbztc6pHhY= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s= @@ -264,8 +264,8 @@ github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a h1:hyJ+pUm/4U4RdEZBlg6k8Ma4rDiuvqyGpoICXAxwsTg= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.0.9 h1:bGWo6xoXV9zMPYgbplQDtUREogDuKPiSY1CYwxV5cOY= -github.com/filecoin-project/go-fil-markets v1.0.9/go.mod h1:uOikzYK7aNbSWMczCp6Ru257ML4PplLRBfDk/NAOgaY= +github.com/filecoin-project/go-fil-markets v1.0.10 h1:1QunPsgApTLNXVlaXoPMxyrMtOsMLPOQq3RUjGRmgVI= +github.com/filecoin-project/go-fil-markets v1.0.10/go.mod h1:tcXby9CsTNuHu19dH05YZ5pNDsoYcQXSrbkxzVeMJrY= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 7ecdbc86941..e90a31a80c9 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -184,55 +184,57 @@ func (a *API) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) { return nil, err } + // Get a map of transfer ID => DataTransfer + dataTransfersByID, err := a.transfersByID(ctx) + if err != nil { + return nil, err + } + out := make([]api.DealInfo, len(deals)) for k, v := range deals { - out[k] = api.DealInfo{ - ProposalCid: v.ProposalCid, - DataRef: v.DataRef, - State: v.State, - Message: v.Message, - Provider: v.Proposal.Provider, - - PieceCID: v.Proposal.PieceCID, - Size: uint64(v.Proposal.PieceSize.Unpadded()), - - PricePerEpoch: v.Proposal.StoragePricePerEpoch, - Duration: uint64(v.Proposal.Duration()), - DealID: v.DealID, - CreationTime: v.CreationTime.Time(), - Verified: v.Proposal.VerifiedDeal, + // Find the data transfer associated with this deal + var transferCh *api.DataTransferChannel + if v.TransferChannelID != nil { + if ch, ok := dataTransfersByID[*v.TransferChannelID]; ok { + transferCh = &ch + } } + + out[k] = a.newDealInfoWithTransfer(transferCh, v) } return out, nil } +func (a *API) transfersByID(ctx context.Context) (map[datatransfer.ChannelID]api.DataTransferChannel, error) { + inProgressChannels, err := a.DataTransfer.InProgressChannels(ctx) + if err != nil { + return nil, err + } + + dataTransfersByID := make(map[datatransfer.ChannelID]api.DataTransferChannel, len(inProgressChannels)) + for id, channelState := range inProgressChannels { + ch := api.NewDataTransferChannel(a.Host.ID(), channelState) + dataTransfersByID[id] = ch + } + return dataTransfersByID, nil +} + func (a *API) ClientGetDealInfo(ctx context.Context, d cid.Cid) (*api.DealInfo, error) { v, err := a.SMDealClient.GetLocalDeal(ctx, d) if err != nil { return nil, err } - return &api.DealInfo{ - ProposalCid: v.ProposalCid, - State: v.State, - Message: v.Message, - Provider: v.Proposal.Provider, - PieceCID: v.Proposal.PieceCID, - Size: uint64(v.Proposal.PieceSize.Unpadded()), - PricePerEpoch: v.Proposal.StoragePricePerEpoch, - Duration: uint64(v.Proposal.Duration()), - DealID: v.DealID, - CreationTime: v.CreationTime.Time(), - Verified: v.Proposal.VerifiedDeal, - }, nil + di := a.newDealInfo(ctx, v) + return &di, nil } func (a *API) ClientGetDealUpdates(ctx context.Context) (<-chan api.DealInfo, error) { updates := make(chan api.DealInfo) unsub := a.SMDealClient.SubscribeToEvents(func(_ storagemarket.ClientEvent, deal storagemarket.ClientDeal) { - updates <- newDealInfo(deal) + updates <- a.newDealInfo(ctx, deal) }) go func() { @@ -243,6 +245,41 @@ func (a *API) ClientGetDealUpdates(ctx context.Context) (<-chan api.DealInfo, er return updates, nil } +func (a *API) newDealInfo(ctx context.Context, v storagemarket.ClientDeal) api.DealInfo { + // Find the data transfer associated with this deal + var transferCh *api.DataTransferChannel + if v.TransferChannelID != nil { + state, err := a.DataTransfer.ChannelState(ctx, *v.TransferChannelID) + + // Note: If there was an error just ignore it, as the data transfer may + // be not found if it's no longer active + if err == nil { + ch := api.NewDataTransferChannel(a.Host.ID(), state) + transferCh = &ch + } + } + return a.newDealInfoWithTransfer(transferCh, v) +} + +func (a *API) newDealInfoWithTransfer(transferCh *api.DataTransferChannel, v storagemarket.ClientDeal) api.DealInfo { + return api.DealInfo{ + ProposalCid: v.ProposalCid, + DataRef: v.DataRef, + State: v.State, + Message: v.Message, + Provider: v.Proposal.Provider, + PieceCID: v.Proposal.PieceCID, + Size: uint64(v.Proposal.PieceSize.Unpadded()), + PricePerEpoch: v.Proposal.StoragePricePerEpoch, + Duration: uint64(v.Proposal.Duration()), + DealID: v.DealID, + CreationTime: v.CreationTime.Time(), + Verified: v.Proposal.VerifiedDeal, + TransferChannelID: v.TransferChannelID, + DataTransfer: transferCh, + } +} + func (a *API) ClientHasLocal(ctx context.Context, root cid.Cid) (bool, error) { // TODO: check if we have the ENTIRE dag @@ -876,23 +913,6 @@ func (a *API) ClientCancelDataTransfer(ctx context.Context, transferID datatrans return a.DataTransfer.CloseDataTransferChannel(ctx, datatransfer.ChannelID{Initiator: otherPeer, Responder: selfPeer, ID: transferID}) } -func newDealInfo(v storagemarket.ClientDeal) api.DealInfo { - return api.DealInfo{ - ProposalCid: v.ProposalCid, - DataRef: v.DataRef, - State: v.State, - Message: v.Message, - Provider: v.Proposal.Provider, - PieceCID: v.Proposal.PieceCID, - Size: uint64(v.Proposal.PieceSize.Unpadded()), - PricePerEpoch: v.Proposal.StoragePricePerEpoch, - Duration: uint64(v.Proposal.Duration()), - DealID: v.DealID, - CreationTime: v.CreationTime.Time(), - Verified: v.Proposal.VerifiedDeal, - } -} - func (a *API) ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error { return a.Retrieval.TryRestartInsufficientFunds(paymentChannel) }