diff --git a/cbor_gen.go b/cbor_gen.go index eb6143ff7..42a54c103 100644 --- a/cbor_gen.go +++ b/cbor_gen.go @@ -132,7 +132,7 @@ func (t *DealInfo) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{162}); err != nil { + if _, err := w.Write([]byte{163}); err != nil { return err } @@ -167,6 +167,22 @@ func (t *DealInfo) MarshalCBOR(w io.Writer) error { if err := t.DealSchedule.MarshalCBOR(w); err != nil { return err } + + // t.KeepUnsealed (bool) (bool) + if len("KeepUnsealed") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"KeepUnsealed\" was too long") + } + + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len("KeepUnsealed")))); err != nil { + return err + } + if _, err := w.Write([]byte("KeepUnsealed")); err != nil { + return err + } + + if err := cbg.WriteBool(w, t.KeepUnsealed); err != nil { + return err + } return nil } @@ -225,6 +241,24 @@ func (t *DealInfo) UnmarshalCBOR(r io.Reader) error { } } + // t.KeepUnsealed (bool) (bool) + case "KeepUnsealed": + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.KeepUnsealed = false + case 21: + t.KeepUnsealed = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } default: return fmt.Errorf("unknown struct field %d: '%s'", i, name) diff --git a/fsm.go b/fsm.go index e0c53cfce..9f6580854 100644 --- a/fsm.go +++ b/fsm.go @@ -251,8 +251,7 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta // Post-seal case Proving: - // TODO: track sector health / expiration - log.Infof("Proving sector %d", state.SectorNumber) + return m.handleProvingSector, nil case Removing: return m.handleRemoving, nil diff --git a/states_sealing.go b/states_sealing.go index 9659bce7b..113105162 100644 --- a/states_sealing.go +++ b/states_sealing.go @@ -356,9 +356,23 @@ func (m *Sealing) handleCommitWait(ctx statemachine.Context, sector SectorInfo) func (m *Sealing) handleFinalizeSector(ctx statemachine.Context, sector SectorInfo) error { // TODO: Maybe wait for some finality - if err := m.sealer.FinalizeSector(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorNumber), nil); err != nil { + if err := m.sealer.FinalizeSector(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorNumber), sector.keepUnsealedRanges(false)); err != nil { return ctx.Send(SectorFinalizeFailed{xerrors.Errorf("finalize sector: %w", err)}) } return ctx.Send(SectorFinalized{}) } + +func (m *Sealing) handleProvingSector(ctx statemachine.Context, sector SectorInfo) error { + // TODO: track sector health / expiration + log.Infof("Proving sector %d", sector.SectorNumber) + + if err := m.sealer.ReleaseUnsealed(ctx.Context(), m.minerSector(sector.SectorNumber), sector.keepUnsealedRanges(true)); err != nil { + log.Error(err) + } + + // TODO: Watch termination + // TODO: Auto-extend if set + + return nil +} diff --git a/types.go b/types.go index 41e1e0954..255c93a55 100644 --- a/types.go +++ b/types.go @@ -30,6 +30,7 @@ type Piece struct { type DealInfo struct { DealID abi.DealID DealSchedule DealSchedule + KeepUnsealed bool } // DealSchedule communicates the time interval of a storage deal. The deal must @@ -141,6 +142,32 @@ func (t *SectorInfo) sealingCtx(ctx context.Context) context.Context { return ctx } +// Returns list of offset/length tuples of sector data ranges which clients +// requested to keep unsealed +func (t *SectorInfo) keepUnsealedRanges(invert bool) []storage.Range { + var out []storage.Range + + var at abi.UnpaddedPieceSize + for _, piece := range t.Pieces { + psize := piece.Piece.Size.Unpadded() + at += psize + + if piece.DealInfo == nil { + continue + } + if piece.DealInfo.KeepUnsealed == invert { + continue + } + + out = append(out, storage.Range{ + Offset: at - psize, + Size: psize, + }) + } + + return out +} + type SectorIDCounter interface { Next() (abi.SectorNumber, error) }