diff --git a/actors/builtin/market/cbor_gen.go b/actors/builtin/market/cbor_gen.go index 4ed5bd11c..a459c7830 100644 --- a/actors/builtin/market/cbor_gen.go +++ b/actors/builtin/market/cbor_gen.go @@ -398,3 +398,386 @@ func (t *DealState) UnmarshalCBOR(r io.Reader) error { } return nil } + +var lengthBufActivateDealsParams = []byte{129} + +func (t *ActivateDealsParams) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufActivateDealsParams); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Sectors ([]market.ActivateDealsParamsInner) (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 *ActivateDealsParams) UnmarshalCBOR(r io.Reader) error { + *t = ActivateDealsParams{} + + 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.ActivateDealsParamsInner) (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([]ActivateDealsParamsInner, extra) + } + + for i := 0; i < int(extra); i++ { + + var v ActivateDealsParamsInner + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Sectors[i] = v + } + + return nil +} + +var lengthBufActivateDealsParamsInner = []byte{130} + +func (t *ActivateDealsParamsInner) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufActivateDealsParamsInner); 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.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 + } + } + return nil +} + +func (t *ActivateDealsParamsInner) UnmarshalCBOR(r io.Reader) error { + *t = ActivateDealsParamsInner{} + + 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.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) + } + return nil +} + +var lengthBufActivateDealsReturn = []byte{129} + +func (t *ActivateDealsReturn) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufActivateDealsReturn); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Sectors ([]market.ActivateDealsReturnInner) (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 *ActivateDealsReturn) UnmarshalCBOR(r io.Reader) error { + *t = ActivateDealsReturn{} + + 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.ActivateDealsReturnInner) (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([]ActivateDealsReturnInner, extra) + } + + for i := 0; i < int(extra); i++ { + + var v ActivateDealsReturnInner + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Sectors[i] = v + } + + return nil +} + +var lengthBufActivateDealsReturnInner = []byte{132} + +func (t *ActivateDealsReturnInner) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write(lengthBufActivateDealsReturnInner); err != nil { + return err + } + + scratch := make([]byte, 9) + + // t.Success (bool) (bool) + if err := cbg.WriteBool(w, t.Success); err != nil { + return err + } + + // 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 *ActivateDealsReturnInner) UnmarshalCBOR(r io.Reader) error { + *t = ActivateDealsReturnInner{} + + 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 != 4 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Success (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.Success = false + case 21: + t.Success = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // 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 +} diff --git a/actors/builtin/market/market_actor.go b/actors/builtin/market/market_actor.go index 116277297..edd9015cd 100644 --- a/actors/builtin/market/market_actor.go +++ b/actors/builtin/market/market_actor.go @@ -406,15 +406,32 @@ func (a Actor) VerifyDealsForActivation(rt Runtime, params *VerifyDealsForActiva } } -//type ActivateDealsParams struct { -// DealIDs []abi.DealID -// SectorExpiry abi.ChainEpoch -//} -type ActivateDealsParams = market0.ActivateDealsParams +type ActivateDealsParams struct { + Sectors []ActivateDealsParamsInner +} + +//cbor-gen is annoying +type ActivateDealsParamsInner struct { + DealIDs []abi.DealID + SectorExpiry abi.ChainEpoch +} + +type ActivateDealsReturn struct { + Sectors []ActivateDealsReturnInner +} + +type ActivateDealsReturnInner struct { + Success bool // True if activation was a success + DealSpace uint64 // Total space in bytes of submitted deals. + DealWeight abi.DealWeight // Total space*time of submitted deals. + VerifiedDealWeight abi.DealWeight // Total space*time of submitted verified deals. +} // Verify that a given set of storage deals is valid for a sector currently being ProveCommitted, // update the market's internal state accordingly. -func (a Actor) ActivateDeals(rt Runtime, params *ActivateDealsParams) *abi.EmptyValue { +// TODO: ActivateDeals somehow needs to check DealSpace <= SectorSize +// currently it was done at precommit +func (a Actor) ActivateDeals(rt Runtime, params *ActivateDealsParams) *ActivateDealsReturn { rt.ValidateImmediateCallerType(builtin.StorageMinerActorCodeID) minerAddr := rt.Caller() currEpoch := rt.CurrEpoch() @@ -422,50 +439,83 @@ func (a Actor) ActivateDeals(rt Runtime, params *ActivateDealsParams) *abi.Empty var st State store := adt.AsStore(rt) + res := make([]ActivateDealsReturnInner, len(params.Sectors)) + // Update deal dealStates. rt.StateTransaction(&st, func() { - _, _, _, err := ValidateDealsForActivation(&st, store, params.DealIDs, minerAddr, params.SectorExpiry, currEpoch) - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to validate dealProposals for activation") - - msm, err := st.mutator(adt.AsStore(rt)).withDealStates(WritePermission). - withPendingProposals(ReadOnlyPermission).withDealProposals(ReadOnlyPermission).build() - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load state") - for _, dealID := range params.DealIDs { - // This construction could be replaced with a single "update deal state" state method, possibly batched - // over all deal ids at once. - _, found, err := msm.dealStates.Get(dealID) - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get state for dealId %d", dealID) - if found { - rt.Abortf(exitcode.ErrIllegalArgument, "deal %d already included in another sector", dealID) + outer: + for i, sector := range params.Sectors { + dealWeight, verifiedWeight, dealSpace, err := ValidateDealsForActivation(&st, store, sector.DealIDs, minerAddr, sector.SectorExpiry, currEpoch) + //builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to validate dealProposals for activation") + if err != nil { + continue outer } - proposal, err := getDealProposal(msm.dealProposals, dealID) - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get dealId %d", dealID) + msm, err := st.mutator(adt.AsStore(rt)).withDealStates(WritePermission). + withPendingProposals(ReadOnlyPermission).withDealProposals(ReadOnlyPermission).build() + builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to load state") + + for _, dealID := range sector.DealIDs { + // This construction could be replaced with a single "update deal state" state method, possibly batched + // over all deal ids at once. + _, found, err := msm.dealStates.Get(dealID) + //builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get state for dealId %d", dealID) + if err != nil { + continue outer + } - propc, err := proposal.Cid() - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to calculate proposal CID") + if found { + //rt.Abortf(exitcode.ErrIllegalArgument, "deal %d already included in another sector", dealID) + if err != nil { + continue outer + } + } + + proposal, err := getDealProposal(msm.dealProposals, dealID) + //builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get dealId %d", dealID) + if err != nil { + continue outer + } + + propc, err := proposal.Cid() + //builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to calculate proposal CID") + if err != nil { + continue outer + } + + has, err := msm.pendingDeals.Has(abi.CidKey(propc)) + //builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get pending proposal %v", propc) + if err != nil { + continue outer + } - has, err := msm.pendingDeals.Has(abi.CidKey(propc)) - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to get pending proposal %v", propc) + if !has { + // rt.Abortf(exitcode.ErrIllegalState, "tried to activate deal that was not in the pending set (%s)", propc) + continue outer + } - if !has { - rt.Abortf(exitcode.ErrIllegalState, "tried to activate deal that was not in the pending set (%s)", propc) + err = msm.dealStates.Set(dealID, &DealState{ + SectorStartEpoch: currEpoch, + LastUpdatedEpoch: epochUndefined, + SlashEpoch: epochUndefined, + }) + builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to set deal state %d", dealID) } - err = msm.dealStates.Set(dealID, &DealState{ - SectorStartEpoch: currEpoch, - LastUpdatedEpoch: epochUndefined, - SlashEpoch: epochUndefined, - }) - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to set deal state %d", dealID) - } + res[i] = ActivateDealsReturnInner{ + Success: true, + DealSpace: dealSpace, + DealWeight: dealWeight, + VerifiedDealWeight: verifiedWeight, + } - err = msm.commitState() - builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush state") + err = msm.commitState() + builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "failed to flush state") + } }) - return nil + return &ActivateDealsReturn{Sectors: res} } //type SectorDataSpec struct { diff --git a/actors/builtin/methods.go b/actors/builtin/methods.go index bbb4f2d3f..0657f87d8 100644 --- a/actors/builtin/methods.go +++ b/actors/builtin/methods.go @@ -103,7 +103,8 @@ var MethodsMiner = struct { PreCommitSectorBatch abi.MethodNum ProveCommitAggregate abi.MethodNum ProveReplicaUpdates abi.MethodNum -}{MethodConstructor, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27} + PreCommitSectorBatch2 abi.MethodNum +}{MethodConstructor, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28} var MethodsVerifiedRegistry = struct { Constructor abi.MethodNum diff --git a/actors/builtin/miner/cbor_gen.go b/actors/builtin/miner/cbor_gen.go index b2972b9f1..5d4fc3fb4 100644 --- a/actors/builtin/miner/cbor_gen.go +++ b/actors/builtin/miner/cbor_gen.go @@ -1367,7 +1367,7 @@ func (t *PowerPair) UnmarshalCBOR(r io.Reader) error { return nil } -var lengthBufSectorPreCommitOnChainInfo = []byte{133} +var lengthBufSectorPreCommitOnChainInfo = []byte{131} func (t *SectorPreCommitOnChainInfo) MarshalCBOR(w io.Writer) error { if t == nil { @@ -1400,16 +1400,6 @@ func (t *SectorPreCommitOnChainInfo) MarshalCBOR(w io.Writer) error { 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 } @@ -1427,7 +1417,7 @@ func (t *SectorPreCommitOnChainInfo) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 5 { + if extra != 3 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -1474,28 +1464,10 @@ func (t *SectorPreCommitOnChainInfo) UnmarshalCBOR(r io.Reader) error { t.PreCommitEpoch = abi.ChainEpoch(extraI) } - // 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 lengthBufSectorPreCommitInfo = []byte{138} +var lengthBufSectorPreCommitInfo = []byte{135} func (t *SectorPreCommitInfo) MarshalCBOR(w io.Writer) error { if t == nil { @@ -1567,27 +1539,16 @@ func (t *SectorPreCommitInfo) MarshalCBOR(w io.Writer) error { } } - // t.ReplaceCapacity (bool) (bool) - if err := cbg.WriteBool(w, t.ReplaceCapacity); err != nil { - return err - } - - // t.ReplaceSectorDeadline (uint64) (uint64) - - if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.ReplaceSectorDeadline)); err != nil { - return err - } - - // t.ReplaceSectorPartition (uint64) (uint64) + // t.UnsealedCID (cid.Cid) (struct) - if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.ReplaceSectorPartition)); err != nil { - return err - } - - // t.ReplaceSectorNumber (abi.SectorNumber) (uint64) - - if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.ReplaceSectorNumber)); err != nil { - return err + if t.UnsealedCID == nil { + if _, err := w.Write(cbg.CborNull); err != nil { + return err + } + } else { + if err := cbg.WriteCidBuf(scratch, w, *t.UnsealedCID); err != nil { + return xerrors.Errorf("failed to write cid field t.UnsealedCID: %w", err) + } } return nil @@ -1607,7 +1568,7 @@ func (t *SectorPreCommitInfo) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 10 { + if extra != 7 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -1745,63 +1706,26 @@ func (t *SectorPreCommitInfo) UnmarshalCBOR(r io.Reader) error { t.Expiration = abi.ChainEpoch(extraI) } - // t.ReplaceCapacity (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.ReplaceCapacity = false - case 21: - t.ReplaceCapacity = true - default: - return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) - } - // t.ReplaceSectorDeadline (uint64) (uint64) + // t.UnsealedCID (cid.Cid) (struct) { - 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.ReplaceSectorDeadline = uint64(extra) - - } - // t.ReplaceSectorPartition (uint64) (uint64) - - { - - maj, extra, err = cbg.CborReadHeaderBuf(br, scratch) + b, err := br.ReadByte() if err != nil { return err } - if maj != cbg.MajUnsignedInt { - return fmt.Errorf("wrong type for uint64 field") - } - t.ReplaceSectorPartition = uint64(extra) - - } - // t.ReplaceSectorNumber (abi.SectorNumber) (uint64) + if b != cbg.CborNull[0] { + if err := br.UnreadByte(); err != nil { + return err + } - { + c, err := cbg.ReadCid(br) + if err != nil { + return xerrors.Errorf("failed to read cid field t.UnsealedCID: %w", err) + } - 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.UnsealedCID = &c } - t.ReplaceSectorNumber = abi.SectorNumber(extra) } return nil diff --git a/actors/builtin/miner/miner_actor.go b/actors/builtin/miner/miner_actor.go index a7c0edefd..7e2bda02d 100644 --- a/actors/builtin/miner/miner_actor.go +++ b/actors/builtin/miner/miner_actor.go @@ -78,6 +78,7 @@ func (a Actor) Exports() []interface{} { 25: a.PreCommitSectorBatch, 26: a.ProveCommitAggregate, 27: a.ProveReplicaUpdates, + 28: a.PreCommitSectorBatch2, } } @@ -676,6 +677,40 @@ type PreCommitSectorBatchParams = miner5.PreCommitSectorBatchParams // This method calculates the sector's power, locks a pre-commit deposit for the sector, stores information about the // sector in state and waits for it to be proven or expire. func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchParams) *abi.EmptyValue { + newSectors := make([]SectorPreCommitInfo, 0, len(params.Sectors)) + for _, pi := range params.Sectors { + if pi.ReplaceCapacity { + rt.Abortf(exitcode.SysErrForbidden, "cc upgrade through precommit discontinued, use lightweight cc upgrade instead") + } + newSectors = append(newSectors, SectorPreCommitInfo{ + SealProof: pi.SealProof, + SectorNumber: pi.SectorNumber, + SealedCID: pi.SealedCID, + SealRandEpoch: pi.SealRandEpoch, + DealIDs: pi.DealIDs, + Expiration: pi.Expiration, + UnsealedCID: nil, + }) + } + + return a.preCommitSectorBatch2Inner(rt, &PreCommitSectorBatch2Params{Sectors: newSectors}, false) +} + +type PreCommitSectorBatch2Params struct { + Sectors []SectorPreCommitInfo +} + +// Pledges the miner to seal and commit some new sectors. +// The caller specifies sector numbers, sealed sector data CIDs, seal randomness epoch, expiration, UnsealedCID, and the IDs +// of any storage deals contained in the sector data. The storage deal proposals should be already submitted +// to the storage market actor. +// This method assumes maximum sector power, locks a pre-commit deposit for the sector, stores information about the +// sector in state and waits for it to be proven or expire. +func (a Actor) PreCommitSectorBatch2(rt Runtime, params *PreCommitSectorBatch2Params) *abi.EmptyValue { + return a.preCommitSectorBatch2Inner(rt, params, true) +} + +func (a Actor) preCommitSectorBatch2Inner(rt Runtime, params *PreCommitSectorBatch2Params, newBehaviour bool) *abi.EmptyValue { currEpoch := rt.CurrEpoch() if len(params.Sectors) == 0 { rt.Abortf(exitcode.ErrIllegalArgument, "batch empty") @@ -685,9 +720,9 @@ func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchPara // Check per-sector preconditions before opening state transaction or sending other messages. challengeEarliest := currEpoch - MaxPreCommitRandomnessLookback - sectorsDeals := make([]market.SectorDeals, len(params.Sectors)) + sectorsDeals := make([]market.SectorDeals, 0) sectorNumbers := bitfield.New() - for i, precommit := range params.Sectors { + for _, precommit := range params.Sectors { // Bitfied.IsSet() is fast when there are only locally-set values. set, err := sectorNumbers.IsSet(uint64(precommit.SectorNumber)) builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "error checking sector number") @@ -714,30 +749,40 @@ func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchPara if precommit.SealRandEpoch < challengeEarliest { rt.Abortf(exitcode.ErrIllegalArgument, "seal challenge epoch %v too old, must be after %v", precommit.SealRandEpoch, challengeEarliest) } + if precommit.UnsealedCID != nil { + if !precommit.UnsealedCID.Defined() { + rt.Abortf(exitcode.ErrIllegalArgument, "unsealed CID undefined") + } + if precommit.UnsealedCID.Prefix() != market.PieceCIDPrefix { + rt.Abortf(exitcode.ErrIllegalArgument, "unsealed CID had wrong prefix") + } + if len(precommit.DealIDs) == 0 { + rt.Abortf(exitcode.ErrIllegalArgument, "UnsealedCID passed when there are no deals") + } + } else { + if newBehaviour && (len(precommit.DealIDs) > 0) { + rt.Abortf(exitcode.ErrIllegalArgument, "UnsealedCID missing when there are deals") + } + } // Require sector lifetime meets minimum by assuming activation happens at last epoch permitted for seal proof. // This could make sector maximum lifetime validation more lenient if the maximum sector limit isn't hit first. maxActivation := currEpoch + MaxProveCommitDuration[precommit.SealProof] validateExpiration(rt, maxActivation, precommit.Expiration, precommit.SealProof) - - if precommit.ReplaceCapacity { - rt.Abortf(exitcode.SysErrForbidden, "cc upgrade through precommit discontinued, use lightweight cc upgrade instead") - } - - sectorsDeals[i] = market.SectorDeals{ - SectorExpiry: precommit.Expiration, - DealIDs: precommit.DealIDs, + if len(precommit.DealIDs) > 0 { + sectorsDeals = append(sectorsDeals, market.SectorDeals{ + SectorExpiry: precommit.Expiration, + DealIDs: precommit.DealIDs, + }) } } // gather information from other actors rewardStats := requestCurrentEpochBlockReward(rt) pwrTotal := requestCurrentTotalPower(rt) - dealWeights := requestDealWeights(rt, sectorsDeals) - if len(dealWeights.Sectors) != len(params.Sectors) { - rt.Abortf(exitcode.ErrIllegalState, "deal weight request returned %d records, expected %d", - len(dealWeights.Sectors), len(params.Sectors)) + if !newBehaviour && len(sectorsDeals) > 0 { + verifyDealsForActivation(rt, sectorsDeals) } store := adt.AsStore(rt) @@ -785,26 +830,15 @@ func (a Actor) PreCommitSectorBatch(rt Runtime, params *PreCommitSectorBatchPara rt.Abortf(exitcode.ErrIllegalArgument, "too many deals for sector %d > %d", len(precommit.DealIDs), dealCountMax) } - // Ensure total deal space does not exceed sector size. - dealWeight := dealWeights.Sectors[i] - if dealWeight.DealSpace > uint64(info.SectorSize) { - rt.Abortf(exitcode.ErrIllegalArgument, "deals too large to fit in sector %d > %d", dealWeight.DealSpace, info.SectorSize) - } - - // Estimate the sector weight using the current epoch as an estimate for activation, - // and compute the pre-commit deposit using that weight. - // The sector's power will be recalculated when it's proven. - duration := precommit.Expiration - currEpoch - sectorWeight := QAPowerForWeight(info.SectorSize, duration, dealWeight.DealWeight, dealWeight.VerifiedDealWeight) + // For PreCommitDeposit we estimate maximum possible power of the sector + sectorWeight := QAPowerMax(info.SectorSize) depositReq := PreCommitDepositForPower(rewardStats.ThisEpochRewardSmoothed, pwrTotal.QualityAdjPowerSmoothed, sectorWeight) // Build on-chain record. chainInfos[i] = &SectorPreCommitOnChainInfo{ - Info: SectorPreCommitInfo(precommit), - PreCommitDeposit: depositReq, - PreCommitEpoch: currEpoch, - DealWeight: dealWeight.DealWeight, - VerifiedDealWeight: dealWeight.VerifiedDealWeight, + Info: SectorPreCommitInfo(precommit), + PreCommitDeposit: depositReq, + PreCommitEpoch: currEpoch, } totalDepositRequired = big.Add(totalDepositRequired, depositReq) @@ -916,6 +950,18 @@ func (a Actor) ProveCommitAggregate(rt Runtime, params *ProveCommitAggregatePara // compute shared verification inputs commDs := requestUnsealedSectorCIDs(rt, computeDataCommitmentsInputs...) + for i, precommit := range precommits { + if len(precommit.Info.DealIDs) > 0 { + if precommit.Info.UnsealedCID != nil { + // new precommit + if !precommit.Info.UnsealedCID.Equals(commDs[i]) { + rt.Abortf(exitcode.ErrIllegalState, "miscomputed UnsealedCID") + } + } else { + // old precommit, no check needed, checked at precommit + } + } + } svis := make([]proof.AggregateSealVerifyInfo, 0) receiver := rt.Receiver() minerActorID, err := addr.IDFromAddress(receiver) @@ -1032,6 +1078,7 @@ func (a Actor) ProveCommitSector(rt Runtime, params *ProveCommitSectorParams) *a DealIDs: precommit.Info.DealIDs, SectorNumber: precommit.Info.SectorNumber, RegisteredSealProof: precommit.Info.SealProof, + UnsealedCID: precommit.Info.UnsealedCID, }) code := rt.Send( @@ -1085,30 +1132,41 @@ func confirmSectorProofsValid(rt Runtime, preCommits []*SectorPreCommitOnChainIn activation := rt.CurrEpoch() // Pre-commits for new sectors. + + var sectorsToActivate []market.ActivateDealsParamsInner + var preCommitsToActivate []*SectorPreCommitOnChainInfo + var validPreCommits []*SectorPreCommitOnChainInfo for _, precommit := range preCommits { if len(precommit.Info.DealIDs) > 0 { - // Check (and activate) storage deals associated to sector. Abort if checks failed. - // TODO: we should batch these calls... - // https://github.com/filecoin-project/specs-actors/issues/474 - code := rt.Send( - builtin.StorageMarketActorAddr, - builtin.MethodsMarket.ActivateDeals, - &market.ActivateDealsParams{ - DealIDs: precommit.Info.DealIDs, - SectorExpiry: precommit.Info.Expiration, - }, - abi.NewTokenAmount(0), - &builtin.Discard{}, - ) - - if code != exitcode.Ok { - rt.Log(rtt.INFO, "failed to activate deals on sector %d, dropping from prove commit set", precommit.Info.SectorNumber) - continue - } + sectorsToActivate = append(sectorsToActivate, market.ActivateDealsParamsInner{ + DealIDs: precommit.Info.DealIDs, + SectorExpiry: precommit.Info.Expiration, + }) + preCommitsToActivate = append(preCommitsToActivate, precommit) + } else { + validPreCommits = append(validPreCommits, precommit) } + } + var activateRes market.ActivateDealsReturn + code := rt.Send( + builtin.StorageMarketActorAddr, + builtin.MethodsMarket.ActivateDeals, + &market.ActivateDealsParams{ + Sectors: sectorsToActivate, + }, + abi.NewTokenAmount(0), + &activateRes, + ) + builtin.RequireSuccess(rt, code, "failed batch deal activation") - validPreCommits = append(validPreCommits, precommit) + sectorWeights := make(map[abi.SectorNumber]market.ActivateDealsReturnInner) + for i, weight := range activateRes.Sectors { + if !weight.Success { + continue + } + sectorWeights[preCommitsToActivate[i].Info.SectorNumber] = weight + validPreCommits = append(validPreCommits, preCommitsToActivate[i]) } // When all prove commits have failed abort early @@ -1134,7 +1192,15 @@ func confirmSectorProofsValid(rt Runtime, preCommits []*SectorPreCommitOnChainIn rt.Log(rtt.WARN, "precommit %d has lifetime %d less than minimum. ignoring", precommit.Info.SectorNumber, duration, MinSectorExpiration) continue } - pwr := QAPowerForWeight(info.SectorSize, duration, precommit.DealWeight, precommit.VerifiedDealWeight) + + dealWeight := big.Zero() + verifiedDealWeight := big.Zero() + if weight, ok := sectorWeights[precommit.Info.SectorNumber]; ok { + dealWeight = weight.DealWeight + verifiedDealWeight = weight.VerifiedDealWeight + } + + pwr := QAPowerForWeight(info.SectorSize, duration, dealWeight, verifiedDealWeight) dayReward := ExpectedRewardForPower(thisEpochRewardSmoothed, qualityAdjPowerSmoothed, pwr, builtin.EpochsInDay) // The storage pledge is recorded for use in computing the penalty if this sector is terminated @@ -1151,8 +1217,8 @@ func confirmSectorProofsValid(rt Runtime, preCommits []*SectorPreCommitOnChainIn DealIDs: precommit.Info.DealIDs, Expiration: precommit.Info.Expiration, Activation: activation, - DealWeight: precommit.DealWeight, - VerifiedDealWeight: precommit.VerifiedDealWeight, + DealWeight: dealWeight, + VerifiedDealWeight: verifiedDealWeight, InitialPledge: initialPledge, ExpectedDayReward: dayReward, ExpectedStoragePledge: storagePledge, @@ -2169,18 +2235,21 @@ func (a Actor) ProveReplicaUpdates(rt Runtime, params *ProveReplicaUpdatesParams continue } + var activateRes market.ActivateDealsReturn code := rt.Send( builtin.StorageMarketActorAddr, builtin.MethodsMarket.ActivateDeals, &market.ActivateDealsParams{ - DealIDs: update.Deals, - SectorExpiry: sectorInfo.Expiration, + Sectors: []market.ActivateDealsParamsInner{{ + DealIDs: update.Deals, + SectorExpiry: sectorInfo.Expiration, + }}, }, abi.NewTokenAmount(0), - &builtin.Discard{}, + &activateRes, ) - if code != exitcode.Ok { + if code != exitcode.Ok || !activateRes.Sectors[0].Success { rt.Log(rtt.INFO, "failed to activate deals, skipping sector %d", update.SectorID) continue } @@ -2751,6 +2820,7 @@ type SealVerifyStuff struct { DealIDs []abi.DealID abi.SectorNumber SealRandEpoch abi.ChainEpoch // Used to tie the seal to a chain. + UnsealedCID *cid.Cid } func getVerifyInfo(rt Runtime, params *SealVerifyStuff) *proof.SealVerifyInfo { @@ -2758,10 +2828,21 @@ func getVerifyInfo(rt Runtime, params *SealVerifyStuff) *proof.SealVerifyInfo { rt.Abortf(exitcode.ErrForbidden, "too early to prove sector") } - commDs := requestUnsealedSectorCIDs(rt, &market.SectorDataSpec{ + commD := requestUnsealedSectorCIDs(rt, &market.SectorDataSpec{ SectorType: params.RegisteredSealProof, DealIDs: params.DealIDs, - }) + })[0] + + if len(params.DealIDs) > 0 { + if params.UnsealedCID != nil { + // new precommit + if !params.UnsealedCID.Equals(commD) { + rt.Abortf(exitcode.ErrIllegalState, "miscomputed UnsealedCID") + } + } else { + // old precommit, no check needed, checked at precommit + } + } minerActorID, err := addr.IDFromAddress(rt.Receiver()) builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "runtime provided non-ID receiver address %v", rt.Receiver()) @@ -2785,7 +2866,7 @@ func getVerifyInfo(rt Runtime, params *SealVerifyStuff) *proof.SealVerifyInfo { Proof: params.Proof, Randomness: abi.SealRandomness(svInfoRandomness), SealedCID: params.SealedCID, - UnsealedCID: commDs[0], + UnsealedCID: commD, } } @@ -2813,6 +2894,25 @@ func requestUnsealedSectorCIDs(rt Runtime, dataCommitmentInputs ...*market.Secto return unsealedCIDs } +func verifyDealsForActivation(rt Runtime, sectors []market.SectorDeals) { + var dealWeights market.VerifyDealsForActivationReturn + code := rt.Send( + builtin.StorageMarketActorAddr, + builtin.MethodsMarket.VerifyDealsForActivation, + &market.VerifyDealsForActivationParams{ + Sectors: sectors, + }, + abi.NewTokenAmount(0), + &dealWeights, + ) + builtin.RequireSuccess(rt, code, "failed to verify deals and get deal weight") + if len(dealWeights.Sectors) != len(sectors) { + rt.Abortf(exitcode.ErrIllegalState, "deal weight request returned %d records, expected %d", + len(dealWeights.Sectors), len(sectors)) + } +} + +// TODO remove?? func requestDealWeights(rt Runtime, sectors []market.SectorDeals) *market.VerifyDealsForActivationReturn { // Short-circuit if there are no deals in any of the sectors. dealCount := 0 @@ -2844,6 +2944,10 @@ func requestDealWeights(rt Runtime, sectors []market.SectorDeals) *market.Verify &dealWeights, ) builtin.RequireSuccess(rt, code, "failed to verify deals and get deal weight") + if len(dealWeights.Sectors) != len(sectors) { + rt.Abortf(exitcode.ErrIllegalState, "deal weight request returned %d records, expected %d", + len(dealWeights.Sectors), len(sectors)) + } return &dealWeights } diff --git a/actors/builtin/miner/miner_commitment_test.go b/actors/builtin/miner/miner_commitment_test.go index 00b15c062..dcc29b30a 100644 --- a/actors/builtin/miner/miner_commitment_test.go +++ b/actors/builtin/miner/miner_commitment_test.go @@ -91,8 +91,6 @@ func TestCommitments(t *testing.T) { // Check precommit expectations. assert.Equal(t, precommitEpoch, precommit.PreCommitEpoch) - assert.Equal(t, dealWeight, precommit.DealWeight) - assert.Equal(t, verifiedDealWeight, precommit.VerifiedDealWeight) assert.Equal(t, test.sectorNo, precommit.Info.SectorNumber) assert.Equal(t, precommitParams.SealProof, precommit.Info.SealProof) @@ -101,7 +99,7 @@ func TestCommitments(t *testing.T) { assert.Equal(t, precommitParams.DealIDs, precommit.Info.DealIDs) assert.Equal(t, precommitParams.Expiration, precommit.Info.Expiration) - pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-precommitEpoch, dealWeight, verifiedDealWeight) + pwrEstimate := miner.QAPowerMax(actor.sectorSize) expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate) assert.Equal(t, expectedDeposit, precommit.PreCommitDeposit) @@ -135,6 +133,7 @@ func TestCommitments(t *testing.T) { }) t.Run("deal space exceeds sector space", func(t *testing.T) { + t.Skip("TODO needs to be moved to ProveCommit") //TODO actor := newHarness(t, periodOffset) rt := builderForHarness(actor). WithBalance(bigBalance, big.Zero()). @@ -546,7 +545,7 @@ func TestPreCommitBatch(t *testing.T) { DealWeight: dealWeight, VerifiedDealWeight: verifiedDealWeight, } - pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, sectors[i].Expiration-precommitEpoch, dealWeight, verifiedDealWeight) + pwrEstimate := miner.QAPowerMax(actor.sectorSize) deposits[i] = miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate) } @@ -573,8 +572,6 @@ func TestPreCommitBatch(t *testing.T) { st := getState(rt) for i := 0; i < batchSize; i++ { assert.Equal(t, precommitEpoch, precommits[i].PreCommitEpoch) - assert.Equal(t, conf.sectorWeights[i].DealWeight, precommits[i].DealWeight) - assert.Equal(t, conf.sectorWeights[i].VerifiedDealWeight, precommits[i].VerifiedDealWeight) assert.Equal(t, sectorNos[i], precommits[i].Info.SectorNumber) assert.Equal(t, sectors[i].SealProof, precommits[i].Info.SealProof) @@ -583,8 +580,7 @@ func TestPreCommitBatch(t *testing.T) { assert.Equal(t, sectors[i].DealIDs, precommits[i].Info.DealIDs) assert.Equal(t, sectors[i].Expiration, precommits[i].Info.Expiration) - pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, precommits[i].Info.Expiration-precommitEpoch, - conf.sectorWeights[i].DealWeight, conf.sectorWeights[i].VerifiedDealWeight) + pwrEstimate := miner.QAPowerMax(actor.sectorSize) expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate) assert.Equal(t, expectedDeposit, precommits[i].PreCommitDeposit) } @@ -676,12 +672,7 @@ func TestProveCommit(t *testing.T) { }, true) // Check precommit - // deal weights must be set in precommit onchain info - assert.Equal(t, dealWeight, precommit.DealWeight) - assert.Equal(t, verifiedDealWeight, precommit.VerifiedDealWeight) - - pwrEstimate := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-precommitEpoch, precommit.DealWeight, precommit.VerifiedDealWeight) - expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, pwrEstimate) + expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize)) assert.Equal(t, expectedDeposit, precommit.PreCommitDeposit) // expect total precommit deposit to equal our new deposit @@ -698,8 +689,6 @@ func TestProveCommit(t *testing.T) { assert.Equal(t, precommit.Info.DealIDs, sector.DealIDs) assert.Equal(t, rt.Epoch(), sector.Activation) assert.Equal(t, precommit.Info.Expiration, sector.Expiration) - assert.Equal(t, precommit.DealWeight, sector.DealWeight) - assert.Equal(t, precommit.VerifiedDealWeight, sector.VerifiedDealWeight) // expect precommit to have been removed st = getState(rt) @@ -712,14 +701,10 @@ func TestProveCommit(t *testing.T) { // The sector is exactly full with verified deals, so expect fully verified power. expectedPower := big.Mul(big.NewInt(int64(actor.sectorSize)), big.Div(builtin.VerifiedDealWeightMultiplier, builtin.QualityBaseMultiplier)) - qaPower := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-rt.Epoch(), precommit.DealWeight, precommit.VerifiedDealWeight) + qaPower := miner.QAPowerForWeight(actor.sectorSize, precommit.Info.Expiration-rt.Epoch(), sector.DealWeight, sector.VerifiedDealWeight) assert.Equal(t, expectedPower, qaPower) sectorPower := miner.NewPowerPair(big.NewIntUnsigned(uint64(actor.sectorSize)), qaPower) - // expect deal weights to be transferred to on chain info - assert.Equal(t, precommit.DealWeight, sector.DealWeight) - assert.Equal(t, precommit.VerifiedDealWeight, sector.VerifiedDealWeight) - // expect initial plege of sector to be set, and be total pledge requirement expectedInitialPledge := miner.InitialPledgeForPower(qaPower, actor.baselinePower, actor.epochRewardSmooth, actor.epochQAPowerSmooth, rt.TotalFilCircSupply()) assert.Equal(t, expectedInitialPledge, sector.InitialPledge) @@ -783,14 +768,10 @@ func TestProveCommit(t *testing.T) { dealLifespan := sectorExpiration - proveCommitEpoch verifiedDealWeight := big.Mul(big.NewIntUnsigned(dealSpace), big.NewInt(int64(dealLifespan))) - // Power estimates made a pre-commit time - noDealPowerEstimate := miner.QAPowerForWeight(actor.sectorSize, sectorExpiration-precommitEpoch, big.Zero(), big.Zero()) - fullDealPowerEstimate := miner.QAPowerForWeight(actor.sectorSize, sectorExpiration-precommitEpoch, dealWeight, verifiedDealWeight) - deposits := []big.Int{ - miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, noDealPowerEstimate), - miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, fullDealPowerEstimate), - miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, fullDealPowerEstimate), + miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize)), + miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize)), + miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, miner.QAPowerMax(actor.sectorSize)), } conf := preCommitBatchConf{ sectorWeights: []market.SectorWeights{ @@ -1422,7 +1403,7 @@ func TestBatchMethodNetworkFees(t *testing.T) { // Give miner enough balance to pay both and pcd balance := big.Mul(big.NewInt(2), netFee) - oneSectorPowerEstimate := miner.QAPowerForWeight(actor.sectorSize, expiration-precommitEpoch, big.Zero(), big.Zero()) + oneSectorPowerEstimate := miner.QAPowerMax(actor.sectorSize) expectedDeposit := miner.PreCommitDepositForPower(actor.epochRewardSmooth, actor.epochQAPowerSmooth, big.Mul(big.NewInt(4), oneSectorPowerEstimate)) balance = big.Add(balance, expectedDeposit) rt.SetBalance(balance) diff --git a/actors/builtin/miner/miner_state.go b/actors/builtin/miner/miner_state.go index ff20ef3d9..652d2e91f 100644 --- a/actors/builtin/miner/miner_state.go +++ b/actors/builtin/miner/miner_state.go @@ -133,28 +133,29 @@ type WorkerKeyChange struct { EffectiveAt abi.ChainEpoch } +// possible states +// (DealIDs > 0, UnsealedCID != nil) => CommD provided by SP, needs to be checked +// (DealIDs > 0, UnsealedCID == nil) => Old method or migration, DealIDs checked at PreCommit (Depracated) +// (DealIDs == 0, UnsealedCID == nil) => NoDeals, CommD of empty sector +// (DealIDs == 0, UnsealedCID != 0) future approach, fail for now // Information provided by a miner when pre-committing a sector. type SectorPreCommitInfo struct { - SealProof abi.RegisteredSealProof - SectorNumber abi.SectorNumber - SealedCID cid.Cid `checked:"true"` // CommR - SealRandEpoch abi.ChainEpoch - DealIDs []abi.DealID - Expiration abi.ChainEpoch - ReplaceCapacity bool // Whether to replace a "committed capacity" no-deal sector (requires non-empty DealIDs) - // The committed capacity sector to replace, and it's deadline/partition location - ReplaceSectorDeadline uint64 - ReplaceSectorPartition uint64 - ReplaceSectorNumber abi.SectorNumber + SealProof abi.RegisteredSealProof + SectorNumber abi.SectorNumber + SealedCID cid.Cid `checked:"true"` // CommR + SealRandEpoch abi.ChainEpoch + DealIDs []abi.DealID + Expiration abi.ChainEpoch + UnsealedCID *cid.Cid `checked:"true"` } // Information stored on-chain for a pre-committed sector. type SectorPreCommitOnChainInfo struct { - Info SectorPreCommitInfo - PreCommitDeposit abi.TokenAmount - PreCommitEpoch abi.ChainEpoch - DealWeight abi.DealWeight // Integral of active deals over sector lifetime - VerifiedDealWeight abi.DealWeight // Integral of active verified deals over sector lifetime + Info SectorPreCommitInfo + PreCommitDeposit abi.TokenAmount + PreCommitEpoch abi.ChainEpoch + //DealWeight abi.DealWeight // Integral of active deals over sector lifetime + //VerifiedDealWeight abi.DealWeight // Integral of active verified deals over sector lifetime } // Information stored on-chain for a proven sector. diff --git a/actors/builtin/miner/miner_state_test.go b/actors/builtin/miner/miner_state_test.go index 2407e3f1e..8bdedff88 100644 --- a/actors/builtin/miner/miner_state_test.go +++ b/actors/builtin/miner/miner_state_test.go @@ -1008,11 +1008,9 @@ func constructStateHarness(t *testing.T, periodBoundary abi.ChainEpoch) *stateHa func newPreCommitOnChain(sectorNo abi.SectorNumber, sealed cid.Cid, deposit abi.TokenAmount, epoch abi.ChainEpoch) *miner.SectorPreCommitOnChainInfo { info := newSectorPreCommitInfo(sectorNo, sealed) return &miner.SectorPreCommitOnChainInfo{ - Info: *info, - PreCommitDeposit: deposit, - PreCommitEpoch: epoch, - DealWeight: big.Zero(), - VerifiedDealWeight: big.Zero(), + Info: *info, + PreCommitDeposit: deposit, + PreCommitEpoch: epoch, } } diff --git a/actors/builtin/miner/miner_test.go b/actors/builtin/miner/miner_test.go index 6af3a4d90..c0abef82f 100644 --- a/actors/builtin/miner/miner_test.go +++ b/actors/builtin/miner/miner_test.go @@ -4166,9 +4166,10 @@ func (h *actorHarness) confirmSectorProofsValidInternal(rt *mock.Runtime, conf p validPrecommits = append(validPrecommits, precommit) if len(precommit.Info.DealIDs) > 0 { vdParams := market.ActivateDealsParams{ - DealIDs: precommit.Info.DealIDs, - SectorExpiry: precommit.Info.Expiration, - } + Sectors: []market.ActivateDealsParamsInner{{ + DealIDs: precommit.Info.DealIDs, + SectorExpiry: precommit.Info.Expiration, + }}} exit, found := conf.verifyDealsExit[precommit.Info.SectorNumber] if found { validPrecommits = validPrecommits[:len(validPrecommits)-1] // pop @@ -4187,21 +4188,18 @@ func (h *actorHarness) confirmSectorProofsValidInternal(rt *mock.Runtime, conf p expectRawPower := big.Zero() for _, precommit := range validPrecommits { precommitOnChain := h.getPreCommit(rt, precommit.Info.SectorNumber) + _ = precommitOnChain duration := precommit.Info.Expiration - rt.Epoch() if duration >= miner.MinSectorExpiration { - qaPowerDelta := miner.QAPowerForWeight(h.sectorSize, duration, precommitOnChain.DealWeight, precommitOnChain.VerifiedDealWeight) + //qaPowerDelta := miner.QAPowerForWeight(h.sectorSize, duration, precommitOnChain.DealWeight, precommitOnChain.VerifiedDealWeight) + // TODO DealWeight access during prove commit + qaPowerDelta := big.Zero() expectQAPower = big.Add(expectQAPower, qaPowerDelta) expectRawPower = big.Add(expectRawPower, big.NewIntUnsigned(uint64(h.sectorSize))) pledge := miner.InitialPledgeForPower(qaPowerDelta, h.baselinePower, h.epochRewardSmooth, h.epochQAPowerSmooth, rt.TotalFilCircSupply()) - // if cc upgrade, pledge is max of new and replaced pledges - if precommitOnChain.Info.ReplaceCapacity { - replaced := h.getSector(rt, precommitOnChain.Info.ReplaceSectorNumber) - pledge = big.Max(pledge, replaced.InitialPledge) - } - expectPledge = big.Add(expectPledge, pledge) } } diff --git a/actors/builtin/miner/monies.go b/actors/builtin/miner/monies.go index 8a2d58c76..0db2c0e03 100644 --- a/actors/builtin/miner/monies.go +++ b/actors/builtin/miner/monies.go @@ -4,7 +4,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/exitcode" - rtt "github.com/filecoin-project/go-state-types/rt" "github.com/filecoin-project/specs-actors/v7/actors/builtin" "github.com/filecoin-project/specs-actors/v7/actors/util/math" @@ -192,7 +191,6 @@ func RepayDebtsOrAbort(rt Runtime, st *State) abi.TokenAmount { currBalance := rt.CurrentBalance() toBurn, err := st.repayDebts(currBalance) builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "unlocked balance can not repay fee debt") - rt.Log(rtt.DEBUG, "RepayDebtsOrAbort was called and succeeded") return toBurn } diff --git a/actors/builtin/miner/policy.go b/actors/builtin/miner/policy.go index e3759d30e..26fc0e54d 100644 --- a/actors/builtin/miner/policy.go +++ b/actors/builtin/miner/policy.go @@ -249,6 +249,13 @@ func QualityForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, return big.Div(big.Div(scaledUpWeightedSumSpaceTime, sectorSpaceTime), builtin.QualityBaseMultiplier) } +func QAPowerMax(size abi.SectorSize) abi.StoragePower { + // return (size * VerifiedDealWeightMultiplier) / QualityBaseMultiplier + // order of operation to preserve maximum precision + // for efficiency we could change definition of VerifiedDealWeightMultiplier to be more efficient + return big.Div(big.Mul(big.NewIntUnsigned(uint64(size)), builtin.VerifiedDealWeightMultiplier), builtin.QualityBaseMultiplier) +} + // The power for a sector size, committed duration, and weight. func QAPowerForWeight(size abi.SectorSize, duration abi.ChainEpoch, dealWeight, verifiedWeight abi.DealWeight) abi.StoragePower { quality := QualityForWeight(size, duration, dealWeight, verifiedWeight) diff --git a/actors/test/commit_post_test.go b/actors/test/commit_post_test.go index 90e1185db..1917a8a6f 100644 --- a/actors/test/commit_post_test.go +++ b/actors/test/commit_post_test.go @@ -282,7 +282,7 @@ func TestMeasurePreCommitGas(t *testing.T) { require.NoError(t, err) addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), builtin.TokenPrecision), 93837778) owner, worker := addrs[0], addrs[0] - minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL)) + minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL)) // Advance vm so we can have seal randomness epoch in the past v, err = v.WithEpoch(abi.ChainEpoch(200)) @@ -327,9 +327,9 @@ func TestMeasurePoRepGas(t *testing.T) { wPoStProof, err := sealProof.RegisteredWindowPoStProof() require.NoError(t, err) - addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(10_000), builtin.TokenPrecision), 93837778) + addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), builtin.TokenPrecision), 93837778) owner, worker := addrs[0], addrs[0] - minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL)) + minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL)) // advance vm so we can have seal randomness epoch in the past v, err = v.WithEpoch(abi.ChainEpoch(200)) @@ -620,14 +620,14 @@ func TestAggregateSizeLimits(t *testing.T) { ctx := context.Background() blkStore := ipld.NewBlockStoreInMemory() v := vm.NewVMWithSingletons(ctx, t, blkStore) - addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(10_000), big.NewInt(1e18)), 93837778) + addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), big.NewInt(1e18)), 93837778) // create miner sealProof := abi.RegisteredSealProof_StackedDrg32GiBV1_1 wPoStProof, err := sealProof.RegisteredWindowPoStProof() require.NoError(t, err) owner, worker := addrs[0], addrs[0] - minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL)) + minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL)) // advance vm so we can have seal randomness epoch in the past v, err = v.WithEpoch(abi.ChainEpoch(200)) @@ -780,9 +780,9 @@ func TestMeasureAggregatePorepGas(t *testing.T) { sealProof := abi.RegisteredSealProof_StackedDrg32GiBV1_1 wPoStProof, err := sealProof.RegisteredWindowPoStProof() require.NoError(t, err) - addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(10_000), builtin.TokenPrecision), 93837778) + addrs := vm.CreateAccounts(ctx, t, v, 1, big.Mul(big.NewInt(100_000), builtin.TokenPrecision), 93837778) owner, worker := addrs[0], addrs[0] - minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(10_000), vm.FIL)) + minerAddrs := createMiner(t, v, owner, worker, wPoStProof, big.Mul(big.NewInt(100_000), vm.FIL)) // advance vm so we can have seal randomness epoch in the past v, err = v.WithEpoch(abi.ChainEpoch(200)) diff --git a/gen/gen.go b/gen/gen.go index d11535e91..472ebc715 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -119,7 +119,7 @@ func main() { // method params and returns //paych.ConstructorParams{}, // Aliased from v0 paych.UpdateChannelStateParams{}, // Changed in v7 - paych.SignedVoucher{}, // Changed in v7 + paych.SignedVoucher{}, // Changed in v7 //paych.ModVerifyParams{}, // Aliased from v0 // other types //paych.Merge{}, // Aliased from v0 @@ -152,7 +152,10 @@ func main() { //market.WithdrawBalanceParams{}, // Aliased from v0 // market.PublishStorageDealsParams{}, // Aliased from v0 //market.PublishStorageDealsReturn{}, // Aliased from v6 - //market.ActivateDealsParams{}, // Aliased from v0 + market.ActivateDealsParams{}, + market.ActivateDealsParamsInner{}, + market.ActivateDealsReturn{}, + market.ActivateDealsReturnInner{}, //market.VerifyDealsForActivationParams{}, // Aliased from v3 //market.VerifyDealsForActivationReturn{}, // Aliased from v3 //market.ComputeDataCommitmentParams{}, // Aliased from v5 @@ -230,9 +233,9 @@ func main() { verifreg.RemoveDataCapParams{}, // New in v7 verifreg.RemoveDataCapReturn{}, // New in v7 // other types - verifreg.RemoveDataCapRequest{}, // New in v7 + verifreg.RemoveDataCapRequest{}, // New in v7 verifreg.RemoveDataCapProposal{}, // New in v7 - verifreg.RmDcProposalID{}, // New in v7 + verifreg.RmDcProposalID{}, // New in v7 ); err != nil { panic(err) } diff --git a/support/agent/cases_test.go b/support/agent/cases_test.go index 39d114980..05630ca36 100644 --- a/support/agent/cases_test.go +++ b/support/agent/cases_test.go @@ -23,7 +23,7 @@ import ( func TestCreate20Miners(t *testing.T) { ctx := context.Background() - initialBalance := big.Mul(big.NewInt(1000), big.NewInt(1e18)) + initialBalance := big.Mul(big.NewInt(10000), big.NewInt(1e18)) minerCount := 20 rnd := rand.New(rand.NewSource(42))