From 636a9588a794e3b627d60597f77343081cbfad67 Mon Sep 17 00:00:00 2001 From: Aayush Date: Fri, 11 Mar 2022 19:37:44 -0500 Subject: [PATCH] Market state: Change Label to be a Union of strings and bytes --- actors/builtin/market/cbor_gen.go | 1128 +++++++++++++++++++++++++ actors/builtin/market/deal.go | 229 ++++- actors/builtin/market/market_actor.go | 11 +- actors/builtin/market/market_test.go | 60 +- actors/test/common_test.go | 13 +- gen/gen.go | 12 +- support/agent/deal_client_agent.go | 7 +- 7 files changed, 1393 insertions(+), 67 deletions(-) diff --git a/actors/builtin/market/cbor_gen.go b/actors/builtin/market/cbor_gen.go index 4ed5bd11c..fa666e760 100644 --- a/actors/builtin/market/cbor_gen.go +++ b/actors/builtin/market/cbor_gen.go @@ -255,6 +255,1134 @@ func (t *State) UnmarshalCBOR(r io.Reader) error { return nil } +var lengthBufPublishStorageDealsParams = []byte{129} + +func (t *PublishStorageDealsParams) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufPublishStorageDealsParams); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Deals ([]market.ClientDealProposal) (slice) + if len(t.Deals) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Deals was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Deals))); err != nil { + return err + } + for _, v := range t.Deals { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *PublishStorageDealsParams) UnmarshalCBOR(r io.Reader) error { + *t = PublishStorageDealsParams{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 1 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Deals ([]market.ClientDealProposal) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Deals: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Deals = make([]ClientDealProposal, extra) + } + + for i := 0; i < int(extra); i++ { + + var v ClientDealProposal + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Deals[i] = v + } + + return nil +} + +var lengthBufPublishStorageDealsReturn = []byte{130} + +func (t *PublishStorageDealsReturn) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufPublishStorageDealsReturn); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.IDs ([]abi.DealID) (slice) + if len(t.IDs) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.IDs was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.IDs))); err != nil { + return err + } + for _, v := range t.IDs { + if err := cbg.CborWriteHeader(w, cbg.MajUnsignedInt, uint64(v)); err != nil { + return err + } + } + + // t.ValidDeals (bitfield.BitField) (struct) + if err := t.ValidDeals.MarshalCBOR(w); err != nil { + return err + } + return nil +} + +func (t *PublishStorageDealsReturn) UnmarshalCBOR(r io.Reader) error { + *t = PublishStorageDealsReturn{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.IDs ([]abi.DealID) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.IDs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.IDs = make([]abi.DealID, extra) + } + + for i := 0; i < int(extra); i++ { + + maj, val, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return xerrors.Errorf("failed to read uint64 for t.IDs slice: %w", err) + } + + if maj != cbg.MajUnsignedInt { + return xerrors.Errorf("value read for array t.IDs was not a uint, instead got %d", maj) + } + + t.IDs[i] = abi.DealID(val) + } + + // t.ValidDeals (bitfield.BitField) (struct) + + { + + if err := t.ValidDeals.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.ValidDeals: %w", err) + } + + } + return nil +} + +var lengthBufVerifyDealsForActivationParams = []byte{129} + +func (t *VerifyDealsForActivationParams) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufVerifyDealsForActivationParams); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Sectors ([]market.SectorDeals) (slice) + if len(t.Sectors) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Sectors was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Sectors))); err != nil { + return err + } + for _, v := range t.Sectors { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *VerifyDealsForActivationParams) UnmarshalCBOR(r io.Reader) error { + *t = VerifyDealsForActivationParams{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 1 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Sectors ([]market.SectorDeals) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Sectors: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Sectors = make([]SectorDeals, extra) + } + + for i := 0; i < int(extra); i++ { + + var v SectorDeals + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Sectors[i] = v + } + + return nil +} + +var lengthBufVerifyDealsForActivationReturn = []byte{129} + +func (t *VerifyDealsForActivationReturn) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufVerifyDealsForActivationReturn); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Sectors ([]market.SectorWeights) (slice) + if len(t.Sectors) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Sectors was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Sectors))); err != nil { + return err + } + for _, v := range t.Sectors { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *VerifyDealsForActivationReturn) UnmarshalCBOR(r io.Reader) error { + *t = VerifyDealsForActivationReturn{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 1 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Sectors ([]market.SectorWeights) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Sectors: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Sectors = make([]SectorWeights, extra) + } + + for i := 0; i < int(extra); i++ { + + var v SectorWeights + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Sectors[i] = v + } + + return nil +} + +var lengthBufSectorDataSpec = []byte{130} + +func (t *SectorDataSpec) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufSectorDataSpec); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.DealIDs ([]abi.DealID) (slice) + if len(t.DealIDs) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.DealIDs was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.DealIDs))); err != nil { + return err + } + for _, v := range t.DealIDs { + if err := cbg.CborWriteHeader(w, cbg.MajUnsignedInt, uint64(v)); err != nil { + return err + } + } + + // t.SectorType (abi.RegisteredSealProof) (int64) + if t.SectorType >= 0 { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.SectorType)); err != nil { + return err + } + } else { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.SectorType-1)); err != nil { + return err + } + } + return nil +} + +func (t *SectorDataSpec) UnmarshalCBOR(r io.Reader) error { + *t = SectorDataSpec{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.DealIDs ([]abi.DealID) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.DealIDs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.DealIDs = make([]abi.DealID, extra) + } + + for i := 0; i < int(extra); i++ { + + maj, val, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return xerrors.Errorf("failed to read uint64 for t.DealIDs slice: %w", err) + } + + if maj != cbg.MajUnsignedInt { + return xerrors.Errorf("value read for array t.DealIDs was not a uint, instead got %d", maj) + } + + t.DealIDs[i] = abi.DealID(val) + } + + // t.SectorType (abi.RegisteredSealProof) (int64) + { + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + var extraI int64 + if err != nil { + return err + } + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative oveflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } + + t.SectorType = abi.RegisteredSealProof(extraI) + } + return nil +} + +var lengthBufComputeDataCommitmentParams = []byte{129} + +func (t *ComputeDataCommitmentParams) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufComputeDataCommitmentParams); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Inputs ([]*market.SectorDataSpec) (slice) + if len(t.Inputs) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Inputs was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Inputs))); err != nil { + return err + } + for _, v := range t.Inputs { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *ComputeDataCommitmentParams) UnmarshalCBOR(r io.Reader) error { + *t = ComputeDataCommitmentParams{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 1 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Inputs ([]*market.SectorDataSpec) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Inputs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Inputs = make([]*SectorDataSpec, extra) + } + + for i := 0; i < int(extra); i++ { + + var v SectorDataSpec + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Inputs[i] = &v + } + + return nil +} + +var lengthBufComputeDataCommitmentReturn = []byte{129} + +func (t *ComputeDataCommitmentReturn) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufComputeDataCommitmentReturn); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.CommDs ([]typegen.CborCid) (slice) + if len(t.CommDs) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.CommDs was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.CommDs))); err != nil { + return err + } + for _, v := range t.CommDs { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *ComputeDataCommitmentReturn) UnmarshalCBOR(r io.Reader) error { + *t = ComputeDataCommitmentReturn{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 1 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.CommDs ([]typegen.CborCid) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.CommDs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.CommDs = make([]cbg.CborCid, extra) + } + + for i := 0; i < int(extra); i++ { + + var v cbg.CborCid + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.CommDs[i] = v + } + + return nil +} + +var lengthBufDealProposal = []byte{139} + +func (t *DealProposal) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufDealProposal); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.PieceCID (cid.Cid) (struct) + + if err := cbg.WriteCidBuf(scratch, w, t.PieceCID); err != nil { + return xerrors.Errorf("failed to write cid field t.PieceCID: %w", err) + } + + // t.PieceSize (abi.PaddedPieceSize) (uint64) + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.PieceSize)); err != nil { + return err + } + + // t.VerifiedDeal (bool) (bool) + if err := cbg.WriteBool(w, t.VerifiedDeal); err != nil { + return err + } + + // t.Client (address.Address) (struct) + if err := t.Client.MarshalCBOR(w); err != nil { + return err + } + + // t.Provider (address.Address) (struct) + if err := t.Provider.MarshalCBOR(w); err != nil { + return err + } + + // t.Label (market.DealLabel) (struct) + if err := t.Label.MarshalCBOR(w); err != nil { + return err + } + + // t.StartEpoch (abi.ChainEpoch) (int64) + if t.StartEpoch >= 0 { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.StartEpoch)); err != nil { + return err + } + } else { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.StartEpoch-1)); err != nil { + return err + } + } + + // t.EndEpoch (abi.ChainEpoch) (int64) + if t.EndEpoch >= 0 { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.EndEpoch)); err != nil { + return err + } + } else { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.EndEpoch-1)); err != nil { + return err + } + } + + // t.StoragePricePerEpoch (big.Int) (struct) + if err := t.StoragePricePerEpoch.MarshalCBOR(w); err != nil { + return err + } + + // t.ProviderCollateral (big.Int) (struct) + if err := t.ProviderCollateral.MarshalCBOR(w); err != nil { + return err + } + + // t.ClientCollateral (big.Int) (struct) + if err := t.ClientCollateral.MarshalCBOR(w); err != nil { + return err + } + return nil +} + +func (t *DealProposal) UnmarshalCBOR(r io.Reader) error { + *t = DealProposal{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 11 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.PieceCID (cid.Cid) (struct) + + { + + c, err := cbg.ReadCid(br) + if err != nil { + return xerrors.Errorf("failed to read cid field t.PieceCID: %w", err) + } + + t.PieceCID = c + + } + // t.PieceSize (abi.PaddedPieceSize) (uint64) + + { + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.PieceSize = abi.PaddedPieceSize(extra) + + } + // t.VerifiedDeal (bool) (bool) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.VerifiedDeal = false + case 21: + t.VerifiedDeal = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // t.Client (address.Address) (struct) + + { + + if err := t.Client.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.Client: %w", err) + } + + } + // t.Provider (address.Address) (struct) + + { + + if err := t.Provider.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.Provider: %w", err) + } + + } + // t.Label (market.DealLabel) (struct) + + { + + if err := t.Label.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.Label: %w", err) + } + + } + // t.StartEpoch (abi.ChainEpoch) (int64) + { + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + var extraI int64 + if err != nil { + return err + } + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative oveflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } + + t.StartEpoch = abi.ChainEpoch(extraI) + } + // t.EndEpoch (abi.ChainEpoch) (int64) + { + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + var extraI int64 + if err != nil { + return err + } + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative oveflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } + + t.EndEpoch = abi.ChainEpoch(extraI) + } + // t.StoragePricePerEpoch (big.Int) (struct) + + { + + if err := t.StoragePricePerEpoch.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.StoragePricePerEpoch: %w", err) + } + + } + // t.ProviderCollateral (big.Int) (struct) + + { + + if err := t.ProviderCollateral.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.ProviderCollateral: %w", err) + } + + } + // t.ClientCollateral (big.Int) (struct) + + { + + if err := t.ClientCollateral.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.ClientCollateral: %w", err) + } + + } + return nil +} + +var lengthBufClientDealProposal = []byte{130} + +func (t *ClientDealProposal) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufClientDealProposal); err != nil { + return err + } + + // t.Proposal (market.DealProposal) (struct) + if err := t.Proposal.MarshalCBOR(w); err != nil { + return err + } + + // t.ClientSignature (crypto.Signature) (struct) + if err := t.ClientSignature.MarshalCBOR(w); err != nil { + return err + } + return nil +} + +func (t *ClientDealProposal) UnmarshalCBOR(r io.Reader) error { + *t = ClientDealProposal{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Proposal (market.DealProposal) (struct) + + { + + if err := t.Proposal.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.Proposal: %w", err) + } + + } + // t.ClientSignature (crypto.Signature) (struct) + + { + + if err := t.ClientSignature.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.ClientSignature: %w", err) + } + + } + return nil +} + +var lengthBufSectorDeals = []byte{130} + +func (t *SectorDeals) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufSectorDeals); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.SectorExpiry (abi.ChainEpoch) (int64) + if t.SectorExpiry >= 0 { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.SectorExpiry)); err != nil { + return err + } + } else { + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.SectorExpiry-1)); err != nil { + return err + } + } + + // t.DealIDs ([]abi.DealID) (slice) + if len(t.DealIDs) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.DealIDs was too long") + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.DealIDs))); err != nil { + return err + } + for _, v := range t.DealIDs { + if err := cbg.CborWriteHeader(w, cbg.MajUnsignedInt, uint64(v)); err != nil { + return err + } + } + return nil +} + +func (t *SectorDeals) UnmarshalCBOR(r io.Reader) error { + *t = SectorDeals{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.SectorExpiry (abi.ChainEpoch) (int64) + { + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + var extraI int64 + if err != nil { + return err + } + switch maj { + case cbg.MajUnsignedInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 positive overflow") + } + case cbg.MajNegativeInt: + extraI = int64(extra) + if extraI < 0 { + return fmt.Errorf("int64 negative oveflow") + } + extraI = -1 - extraI + default: + return fmt.Errorf("wrong type for int64 field: %d", maj) + } + + t.SectorExpiry = abi.ChainEpoch(extraI) + } + // t.DealIDs ([]abi.DealID) (slice) + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.DealIDs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.DealIDs = make([]abi.DealID, extra) + } + + for i := 0; i < int(extra); i++ { + + maj, val, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return xerrors.Errorf("failed to read uint64 for t.DealIDs slice: %w", err) + } + + if maj != cbg.MajUnsignedInt { + return xerrors.Errorf("value read for array t.DealIDs was not a uint, instead got %d", maj) + } + + t.DealIDs[i] = abi.DealID(val) + } + + return nil +} + +var lengthBufSectorWeights = []byte{131} + +func (t *SectorWeights) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufSectorWeights); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.DealSpace (uint64) (uint64) + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.DealSpace)); err != nil { + return err + } + + // t.DealWeight (big.Int) (struct) + if err := t.DealWeight.MarshalCBOR(w); err != nil { + return err + } + + // t.VerifiedDealWeight (big.Int) (struct) + if err := t.VerifiedDealWeight.MarshalCBOR(w); err != nil { + return err + } + return nil +} + +func (t *SectorWeights) UnmarshalCBOR(r io.Reader) error { + *t = SectorWeights{} + + br := cbg.GetPeeker(r) + scratch := make([]byte, 8) + + maj, extra, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.DealSpace (uint64) (uint64) + + { + + maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.DealSpace = uint64(extra) + + } + // t.DealWeight (big.Int) (struct) + + { + + if err := t.DealWeight.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.DealWeight: %w", err) + } + + } + // t.VerifiedDealWeight (big.Int) (struct) + + { + + if err := t.VerifiedDealWeight.UnmarshalCBOR(br); err != nil { + return xerrors.Errorf("unmarshaling t.VerifiedDealWeight: %w", err) + } + + } + return nil +} + var lengthBufDealState = []byte{131} func (t *DealState) MarshalCBOR(w io.Writer) error { diff --git a/actors/builtin/market/deal.go b/actors/builtin/market/deal.go index 6a7d41519..de0acd544 100644 --- a/actors/builtin/market/deal.go +++ b/actors/builtin/market/deal.go @@ -1,7 +1,18 @@ package market import ( + "bytes" + "fmt" + "io" + + addr "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + acrypto "github.com/filecoin-project/go-state-types/crypto" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" ) //var PieceCIDPrefix = cid.Prefix{ @@ -12,6 +23,147 @@ import ( //} var PieceCIDPrefix = market0.PieceCIDPrefix +// The DealLabel is a "kinded union" -- can either be a String or a byte slice, but not both +// TODO: What represents the empty label and how do we marshall it? +type DealLabel struct { + labelString string + labelBytes []byte +} + +var EmptyDealLabel = DealLabel{} + +func NewDealLabelFromString(s string) (DealLabel, error) { + if len(s) > DealMaxLabelSize { + return EmptyDealLabel, xerrors.Errorf("provided string is too large to be a label (%d), max length (%d)", len(s), DealMaxLabelSize) + } + // TODO: Check UTF-8 + return DealLabel{ + labelString: s, + }, nil +} + +func NewDealLabelFromBytes(b []byte) (DealLabel, error) { + if len(b) > DealMaxLabelSize { + return EmptyDealLabel, xerrors.Errorf("provided bytes are too large to be a label (%d), max length (%d)", len(b), DealMaxLabelSize) + } + // TODO: nilcheck? See note about emptiness. + return DealLabel{ + labelBytes: b, + }, nil +} + +func (label DealLabel) IsStringSet() bool { + return label.labelString == "" +} + +func (label DealLabel) IsBytesSet() bool { + return len(label.labelBytes) != 0 +} + +func (label DealLabel) ToString() (string, error) { + if label.IsBytesSet() { + return "", xerrors.Errorf("label has bytes set") + } + + return label.labelString, nil +} + +func (label DealLabel) ToBytes() ([]byte, error) { + if label.IsStringSet() { + return nil, xerrors.Errorf("label has string set") + } + + return label.labelBytes, nil +} + +func (label DealLabel) Length() int { + if label.IsStringSet() { + return len(label.labelString) + } + + return len(label.labelBytes) +} +func (l DealLabel) Equals(o DealLabel) bool { + return l.labelString == o.labelString && bytes.Equal(l.labelBytes, o.labelBytes) +} + +func (label *DealLabel) MarshalCBOR(w io.Writer) error { + // TODO: Whait if nil? + if label.IsStringSet() && label.IsBytesSet() { + return fmt.Errorf("dealLabel cannot have both string and bytes set") + } + + scratch := make([]byte, 9) + + if label.IsBytesSet() { + if len(label.labelBytes) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("labelBytes is too long to marshal (%d), max allowed (%d)", len(label.labelBytes), cbg.ByteArrayMaxLen) + } + + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajByteString, uint64(len(label.labelBytes))); err != nil { + return err + } + + if _, err := w.Write(label.labelBytes[:]); err != nil { + return err + } + } else { + // "Empty" labels (empty strings and nil bytes) get marshaled as empty strings + if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajTextString, uint64(len(label.labelString))); err != nil { + return err + } + if _, err := io.WriteString(w, label.labelString); err != nil { + return err + } + } + + return nil +} + +func (label *DealLabel) UnmarshalCBOR(br io.Reader) error { + // TODO: Whait if nil? + + scratch := make([]byte, 8) + + maj, length, err := cbg.CborReadHeaderBuf(br, scratch) + if err != nil { + return err + } + + if maj == cbg.MajTextString { + label.labelBytes = nil + if length > cbg.MaxLength { + return fmt.Errorf("label string was too long (%d), max allowed (%d)", length, cbg.MaxLength) + } + + buf := make([]byte, length) + _, err = io.ReadAtLeast(br, buf, int(length)) + if err != nil { + return err + } + + // TODO: Check UTF-8 here too + label.labelString = string(buf) + } else if maj == cbg.MajByteString { + label.labelString = "" + if length > cbg.ByteArrayMaxLen { + return fmt.Errorf("label bytes was too long (%d), max allowed (%d)", length, cbg.ByteArrayMaxLen) + } + + if length > 0 { + label.labelBytes = make([]uint8, length) + } + + if _, err := io.ReadFull(br, label.labelBytes[:]); err != nil { + return err + } + } else { + return fmt.Errorf("unexpected major tag (%d) when unmarshaling DealLabel: only textString (%d) or byteString (%d) expected", maj, cbg.MajTextString, cbg.MajByteString) + } + + return nil +} + // Note: Deal Collateral is only released and returned to clients and miners // when the storage deal stops counting towards power. In the current iteration, // it will be released when the sector containing the storage deals expires, @@ -20,33 +172,54 @@ var PieceCIDPrefix = market0.PieceCIDPrefix // minimal deals that last for a long time. // Note: ClientCollateralPerEpoch may not be needed and removed pending future confirmation. // There will be a Minimum value for both client and provider deal collateral. -//type DealProposal struct { -// PieceCID cid.Cid `checked:"true"` // Checked in validateDeal, CommP -// PieceSize abi.PaddedPieceSize -// VerifiedDeal bool -// Client addr.Address -// Provider addr.Address -// -// // Label is an arbitrary client chosen label to apply to the deal -// // TODO: Limit the size of this: https://github.com/filecoin-project/specs-actors/issues/897 -// Label string -// -// // Nominal start epoch. Deal payment is linear between StartEpoch and EndEpoch, -// // with total amount StoragePricePerEpoch * (EndEpoch - StartEpoch). -// // Storage deal must appear in a sealed (proven) sector no later than StartEpoch, -// // otherwise it is invalid. -// StartEpoch abi.ChainEpoch -// EndEpoch abi.ChainEpoch -// StoragePricePerEpoch abi.TokenAmount -// -// ProviderCollateral abi.TokenAmount -// ClientCollateral abi.TokenAmount -//} -type DealProposal = market0.DealProposal +type DealProposal struct { + PieceCID cid.Cid `checked:"true"` // Checked in validateDeal, CommP + PieceSize abi.PaddedPieceSize + VerifiedDeal bool + Client addr.Address + Provider addr.Address + + // Label is an arbitrary client chosen label to apply to the deal + Label DealLabel + + // Nominal start epoch. Deal payment is linear between StartEpoch and EndEpoch, + // with total amount StoragePricePerEpoch * (EndEpoch - StartEpoch). + // Storage deal must appear in a sealed (proven) sector no later than StartEpoch, + // otherwise it is invalid. + StartEpoch abi.ChainEpoch + EndEpoch abi.ChainEpoch + StoragePricePerEpoch abi.TokenAmount + + ProviderCollateral abi.TokenAmount + ClientCollateral abi.TokenAmount +} // ClientDealProposal is a DealProposal signed by a client -// type ClientDealProposal struct { -// Proposal DealProposal -// ClientSignature crypto.Signature -// } -type ClientDealProposal = market0.ClientDealProposal +type ClientDealProposal struct { + Proposal DealProposal + ClientSignature acrypto.Signature +} + +func (p *DealProposal) Duration() abi.ChainEpoch { + return p.EndEpoch - p.StartEpoch +} + +func (p *DealProposal) TotalStorageFee() abi.TokenAmount { + return big.Mul(p.StoragePricePerEpoch, big.NewInt(int64(p.Duration()))) +} + +func (p *DealProposal) ClientBalanceRequirement() abi.TokenAmount { + return big.Add(p.ClientCollateral, p.TotalStorageFee()) +} + +func (p *DealProposal) ProviderBalanceRequirement() abi.TokenAmount { + return p.ProviderCollateral +} + +func (p *DealProposal) Cid() (cid.Cid, error) { + buf := new(bytes.Buffer) + if err := p.MarshalCBOR(buf); err != nil { + return cid.Undef, err + } + return abi.CidBuilder.Sum(buf.Bytes()) +} diff --git a/actors/builtin/market/market_actor.go b/actors/builtin/market/market_actor.go index af82b4f7b..9368f4198 100644 --- a/actors/builtin/market/market_actor.go +++ b/actors/builtin/market/market_actor.go @@ -140,10 +140,9 @@ func (a Actor) AddBalance(rt Runtime, providerOrClientAddress *addr.Address) *ab return nil } -// type PublishStorageDealsParams struct { -// Deals []ClientDealProposal -// } -type PublishStorageDealsParams = market0.PublishStorageDealsParams +type PublishStorageDealsParams struct { + Deals []ClientDealProposal +} //type PublishStorageDealsReturn struct { // IDs []abi.DealID @@ -800,8 +799,8 @@ func validateDeal(rt Runtime, deal ClientDealProposal, networkRawPower, networkQ proposal := deal.Proposal - if len(proposal.Label) > DealMaxLabelSize { - return xerrors.Errorf("deal label can be at most %d bytes, is %d", DealMaxLabelSize, len(proposal.Label)) + if proposal.Label.Length() > DealMaxLabelSize { + return xerrors.Errorf("deal label can be at most %d bytes, is %d", DealMaxLabelSize, proposal.Label.Length()) } if err := proposal.PieceSize.Validate(); err != nil { diff --git a/actors/builtin/market/market_test.go b/actors/builtin/market/market_test.go index daec3facb..a315321f2 100644 --- a/actors/builtin/market/market_test.go +++ b/actors/builtin/market/market_test.go @@ -2415,8 +2415,10 @@ func TestMarketActorDeals(t *testing.T) { rt.Verify() } - dealProposal.Label = "foo" + label, err := market.NewDealLabelFromString("foo") + assert.NoError(t, err) + dealProposal.Label = label // Same deal with a different label should work { rt.SetCaller(worker, builtin.AccountActorCodeID) @@ -2443,31 +2445,38 @@ func TestMaxDealLabelSize(t *testing.T) { actor.addParticipantFunds(rt, client, abi.NewTokenAmount(20000000)) dealProposal := generateDealProposal(client, provider, abi.ChainEpoch(1), abi.ChainEpoch(200*builtin.EpochsInDay)) - dealProposal.Label = string(make([]byte, market.DealMaxLabelSize)) - params := &market.PublishStorageDealsParams{Deals: []market.ClientDealProposal{{Proposal: dealProposal}}} - // Label at max size should work. - { - rt.SetCaller(worker, builtin.AccountActorCodeID) - actor.publishDeals(rt, minerAddrs, publishDealReq{deal: dealProposal}) - } + label, err := market.NewDealLabelFromString(string(make([]byte, market.DealMaxLabelSize))) + assert.NoError(t, err) - dealProposal.Label = string(make([]byte, market.DealMaxLabelSize+1)) + dealProposal.Label = label + //params := &market.PublishStorageDealsParams{Deals: []market.ClientDealProposal{{Proposal: dealProposal}}} - // Label greater than max size should fail. + // DealLabel at max size should work. { - rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID) - rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0) - expectQueryNetworkInfo(rt, actor) - rt.ExpectVerifySignature(crypto.Signature{}, client, mustCbor(¶ms.Deals[0].Proposal), nil) rt.SetCaller(worker, builtin.AccountActorCodeID) - rt.ExpectAbort(exitcode.ErrIllegalArgument, func() { - rt.Call(actor.PublishStorageDeals, params) - }) - - rt.Verify() + actor.publishDeals(rt, minerAddrs, publishDealReq{deal: dealProposal}) } - actor.checkState(rt) + + //label, err = market.NewDealLabelFromString(string(make([]byte, market.DealMaxLabelSize+1))) + //assert.NoError(t, err) + // + //dealProposal.Label = label + + // DealLabel greater than max size should fail. + //{ + // rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID) + // rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0) + // expectQueryNetworkInfo(rt, actor) + // rt.ExpectVerifySignature(crypto.Signature{}, client, mustCbor(¶ms.Deals[0].Proposal), nil) + // rt.SetCaller(worker, builtin.AccountActorCodeID) + // rt.ExpectAbort(exitcode.ErrIllegalArgument, func() { + // rt.Call(actor.PublishStorageDeals, params) + // }) + // + // rt.Verify() + //} + //actor.checkState(rt) } func TestComputeDataCommitment(t *testing.T) { @@ -3266,7 +3275,10 @@ func (h *marketActorTestHarness) generateAndPublishDealForPiece(rt *mock.Runtime clientCollateral := big.NewInt(10) providerCollateral := big.NewInt(10) - deal := market.DealProposal{PieceCID: pieceCID, PieceSize: pieceSize, Client: client, Provider: minerAddrs.provider, Label: "label", StartEpoch: startEpoch, + label, err := market.NewDealLabelFromString("label") + assert.NoError(h.t, err) + + deal := market.DealProposal{PieceCID: pieceCID, PieceSize: pieceSize, Client: client, Provider: minerAddrs.provider, Label: label, StartEpoch: startEpoch, EndEpoch: endEpoch, StoragePricePerEpoch: storagePerEpoch, ProviderCollateral: providerCollateral, ClientCollateral: clientCollateral} // add funds @@ -3317,8 +3329,12 @@ func generateDealProposalWithCollateral(client, provider address.Address, provid pieceCid := tutil.MakeCID("1", &market.PieceCIDPrefix) pieceSize := abi.PaddedPieceSize(2048) storagePerEpoch := big.NewInt(10) + label, err := market.NewDealLabelFromString("label") + if err != nil { + panic(err) + } - return market.DealProposal{PieceCID: pieceCid, PieceSize: pieceSize, Client: client, Provider: provider, Label: "label", StartEpoch: startEpoch, + return market.DealProposal{PieceCID: pieceCid, PieceSize: pieceSize, Client: client, Provider: provider, Label: label, StartEpoch: startEpoch, EndEpoch: endEpoch, StoragePricePerEpoch: storagePerEpoch, ProviderCollateral: providerCollateral, ClientCollateral: clientCollateral} } diff --git a/actors/test/common_test.go b/actors/test/common_test.go index 09c5fb0b4..6c0cbcc18 100644 --- a/actors/test/common_test.go +++ b/actors/test/common_test.go @@ -3,6 +3,7 @@ package test import ( "bytes" "fmt" + "github.com/stretchr/testify/assert" "testing" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" @@ -108,13 +109,16 @@ func createMiner(t *testing.T, v *vm.VM, owner, worker addr.Address, wPoStProof func publishDeal(t *testing.T, v *vm.VM, provider, dealClient, minerID addr.Address, dealLabel string, pieceSize abi.PaddedPieceSize, verifiedDeal bool, dealStart abi.ChainEpoch, dealLifetime abi.ChainEpoch, ) *market.PublishStorageDealsReturn { + label, err := market.NewDealLabelFromString("label") + assert.NoError(t, err) + deal := market.DealProposal{ PieceCID: tutil.MakeCID(dealLabel, &market.PieceCIDPrefix), PieceSize: pieceSize, VerifiedDeal: verifiedDeal, Client: dealClient, Provider: minerID, - Label: dealLabel, + Label: label, StartEpoch: dealStart, EndEpoch: dealStart + dealLifetime, StoragePricePerEpoch: abi.NewTokenAmount(1 << 20), @@ -123,7 +127,7 @@ func publishDeal(t *testing.T, v *vm.VM, provider, dealClient, minerID addr.Addr } paramBuf := new(bytes.Buffer) - err := deal.MarshalCBOR(paramBuf) + err = deal.MarshalCBOR(paramBuf) require.NoError(t, err) publishDealParams := market.PublishStorageDealsParams{ @@ -175,13 +179,16 @@ func newDealBatcher(v *vm.VM) *dealBatcher { func (db *dealBatcher) stage(t *testing.T, dealClient, dealProvider addr.Address, dealLabel string, pieceSize abi.PaddedPieceSize, verifiedDeal bool, dealStart, dealLifetime abi.ChainEpoch, pricePerEpoch, providerCollateral, clientCollateral abi.TokenAmount) { + label, err := market.NewDealLabelFromString("label") + assert.NoError(t, err) + deal := market.DealProposal{ PieceCID: tutil.MakeCID(dealLabel, &market.PieceCIDPrefix), PieceSize: pieceSize, VerifiedDeal: verifiedDeal, Client: dealClient, Provider: dealProvider, - Label: dealLabel, + Label: label, StartEpoch: dealStart, EndEpoch: dealStart + dealLifetime, StoragePricePerEpoch: pricePerEpoch, diff --git a/gen/gen.go b/gen/gen.go index 65b37bcbe..be73893ea 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -159,7 +159,7 @@ func main() { market.DealState{}, // method params and returns //market.WithdrawBalanceParams{}, // Aliased from v0 - // market.PublishStorageDealsParams{}, // Aliased from v0 + market.PublishStorageDealsParams{}, //market.PublishStorageDealsReturn{}, // Aliased from v6 //market.ActivateDealsParams{}, // Aliased from v0 //market.VerifyDealsForActivationParams{}, // Aliased from v3 @@ -168,11 +168,11 @@ func main() { //market.ComputeDataCommitmentReturn{}, // Aliased from v5 //market.OnMinerSectorsTerminateParams{}, // Aliased from v0 // other types - //market.DealProposal{}, // Aliased from v0 - //market.ClientDealProposal{}, - //market.SectorDeals{}, // Aliased from v3 - //market.SectorWeights{}, // Aliased from v3 - //market.SectorDataSpec{}, // Aliased from v5 + market.DealProposal{}, // Changed in v7 + market.ClientDealProposal{}, // Changed in v7 + market.SectorDeals{}, + market.SectorWeights{}, + market.DealState{}, ); err != nil { panic(err) } diff --git a/support/agent/deal_client_agent.go b/support/agent/deal_client_agent.go index 4e495385c..b07361517 100644 --- a/support/agent/deal_client_agent.go +++ b/support/agent/deal_client_agent.go @@ -155,14 +155,17 @@ func (dca *DealClientAgent) createDeal(s SimState, provider DealProvider) error } dca.expectedMarketBalance = big.Sub(dca.expectedMarketBalance, storageFee) - + label, err := market.NewDealLabelFromString(dca.account.String() + ":" + strconv.Itoa(dca.DealCount)) + if err != nil { + return err + } proposal := market.DealProposal{ PieceCID: pieceCid, PieceSize: abi.PaddedPieceSize(pieceSize), VerifiedDeal: false, Client: dca.account, Provider: provider.Address(), - Label: dca.account.String() + ":" + strconv.Itoa(dca.DealCount), + Label: label, StartEpoch: dealStart, EndEpoch: dealEnd, StoragePricePerEpoch: price,