From 1de66af50aada5f2f887629c16f61f06d6072c2d Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 4 Mar 2021 12:10:17 +0100 Subject: [PATCH 01/18] Add DealStages field to track and keep history of lifecycle of deal --- storagemarket/dealstatus.go | 67 +++ storagemarket/impl/client.go | 1 + storagemarket/impl/clientstates/client_fsm.go | 56 +- storagemarket/types.go | 79 ++- storagemarket/types_cbor_gen.go | 525 +++++++++++++++++- 5 files changed, 722 insertions(+), 6 deletions(-) diff --git a/storagemarket/dealstatus.go b/storagemarket/dealstatus.go index dc10de7a..8aa0b1fc 100644 --- a/storagemarket/dealstatus.go +++ b/storagemarket/dealstatus.go @@ -141,3 +141,70 @@ var DealStates = map[StorageDealStatus]string{ StorageDealClientTransferRestart: "StorageDealClientTransferRestart", StorageDealProviderTransferAwaitRestart: "StorageDealProviderTransferAwaitRestart", } + +// DealStatesDescriptions maps StorageDealStatus codes to string description for better UX +var DealStatesDescriptions = map[StorageDealStatus]string{ + StorageDealUnknown: "Unknown", + StorageDealProposalNotFound: "Proposal not found", + StorageDealProposalRejected: "Proposal rejected", + StorageDealProposalAccepted: "Proposal accepted", + StorageDealAcceptWait: "AcceptWait", + StorageDealStartDataTransfer: "Starting data transfer", + StorageDealStaged: "Staged", + StorageDealAwaitingPreCommit: "Awaiting a PreCommit message on chain", + StorageDealSealing: "Sealing", + StorageDealActive: "Active", + StorageDealExpired: "Expired", + StorageDealSlashed: "Slashed", + StorageDealRejecting: "Rejecting", + StorageDealFailing: "Failing", + StorageDealFundsReserved: "FundsReserved", + StorageDealCheckForAcceptance: "Checking for deal acceptance", + StorageDealValidating: "Validating", + StorageDealTransferring: "Transferring", + StorageDealWaitingForData: "Waiting for data", + StorageDealVerifyData: "Verifying data", + StorageDealReserveProviderFunds: "Reserving provider funds", + StorageDealReserveClientFunds: "Reserving client funds", + StorageDealProviderFunding: "Provider funding", + StorageDealClientFunding: "Client funding", + StorageDealPublish: "Publish", + StorageDealPublishing: "Publishing", + StorageDealError: "Error", + StorageDealFinalizing: "Finalizing", + StorageDealClientTransferRestart: "Client transfer restart", + StorageDealProviderTransferAwaitRestart: "ProviderTransferAwaitRestart", +} + +var DealStatesDurations = map[StorageDealStatus]string{ + StorageDealUnknown: "", + StorageDealProposalNotFound: "", + StorageDealProposalRejected: "", + StorageDealProposalAccepted: "a few minutes", + StorageDealAcceptWait: "a few minutes", + StorageDealStartDataTransfer: "a few minutes", + StorageDealStaged: "a few minutes", + StorageDealAwaitingPreCommit: "a few minutes", + StorageDealSealing: "a few hours", + StorageDealActive: "", + StorageDealExpired: "", + StorageDealSlashed: "", + StorageDealRejecting: "", + StorageDealFailing: "", + StorageDealFundsReserved: "a few minutes", + StorageDealCheckForAcceptance: "a few minutes", + StorageDealValidating: "a few minutes", + StorageDealTransferring: "a few minutes", + StorageDealWaitingForData: "a few minutes", + StorageDealVerifyData: "a few minutes", + StorageDealReserveProviderFunds: "a few minutes", + StorageDealReserveClientFunds: "a few minutes", + StorageDealProviderFunding: "a few minutes", + StorageDealClientFunding: "a few minutes", + StorageDealPublish: "a few minutes", + StorageDealPublishing: "a few minutes", + StorageDealError: "", + StorageDealFinalizing: "a few minutes", + StorageDealClientTransferRestart: "depending on data size, anywhere between a few minutes to a few hours", + StorageDealProviderTransferAwaitRestart: "a few minutes", +} diff --git a/storagemarket/impl/client.go b/storagemarket/impl/client.go index c3ff4e6c..da2b45e2 100644 --- a/storagemarket/impl/client.go +++ b/storagemarket/impl/client.go @@ -388,6 +388,7 @@ func (c *Client) ProposeStorageDeal(ctx context.Context, params storagemarket.Pr DataRef: params.Data, FastRetrieval: params.FastRetrieval, StoreID: params.StoreID, + DealStages: storagemarket.NewDealStages(), CreationTime: curTime(), } diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index d124bf0a..be3002e9 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -22,12 +22,14 @@ var ClientEvents = fsm.Events{ From(storagemarket.StorageDealReserveClientFunds).To(storagemarket.StorageDealClientFunding). Action(func(deal *storagemarket.ClientDeal, mcid cid.Cid) error { deal.AddFundsCid = &mcid + deal.AddLog("adding funds with message <%s>", mcid) return nil }), fsm.Event(storagemarket.ClientEventReserveFundsFailed). FromMany(storagemarket.StorageDealClientFunding, storagemarket.StorageDealReserveClientFunds).To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("adding market funds failed: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventFundsReserved). @@ -38,12 +40,14 @@ var ClientEvents = fsm.Events{ } else { deal.FundsReserved = big.Add(deal.FundsReserved, fundsReserved) } + deal.AddLog("funds reserved, amount <%s>", fundsReserved) return nil }), fsm.Event(storagemarket.ClientEventFundsReleased). FromMany(storagemarket.StorageDealProposalAccepted, storagemarket.StorageDealFailing).ToJustRecord(). Action(func(deal *storagemarket.ClientDeal, fundsReleased abi.TokenAmount) error { deal.FundsReserved = big.Subtract(deal.FundsReserved, fundsReleased) + deal.AddLog("funds released, amount <%s>", fundsReleased) return nil }), fsm.Event(storagemarket.ClientEventFundingComplete). @@ -52,27 +56,34 @@ var ClientEvents = fsm.Events{ From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("sending proposal to storage provider failed: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventReadResponseFailed). From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("error reading Response message: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventResponseVerificationFailed). From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal) error { deal.Message = "unable to verify signature on deal response" + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventInitiateDataTransfer). - From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealStartDataTransfer), - + From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealStartDataTransfer). + Action(func(deal *storagemarket.ClientDeal) error { + deal.AddLog("initiate data transfer") + return nil + }), fsm.Event(storagemarket.ClientEventUnexpectedDealState). From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, status storagemarket.StorageDealStatus, providerMessage string) error { deal.Message = xerrors.Errorf("unexpected deal status while waiting for data request: %d (%s). Provider message: %s", status, storagemarket.DealStates[status], providerMessage).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDataTransferFailed). @@ -80,6 +91,7 @@ var ClientEvents = fsm.Events{ To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("failed to initiate data transfer: %w", err).Error() + deal.AddLog(deal.Message) return nil }), @@ -87,6 +99,7 @@ var ClientEvents = fsm.Events{ To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("failed to restart data transfer: %w", err).Error() + deal.AddLog(deal.Message) return nil }), @@ -94,6 +107,7 @@ var ClientEvents = fsm.Events{ FromMany(storagemarket.StorageDealStartDataTransfer).To(storagemarket.StorageDealTransferring). Action(func(deal *storagemarket.ClientDeal, channelId datatransfer.ChannelID) error { deal.TransferChannelID = &channelId + deal.AddLog("data transfer initiated on channel id <%s>", channelId) return nil }), @@ -103,6 +117,7 @@ var ClientEvents = fsm.Events{ Action(func(deal *storagemarket.ClientDeal, channelId datatransfer.ChannelID) error { deal.TransferChannelID = &channelId deal.Message = "" + deal.AddLog("data transfer restarted on channel id <%s>", channelId) return nil }), @@ -111,6 +126,7 @@ var ClientEvents = fsm.Events{ To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("could not complete data transfer, could not connect to provider %s", deal.Miner).Error() + deal.AddLog("data transfer stalled, could not connect to provider <%s>", deal.Miner) return nil }), @@ -123,6 +139,7 @@ var ClientEvents = fsm.Events{ To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal) error { deal.Message = "data transfer cancelled" + deal.AddLog(deal.Message) return nil }), @@ -137,18 +154,32 @@ var ClientEvents = fsm.Events{ deal.PollErrorCount++ } deal.Message = fmt.Sprintf("Provider state: %s", storagemarket.DealStates[providerState]) + switch storagemarket.DealStates[providerState] { + case "StorageDealVerifyData": + deal.AddLog("provider is verifying the data") + case "StorageDealPublish": + deal.AddLog("waiting for provider to publish the deal on-chain") // TODO: is that right? + case "StorageDealPublishing": + deal.AddLog("provider has submitted the deal on-chain") // TODO: is that right? + case "StorageDealProviderFunding": + deal.AddLog("waiting for provider to lock collateral on-chain") // TODO: is that right? + default: + deal.AddLog(deal.Message) + } return nil }), fsm.Event(storagemarket.ClientEventResponseDealDidNotMatch). From(storagemarket.StorageDealCheckForAcceptance).To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, responseCid cid.Cid, proposalCid cid.Cid) error { deal.Message = xerrors.Errorf("miner responded to a wrong proposal: %s != %s", responseCid, proposalCid).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDealRejected). From(storagemarket.StorageDealCheckForAcceptance).To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, state storagemarket.StorageDealStatus, reason string) error { deal.Message = xerrors.Errorf("deal failed: (State=%d) %s", state, reason).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDealAccepted). @@ -156,51 +187,63 @@ var ClientEvents = fsm.Events{ Action(func(deal *storagemarket.ClientDeal, publishMessage *cid.Cid) error { deal.PublishMessage = publishMessage deal.Message = "" + deal.AddLog("deal has been accepted") return nil }), fsm.Event(storagemarket.ClientEventStreamCloseError). FromAny().To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("error attempting to close stream: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDealPublishFailed). From(storagemarket.StorageDealProposalAccepted).To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("error validating deal published: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDealPublished). From(storagemarket.StorageDealProposalAccepted).To(storagemarket.StorageDealAwaitingPreCommit). Action(func(deal *storagemarket.ClientDeal, dealID abi.DealID) error { deal.DealID = dealID + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDealPrecommitFailed). From(storagemarket.StorageDealAwaitingPreCommit).To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("error awaiting deal pre-commit: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDealPrecommitted). From(storagemarket.StorageDealAwaitingPreCommit).To(storagemarket.StorageDealSealing). Action(func(deal *storagemarket.ClientDeal, sectorNumber abi.SectorNumber) error { deal.SectorNumber = sectorNumber + deal.AddLog("deal has been precommitted") return nil }), fsm.Event(storagemarket.ClientEventDealActivationFailed). From(storagemarket.StorageDealSealing).To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("error in deal activation: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventDealActivated). FromMany(storagemarket.StorageDealAwaitingPreCommit, storagemarket.StorageDealSealing). - To(storagemarket.StorageDealActive), + To(storagemarket.StorageDealActive). + Action(func(deal *storagemarket.ClientDeal, err error) error { + deal.AddLog("deal activated") + return nil + }), fsm.Event(storagemarket.ClientEventDealSlashed). From(storagemarket.StorageDealActive).To(storagemarket.StorageDealSlashed). Action(func(deal *storagemarket.ClientDeal, slashEpoch abi.ChainEpoch) error { deal.SlashEpoch = slashEpoch + deal.AddLog("deal slashed on <%d>", slashEpoch) return nil }), fsm.Event(storagemarket.ClientEventDealExpired). @@ -209,10 +252,15 @@ var ClientEvents = fsm.Events{ From(storagemarket.StorageDealActive).To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("error waiting for deal completion: %w", err).Error() + deal.AddLog(deal.Message) return nil }), fsm.Event(storagemarket.ClientEventFailed). - From(storagemarket.StorageDealFailing).To(storagemarket.StorageDealError), + From(storagemarket.StorageDealFailing).To(storagemarket.StorageDealError). + Action(func(deal *storagemarket.ClientDeal, err error) error { + deal.AddLog(deal.Message) + return nil + }), fsm.Event(storagemarket.ClientEventRestart).From(storagemarket.StorageDealTransferring).To(storagemarket.StorageDealClientTransferRestart). FromAny().ToNoChange(), } diff --git a/storagemarket/types.go b/storagemarket/types.go index ed642c13..f89117ac 100644 --- a/storagemarket/types.go +++ b/storagemarket/types.go @@ -1,7 +1,11 @@ package storagemarket import ( + "fmt" + "time" + "github.com/ipfs/go-cid" + logging "github.com/ipfs/go-log/v2" "github.com/libp2p/go-libp2p-core/peer" ma "github.com/multiformats/go-multiaddr" cbg "github.com/whyrusleeping/cbor-gen" @@ -16,7 +20,9 @@ import ( "github.com/filecoin-project/go-fil-markets/filestore" ) -//go:generate cbor-gen-for --map-encoding ClientDeal MinerDeal Balance SignedStorageAsk StorageAsk DataRef ProviderDealState +var log = logging.Logger("storagemrkt") + +//go:generate cbor-gen-for --map-encoding ClientDeal MinerDeal Balance SignedStorageAsk StorageAsk DataRef ProviderDealState DealStages DealStage Log // DealProtocolID is the ID for the libp2p protocol for proposing storage deals. const OldDealProtocolID = "/fil/storage/mk/1.0.1" @@ -108,6 +114,71 @@ type MinerDeal struct { SectorNumber abi.SectorNumber } +func NewDealStages() *DealStages { + return &DealStages{} +} + +type DealStages struct { + Stages []*DealStage +} + +type Log struct { + Log string + UpdatedTime cbg.CborTime +} + +func (ds *DealStages) GetStage(stage string) *DealStage { + for _, s := range ds.Stages { + if s.Name == stage { + return s + } + } + + return nil +} + +func (ds *DealStages) AddStageLog(stage, description, expectedDuration, msg string) { + log.Infof("adding log for stage <%s> msg <%s>", stage, msg) + + now := curTime() + st := ds.GetStage(stage) + if st == nil { + st = &DealStage{ + CreatedTime: now, + } + ds.Stages = append(ds.Stages, st) + } + + st.Name = stage + st.Description = description + st.ExpectedDuration = expectedDuration + st.UpdatedTime = now + if msg != "" && (len(st.Logs) == 0 || st.Logs[len(st.Logs)-1].Log != msg) { + st.Logs = append(st.Logs, &Log{msg, now}) + } +} + +type DealStage struct { + Name string + Description string + ExpectedDuration string + CreatedTime cbg.CborTime + UpdatedTime cbg.CborTime + Logs []*Log +} + +func (d *ClientDeal) AddLog(msg string, a ...interface{}) { + if len(a) > 0 { + msg = fmt.Sprintf(msg, a...) + } + + stage := DealStates[d.State] + description := DealStatesDescriptions[d.State] + expectedDuration := DealStatesDurations[d.State] + + d.DealStages.AddStageLog(stage, description, expectedDuration, msg) +} + // ClientDeal is the local state tracked for a deal by a StorageClient type ClientDeal struct { market.ClientDealProposal @@ -119,6 +190,7 @@ type ClientDeal struct { DealID abi.DealID DataRef *DataRef Message string + DealStages *DealStages PublishMessage *cid.Cid SlashEpoch abi.ChainEpoch PollRetryCount uint64 @@ -192,3 +264,8 @@ type ProviderDealState struct { DealID abi.DealID FastRetrieval bool } + +func curTime() cbg.CborTime { + now := time.Now() + return cbg.CborTime(time.Unix(0, now.UnixNano()).UTC()) +} diff --git a/storagemarket/types_cbor_gen.go b/storagemarket/types_cbor_gen.go index 7181ce1f..c9b7b29b 100644 --- a/storagemarket/types_cbor_gen.go +++ b/storagemarket/types_cbor_gen.go @@ -28,7 +28,7 @@ func (t *ClientDeal) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{179}); err != nil { + if _, err := w.Write([]byte{180}); err != nil { return err } @@ -198,6 +198,22 @@ func (t *ClientDeal) MarshalCBOR(w io.Writer) error { return err } + // t.DealStages (storagemarket.DealStages) (struct) + if len("DealStages") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"DealStages\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("DealStages"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("DealStages")); err != nil { + return err + } + + if err := t.DealStages.MarshalCBOR(w); err != nil { + return err + } + // t.PublishMessage (cid.Cid) (struct) if len("PublishMessage") > cbg.MaxLength { return xerrors.Errorf("Value in field \"PublishMessage\" was too long") @@ -540,6 +556,26 @@ func (t *ClientDeal) UnmarshalCBOR(r io.Reader) error { t.Message = string(sval) } + // t.DealStages (storagemarket.DealStages) (struct) + case "DealStages": + + { + + b, err := br.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := br.UnreadByte(); err != nil { + return err + } + t.DealStages = new(DealStages) + if err := t.DealStages.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.DealStages pointer: %w", err) + } + } + + } // t.PublishMessage (cid.Cid) (struct) case "PublishMessage": @@ -2616,3 +2652,490 @@ func (t *ProviderDealState) UnmarshalCBOR(r io.Reader) error { return nil } +func (t *DealStages) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{161}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Stages ([]*storagemarket.DealStage) (slice) + if len("Stages") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Stages\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Stages"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Stages")); err != nil { + return err + } + + if len(t.Stages) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Stages was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Stages))); err != nil { + return err + } + for _, v := range t.Stages { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *DealStages) UnmarshalCBOR(r io.Reader) error { + *t = DealStages{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("DealStages: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Stages ([]*storagemarket.DealStage) (slice) + case "Stages": + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Stages: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Stages = make([]*DealStage, extra) + } + + for i := 0; i < int(extra); i++ { + + var v DealStage + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Stages[i] = &v + } + + default: + // Field doesn't exist on this type, so ignore it + cbg.ScanForLinks(r, func(cid.Cid) {}) + } + } + + return nil +} +func (t *DealStage) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{166}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Name (string) (string) + if len("Name") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Name\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Name"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Name")); err != nil { + return err + } + + if len(t.Name) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Name was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.Name))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Name)); err != nil { + return err + } + + // t.Description (string) (string) + if len("Description") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Description\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Description"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Description")); err != nil { + return err + } + + if len(t.Description) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Description was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.Description))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Description)); err != nil { + return err + } + + // t.ExpectedDuration (string) (string) + if len("ExpectedDuration") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"ExpectedDuration\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("ExpectedDuration"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("ExpectedDuration")); err != nil { + return err + } + + if len(t.ExpectedDuration) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.ExpectedDuration was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.ExpectedDuration))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.ExpectedDuration)); err != nil { + return err + } + + // t.CreatedTime (typegen.CborTime) (struct) + if len("CreatedTime") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"CreatedTime\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("CreatedTime"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("CreatedTime")); err != nil { + return err + } + + if err := t.CreatedTime.MarshalCBOR(w); err != nil { + return err + } + + // t.UpdatedTime (typegen.CborTime) (struct) + if len("UpdatedTime") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"UpdatedTime\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("UpdatedTime"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("UpdatedTime")); err != nil { + return err + } + + if err := t.UpdatedTime.MarshalCBOR(w); err != nil { + return err + } + + // t.Logs ([]*storagemarket.Log) (slice) + if len("Logs") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Logs\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Logs"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Logs")); err != nil { + return err + } + + if len(t.Logs) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Logs was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Logs))); err != nil { + return err + } + for _, v := range t.Logs { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *DealStage) UnmarshalCBOR(r io.Reader) error { + *t = DealStage{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("DealStage: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Name (string) (string) + case "Name": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.Name = string(sval) + } + // t.Description (string) (string) + case "Description": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.Description = string(sval) + } + // t.ExpectedDuration (string) (string) + case "ExpectedDuration": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.ExpectedDuration = string(sval) + } + // t.CreatedTime (typegen.CborTime) (struct) + case "CreatedTime": + + { + + if err := t.CreatedTime.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.CreatedTime: %w", err) + } + + } + // t.UpdatedTime (typegen.CborTime) (struct) + case "UpdatedTime": + + { + + if err := t.UpdatedTime.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.UpdatedTime: %w", err) + } + + } + // t.Logs ([]*storagemarket.Log) (slice) + case "Logs": + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Logs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Logs = make([]*Log, extra) + } + + for i := 0; i < int(extra); i++ { + + var v Log + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Logs[i] = &v + } + + default: + // Field doesn't exist on this type, so ignore it + cbg.ScanForLinks(r, func(cid.Cid) {}) + } + } + + return nil +} +func (t *Log) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{162}); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Log (string) (string) + if len("Log") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Log\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("Log"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Log")); err != nil { + return err + } + + if len(t.Log) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Log was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(t.Log))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Log)); err != nil { + return err + } + + // t.UpdatedTime (typegen.CborTime) (struct) + if len("UpdatedTime") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"UpdatedTime\" was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len("UpdatedTime"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("UpdatedTime")); err != nil { + return err + } + + if err := t.UpdatedTime.MarshalCBOR(w); err != nil { + return err + } + return nil +} + +func (t *Log) UnmarshalCBOR(r io.Reader) error { + *t = Log{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("Log: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Log (string) (string) + case "Log": + + { + sval, err := cbg.ReadStringBuf(br, scratch) + if err != nil { + return err + } + + t.Log = string(sval) + } + // t.UpdatedTime (typegen.CborTime) (struct) + case "UpdatedTime": + + { + + if err := t.UpdatedTime.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.UpdatedTime: %w", err) + } + + } + + default: + // Field doesn't exist on this type, so ignore it + cbg.ScanForLinks(r, func(cid.Cid) {}) + } + } + + return nil +} From 6458ab56ac03d4c30ffccbff2a09a70c7b8d609d Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 18 Mar 2021 17:15:43 +0200 Subject: [PATCH 02/18] fixup --- storagemarket/impl/clientstates/client_fsm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index be3002e9..a6b3e744 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -235,7 +235,7 @@ var ClientEvents = fsm.Events{ fsm.Event(storagemarket.ClientEventDealActivated). FromMany(storagemarket.StorageDealAwaitingPreCommit, storagemarket.StorageDealSealing). To(storagemarket.StorageDealActive). - Action(func(deal *storagemarket.ClientDeal, err error) error { + Action(func(deal *storagemarket.ClientDeal) error { deal.AddLog("deal activated") return nil }), @@ -257,7 +257,7 @@ var ClientEvents = fsm.Events{ }), fsm.Event(storagemarket.ClientEventFailed). From(storagemarket.StorageDealFailing).To(storagemarket.StorageDealError). - Action(func(deal *storagemarket.ClientDeal, err error) error { + Action(func(deal *storagemarket.ClientDeal) error { deal.AddLog(deal.Message) return nil }), From d96bb002f6e99663a37c038f3abdff106c1f5530 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Thu, 18 Mar 2021 18:15:19 +0200 Subject: [PATCH 03/18] fixup --- shared_testutil/generators.go | 1 + 1 file changed, 1 insertion(+) diff --git a/shared_testutil/generators.go b/shared_testutil/generators.go index 7007a8df..92df574d 100644 --- a/shared_testutil/generators.go +++ b/shared_testutil/generators.go @@ -162,6 +162,7 @@ func MakeTestClientDeal(state storagemarket.StorageDealStatus, clientDealProposa Miner: p, MinerWorker: address.TestAddress2, DataRef: MakeTestDataRef(manualXfer), + DealStages: storagemarket.NewDealStages(), }, nil } From ea81924dec2ef784018bc4aebc17f6211389439b Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:23:11 +0200 Subject: [PATCH 04/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index a6b3e744..c8d0c132 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -22,7 +22,7 @@ var ClientEvents = fsm.Events{ From(storagemarket.StorageDealReserveClientFunds).To(storagemarket.StorageDealClientFunding). Action(func(deal *storagemarket.ClientDeal, mcid cid.Cid) error { deal.AddFundsCid = &mcid - deal.AddLog("adding funds with message <%s>", mcid) + deal.AddLog("reserving funds for storage deal, message cid: <%s>", mcid) return nil }), fsm.Event(storagemarket.ClientEventReserveFundsFailed). From 779071d3ffb9658928b186f4c2432e410f987283 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:23:30 +0200 Subject: [PATCH 05/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index c8d0c132..8de2acf2 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -62,7 +62,7 @@ var ClientEvents = fsm.Events{ fsm.Event(storagemarket.ClientEventReadResponseFailed). From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { - deal.Message = xerrors.Errorf("error reading Response message: %w", err).Error() + deal.Message = xerrors.Errorf("error reading Response message from provider: %w", err).Error() deal.AddLog(deal.Message) return nil }), From 36bdc80dc0b24ad40533462bd6e2af911a08d221 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:23:40 +0200 Subject: [PATCH 06/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index 8de2acf2..f48280b7 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -76,7 +76,7 @@ var ClientEvents = fsm.Events{ fsm.Event(storagemarket.ClientEventInitiateDataTransfer). From(storagemarket.StorageDealFundsReserved).To(storagemarket.StorageDealStartDataTransfer). Action(func(deal *storagemarket.ClientDeal) error { - deal.AddLog("initiate data transfer") + deal.AddLog("opening data transfer to storage provider") return nil }), fsm.Event(storagemarket.ClientEventUnexpectedDealState). From 3a26ef02a35f123a4349bb3764bf501c49065ae8 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:23:51 +0200 Subject: [PATCH 07/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index f48280b7..c81c34cd 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -90,7 +90,7 @@ var ClientEvents = fsm.Events{ FromMany(storagemarket.StorageDealStartDataTransfer, storagemarket.StorageDealTransferring). To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { - deal.Message = xerrors.Errorf("failed to initiate data transfer: %w", err).Error() + deal.Message = xerrors.Errorf("failed to complete data transfer: %w", err).Error() deal.AddLog(deal.Message) return nil }), From 9fb4cd63876d4698a9b23faad1f32ab2e569dd0a Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:24:09 +0200 Subject: [PATCH 08/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index c81c34cd..e30cfb2d 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -126,7 +126,7 @@ var ClientEvents = fsm.Events{ To(storagemarket.StorageDealFailing). Action(func(deal *storagemarket.ClientDeal, err error) error { deal.Message = xerrors.Errorf("could not complete data transfer, could not connect to provider %s", deal.Miner).Error() - deal.AddLog("data transfer stalled, could not connect to provider <%s>", deal.Miner) + deal.AddLog(deal.Message) return nil }), From a9a76d3fbfd4ef8a425b485adfdc8911e3f27c23 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:24:20 +0200 Subject: [PATCH 09/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index e30cfb2d..30d53f0c 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -214,7 +214,7 @@ var ClientEvents = fsm.Events{ fsm.Event(storagemarket.ClientEventDealPrecommitFailed). From(storagemarket.StorageDealAwaitingPreCommit).To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal, err error) error { - deal.Message = xerrors.Errorf("error awaiting deal pre-commit: %w", err).Error() + deal.Message = xerrors.Errorf("error waiting for deal pre-commit message to appear on chain: %w", err).Error() deal.AddLog(deal.Message) return nil }), From 093be6f13f1d1cef9c7dfdc49677aae6fe93b091 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:24:30 +0200 Subject: [PATCH 10/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index 30d53f0c..f57e2a2c 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -222,7 +222,7 @@ var ClientEvents = fsm.Events{ From(storagemarket.StorageDealAwaitingPreCommit).To(storagemarket.StorageDealSealing). Action(func(deal *storagemarket.ClientDeal, sectorNumber abi.SectorNumber) error { deal.SectorNumber = sectorNumber - deal.AddLog("deal has been precommitted") + deal.AddLog("deal pre-commit message has landed on chain") return nil }), fsm.Event(storagemarket.ClientEventDealActivationFailed). From 86f83ba22379b4584e5f2523ca423c901e4c32d9 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:24:37 +0200 Subject: [PATCH 11/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index f57e2a2c..25051c2f 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -243,7 +243,7 @@ var ClientEvents = fsm.Events{ From(storagemarket.StorageDealActive).To(storagemarket.StorageDealSlashed). Action(func(deal *storagemarket.ClientDeal, slashEpoch abi.ChainEpoch) error { deal.SlashEpoch = slashEpoch - deal.AddLog("deal slashed on <%d>", slashEpoch) + deal.AddLog("deal slashed at epoch <%d>", slashEpoch) return nil }), fsm.Event(storagemarket.ClientEventDealExpired). From b6c677d9685f0f13e58520ad87f6b4597c6ae71e Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:25:54 +0200 Subject: [PATCH 12/18] decrease log level to debug --- storagemarket/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/types.go b/storagemarket/types.go index f89117ac..97550bca 100644 --- a/storagemarket/types.go +++ b/storagemarket/types.go @@ -138,7 +138,7 @@ func (ds *DealStages) GetStage(stage string) *DealStage { } func (ds *DealStages) AddStageLog(stage, description, expectedDuration, msg string) { - log.Infof("adding log for stage <%s> msg <%s>", stage, msg) + log.Debugf("adding log for stage <%s> msg <%s>", stage, msg) now := curTime() st := ds.GetStage(stage) From afdc5911ada1a63332598aa78136c1e5f67ffb48 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:26:19 +0200 Subject: [PATCH 13/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index 25051c2f..4d454bd6 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -160,7 +160,7 @@ var ClientEvents = fsm.Events{ case "StorageDealPublish": deal.AddLog("waiting for provider to publish the deal on-chain") // TODO: is that right? case "StorageDealPublishing": - deal.AddLog("provider has submitted the deal on-chain") // TODO: is that right? + deal.AddLog("provider has submitted the deal on-chain and is waiting for confirmation") // TODO: is that right? case "StorageDealProviderFunding": deal.AddLog("waiting for provider to lock collateral on-chain") // TODO: is that right? default: From 074a8a3b677e30cfad41ab912b4696100af3320b Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:26:30 +0200 Subject: [PATCH 14/18] Update storagemarket/impl/clientstates/client_fsm.go Co-authored-by: dirkmc --- storagemarket/impl/clientstates/client_fsm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index 4d454bd6..29c30c76 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -187,7 +187,7 @@ var ClientEvents = fsm.Events{ Action(func(deal *storagemarket.ClientDeal, publishMessage *cid.Cid) error { deal.PublishMessage = publishMessage deal.Message = "" - deal.AddLog("deal has been accepted") + deal.AddLog("deal has been accepted by storage provider") return nil }), fsm.Event(storagemarket.ClientEventStreamCloseError). From 00df6da5263e382862dcd73c428bcb3bf9bfd548 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:29:01 +0200 Subject: [PATCH 15/18] explicit set of log with empty value --- storagemarket/impl/clientstates/client_fsm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemarket/impl/clientstates/client_fsm.go b/storagemarket/impl/clientstates/client_fsm.go index 29c30c76..7a37213c 100644 --- a/storagemarket/impl/clientstates/client_fsm.go +++ b/storagemarket/impl/clientstates/client_fsm.go @@ -208,7 +208,7 @@ var ClientEvents = fsm.Events{ From(storagemarket.StorageDealProposalAccepted).To(storagemarket.StorageDealAwaitingPreCommit). Action(func(deal *storagemarket.ClientDeal, dealID abi.DealID) error { deal.DealID = dealID - deal.AddLog(deal.Message) + deal.AddLog("") return nil }), fsm.Event(storagemarket.ClientEventDealPrecommitFailed). @@ -258,7 +258,7 @@ var ClientEvents = fsm.Events{ fsm.Event(storagemarket.ClientEventFailed). From(storagemarket.StorageDealFailing).To(storagemarket.StorageDealError). Action(func(deal *storagemarket.ClientDeal) error { - deal.AddLog(deal.Message) + deal.AddLog("") return nil }), fsm.Event(storagemarket.ClientEventRestart).From(storagemarket.StorageDealTransferring).To(storagemarket.StorageDealClientTransferRestart). From a848de845da83effcd36c74024edfab20b8685e6 Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Fri, 19 Mar 2021 13:31:45 +0200 Subject: [PATCH 16/18] fix test --- storagemarket/impl/clientstates/client_states_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storagemarket/impl/clientstates/client_states_test.go b/storagemarket/impl/clientstates/client_states_test.go index ec27d848..3459e34e 100644 --- a/storagemarket/impl/clientstates/client_states_test.go +++ b/storagemarket/impl/clientstates/client_states_test.go @@ -153,7 +153,7 @@ func TestProposeDeal(t *testing.T) { }, inspector: func(deal storagemarket.ClientDeal, env *fakeEnvironment) { tut.AssertDealState(t, storagemarket.StorageDealFailing, deal.State) - assert.Equal(t, "error reading Response message: read response failed", deal.Message) + assert.Equal(t, "error reading Response message from provider: read response failed", deal.Message) }, }) }) @@ -437,7 +437,7 @@ func TestVerifyDealPreCommitted(t *testing.T) { nodeParams: nodeParams{DealPreCommittedSyncError: errors.New("Something went wrong")}, inspector: func(deal storagemarket.ClientDeal, env *fakeEnvironment) { tut.AssertDealState(t, storagemarket.StorageDealError, deal.State) - assert.Equal(t, "error awaiting deal pre-commit: Something went wrong", deal.Message) + assert.Equal(t, "error waiting for deal pre-commit message to appear on chain: Something went wrong", deal.Message) }, }) }) @@ -446,7 +446,7 @@ func TestVerifyDealPreCommitted(t *testing.T) { nodeParams: nodeParams{DealPreCommittedAsyncError: errors.New("Something went wrong later")}, inspector: func(deal storagemarket.ClientDeal, env *fakeEnvironment) { tut.AssertDealState(t, storagemarket.StorageDealError, deal.State) - assert.Equal(t, "error awaiting deal pre-commit: Something went wrong later", deal.Message) + assert.Equal(t, "error waiting for deal pre-commit message to appear on chain: Something went wrong later", deal.Message) }, }) }) From d9118f75938377558a29b077b9b5af3a61208285 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 19 Mar 2021 15:34:50 +0100 Subject: [PATCH 17/18] fix: dont panic when adding log to nil DealStages --- storagemarket/types.go | 8 ++++++++ storagemarket/types_test.go | 13 +++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 storagemarket/types_test.go diff --git a/storagemarket/types.go b/storagemarket/types.go index 97550bca..dbe33ead 100644 --- a/storagemarket/types.go +++ b/storagemarket/types.go @@ -128,6 +128,10 @@ type Log struct { } func (ds *DealStages) GetStage(stage string) *DealStage { + if ds == nil { + return nil + } + for _, s := range ds.Stages { if s.Name == stage { return s @@ -138,6 +142,10 @@ func (ds *DealStages) GetStage(stage string) *DealStage { } func (ds *DealStages) AddStageLog(stage, description, expectedDuration, msg string) { + if ds == nil { + return + } + log.Debugf("adding log for stage <%s> msg <%s>", stage, msg) now := curTime() diff --git a/storagemarket/types_test.go b/storagemarket/types_test.go new file mode 100644 index 00000000..e1d87c9d --- /dev/null +++ b/storagemarket/types_test.go @@ -0,0 +1,13 @@ +package storagemarket_test + +import ( + "testing" + + "github.com/filecoin-project/go-fil-markets/storagemarket" +) + +func TestDealStagesNil(t *testing.T) { + var ds *storagemarket.DealStages + ds.GetStage("none") + ds.AddStageLog("MyStage", "desc", "duration", "msg") +} From 3f13328acc91444416552d5258433169b7ac0e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Thu, 25 Mar 2021 13:18:26 +0000 Subject: [PATCH 18/18] add godocs to deal stages objects. --- storagemarket/types.go | 59 ++++++++++++++++++++++++++++++------- storagemarket/types_test.go | 4 +-- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/storagemarket/types.go b/storagemarket/types.go index dbe33ead..eef6c190 100644 --- a/storagemarket/types.go +++ b/storagemarket/types.go @@ -114,19 +114,61 @@ type MinerDeal struct { SectorNumber abi.SectorNumber } +// NewDealStages creates a new DealStages object ready to be used. +// EXPERIMENTAL; subject to change. func NewDealStages() *DealStages { return &DealStages{} } +// DealStages captures a timeline of the progress of a deal, grouped by stages. +// EXPERIMENTAL; subject to change. type DealStages struct { + // Stages contains an entry for every stage that the deal has gone through. + // Each stage then contains logs. Stages []*DealStage } +// DealStages captures data about the execution of a deal stage. +// EXPERIMENTAL; subject to change. +type DealStage struct { + // Human-readable fields. + // TODO: these _will_ need to be converted to canonical representations, so + // they are machine readable. + Name string + Description string + ExpectedDuration string + + // Timestamps. + // TODO: may be worth adding an exit timestamp. It _could_ be inferred from + // the start of the next stage, or from the timestamp of the last log line + // if this is a terminal stage. But that's non-determistic and it relies on + // assumptions. + CreatedTime cbg.CborTime + UpdatedTime cbg.CborTime + + // Logs contains a detailed timeline of events that occurred inside + // this stage. + Logs []*Log +} + +// Log represents a point-in-time event that occurred inside a deal stage. +// EXPERIMENTAL; subject to change. type Log struct { - Log string + // Log is a human readable message. + // + // TODO: this _may_ need to be converted to a canonical data model so it + // is machine-readable. + Log string + UpdatedTime cbg.CborTime } +// GetStage returns the DealStage object for a named stage, or nil if not found. +// +// TODO: the input should be a strongly-typed enum instead of a free-form string. +// TODO: drop Get from GetStage to make this code more idiomatic. Return a +// second ok boolean to make it even more idiomatic. +// EXPERIMENTAL; subject to change. func (ds *DealStages) GetStage(stage string) *DealStage { if ds == nil { return nil @@ -141,6 +183,9 @@ func (ds *DealStages) GetStage(stage string) *DealStage { return nil } +// AddStageLog adds a log to the specified stage, creating the stage if it +// doesn't exist yet. +// EXPERIMENTAL; subject to change. func (ds *DealStages) AddStageLog(stage, description, expectedDuration, msg string) { if ds == nil { return @@ -162,19 +207,13 @@ func (ds *DealStages) AddStageLog(stage, description, expectedDuration, msg stri st.ExpectedDuration = expectedDuration st.UpdatedTime = now if msg != "" && (len(st.Logs) == 0 || st.Logs[len(st.Logs)-1].Log != msg) { + // only add the log if it's not a duplicate. st.Logs = append(st.Logs, &Log{msg, now}) } } -type DealStage struct { - Name string - Description string - ExpectedDuration string - CreatedTime cbg.CborTime - UpdatedTime cbg.CborTime - Logs []*Log -} - +// AddLog adds a log inside the DealStages object of the deal. +// EXPERIMENTAL; subject to change. func (d *ClientDeal) AddLog(msg string, a ...interface{}) { if len(a) > 0 { msg = fmt.Sprintf(msg, a...) diff --git a/storagemarket/types_test.go b/storagemarket/types_test.go index e1d87c9d..8b5df7df 100644 --- a/storagemarket/types_test.go +++ b/storagemarket/types_test.go @@ -8,6 +8,6 @@ import ( func TestDealStagesNil(t *testing.T) { var ds *storagemarket.DealStages - ds.GetStage("none") - ds.AddStageLog("MyStage", "desc", "duration", "msg") + ds.GetStage("none") // no panic. + ds.AddStageLog("MyStage", "desc", "duration", "msg") // no panic. }