diff --git a/api/api_storage.go b/api/api_storage.go index bef0a401d1..b8f545ed0d 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -40,6 +40,7 @@ type StorageMiner interface { SectorStartSealing(context.Context, abi.SectorNumber) error SectorsUpdate(context.Context, abi.SectorNumber, SectorState) error SectorRemove(context.Context, abi.SectorNumber) error + SectorMarkForUpgrade(ctx context.Context, id abi.SectorNumber) error StorageList(ctx context.Context) (map[stores.ID][]stores.Decl, error) StorageLocal(ctx context.Context) (map[stores.ID]string, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index c11790e2b5..e93707a8ed 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -202,12 +202,13 @@ type StorageMinerStruct struct { PledgeSector func(context.Context) error `perm:"write"` - SectorsStatus func(context.Context, abi.SectorNumber) (api.SectorInfo, error) `perm:"read"` - SectorsList func(context.Context) ([]abi.SectorNumber, error) `perm:"read"` - SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"` - SectorStartSealing func(context.Context, abi.SectorNumber) error `perm:"write"` - SectorsUpdate func(context.Context, abi.SectorNumber, api.SectorState) error `perm:"admin"` - SectorRemove func(context.Context, abi.SectorNumber) error `perm:"admin"` + SectorsStatus func(context.Context, abi.SectorNumber) (api.SectorInfo, error) `perm:"read"` + SectorsList func(context.Context) ([]abi.SectorNumber, error) `perm:"read"` + SectorsRefs func(context.Context) (map[string][]api.SealedRef, error) `perm:"read"` + SectorStartSealing func(context.Context, abi.SectorNumber) error `perm:"write"` + SectorsUpdate func(context.Context, abi.SectorNumber, api.SectorState) error `perm:"admin"` + SectorRemove func(context.Context, abi.SectorNumber) error `perm:"admin"` + SectorMarkForUpgrade func(ctx context.Context, id abi.SectorNumber) error `perm:"admin"` WorkerConnect func(context.Context, string) error `perm:"admin"` // TODO: worker perm WorkerStats func(context.Context) (map[uint64]storiface.WorkerStats, error) `perm:"admin"` @@ -805,6 +806,10 @@ func (c *StorageMinerStruct) SectorRemove(ctx context.Context, number abi.Sector return c.Internal.SectorRemove(ctx, number) } +func (c *StorageMinerStruct) SectorMarkForUpgrade(ctx context.Context, number abi.SectorNumber) error { + return c.Internal.SectorMarkForUpgrade(ctx, number) +} + func (c *StorageMinerStruct) WorkerConnect(ctx context.Context, url string) error { return c.Internal.WorkerConnect(ctx, url) } diff --git a/api/test/ccupgrade.go b/api/test/ccupgrade.go new file mode 100644 index 0000000000..1151690c77 --- /dev/null +++ b/api/test/ccupgrade.go @@ -0,0 +1,99 @@ +package test + +import ( + "context" + "fmt" + "os" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/specs-actors/actors/abi" + + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/impl" +) + +func TestCCUpgrade(t *testing.T, b APIBuilder, blocktime time.Duration) { + _ = os.Setenv("BELLMAN_NO_GPU", "1") + + ctx := context.Background() + n, sn := b(t, 1, oneMiner) + client := n[0].FullNode.(*impl.FullNodeAPI) + miner := sn[0] + + addrinfo, err := client.NetAddrsListen(ctx) + if err != nil { + t.Fatal(err) + } + + if err := miner.NetConnect(ctx, addrinfo); err != nil { + t.Fatal(err) + } + time.Sleep(time.Second) + + mine := int64(1) + done := make(chan struct{}) + go func() { + defer close(done) + for atomic.LoadInt64(&mine) == 1 { + time.Sleep(blocktime) + if err := sn[0].MineOne(ctx, func(bool) {}); err != nil { + t.Error(err) + } + } + }() + + maddr, err := miner.ActorAddress(ctx) + if err != nil { + t.Fatal(err) + } + + CC := abi.SectorNumber(GenesisPreseals + 1) + Upgraded := CC + 1 + + pledgeSectors(t, ctx, miner, 1) + + sl, err := miner.SectorsList(ctx) + if err != nil { + t.Fatal(err) + } + if len(sl) != 1 { + t.Fatal("expected 1 sector") + } + + if sl[0] != CC { + t.Fatal("bad") + } + + { + si, err := client.StateSectorGetInfo(ctx, maddr, CC, types.EmptyTSK) + require.NoError(t, err) + require.Less(t, 50000, int(si.Expiration)) + } + + if err := miner.SectorMarkForUpgrade(ctx, sl[0]); err != nil { + t.Fatal(err) + } + + makeDeal(t, ctx, 6, client, miner, false) + + // Validate upgrade + + { + si, err := client.StateSectorGetInfo(ctx, maddr, CC, types.EmptyTSK) + require.NoError(t, err) + require.Greater(t, 50000, int(si.Expiration)) + } + { + si, err := client.StateSectorGetInfo(ctx, maddr, Upgraded, types.EmptyTSK) + require.NoError(t, err) + require.Less(t, 50000, int(si.Expiration)) + } + + fmt.Println("shutting down mining") + atomic.AddInt64(&mine, -1) + <-done +} diff --git a/cmd/lotus-storage-miner/sectors.go b/cmd/lotus-storage-miner/sectors.go index 0dfce2f38b..09a963d061 100644 --- a/cmd/lotus-storage-miner/sectors.go +++ b/cmd/lotus-storage-miner/sectors.go @@ -28,6 +28,7 @@ var sectorsCmd = &cli.Command{ sectorsUpdateCmd, sectorsPledgeCmd, sectorsRemoveCmd, + sectorsMarkForUpgradeCmd, }, } @@ -243,6 +244,30 @@ var sectorsRemoveCmd = &cli.Command{ }, } +var sectorsMarkForUpgradeCmd = &cli.Command{ + Name: "mark-for-upgrade", + Usage: "Mark a committed capacity sector for replacement by a sector with deals", + ArgsUsage: "", + Action: func(cctx *cli.Context) error { + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := lcli.ReqContext(cctx) + if cctx.Args().Len() != 1 { + return xerrors.Errorf("must pass sector number") + } + + id, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64) + if err != nil { + return xerrors.Errorf("could not parse sector number: %w", err) + } + + return nodeApi.SectorMarkForUpgrade(ctx, abi.SectorNumber(id)) + }, +} + var sectorsUpdateCmd = &cli.Command{ Name: "update-state", Usage: "ADVANCED: manually update the state of a sector, this may aid in error recovery", diff --git a/go.mod b/go.mod index 197add49e6..d521b248c7 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/filecoin-project/sector-storage v0.0.0-20200701092105-a2de752a3324 github.com/filecoin-project/specs-actors v0.7.1 github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea - github.com/filecoin-project/storage-fsm v0.0.0-20200626155829-408c9a7b3336 + github.com/filecoin-project/storage-fsm v0.0.0-20200701221241-171e0d0e4bf9 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/go-kit/kit v0.10.0 github.com/go-ole/go-ole v1.2.4 // indirect diff --git a/go.sum b/go.sum index 3145e84739..06920d6f24 100644 --- a/go.sum +++ b/go.sum @@ -262,16 +262,14 @@ github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.m github.com/filecoin-project/specs-actors v0.3.0/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y= github.com/filecoin-project/specs-actors v0.6.0/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= github.com/filecoin-project/specs-actors v0.6.1/go.mod h1:dRdy3cURykh2R8O/DKqy8olScl70rmIS7GrB4hB1IDY= -github.com/filecoin-project/specs-actors v0.7.0 h1:tldjW8pFiJcMtyGPsXmPoFdbN/18mKW3BpEMlO4NJAc= -github.com/filecoin-project/specs-actors v0.7.0/go.mod h1:+z0htZu/wLBDbOLcQTKKUEC2rkUTFzL2KJ/bRAVWkws= github.com/filecoin-project/specs-actors v0.7.1 h1:/zW++MN4gGIPvG+s0zmSI97k0Z/aaeiREjLC10gQbco= github.com/filecoin-project/specs-actors v0.7.1/go.mod h1:+z0htZu/wLBDbOLcQTKKUEC2rkUTFzL2KJ/bRAVWkws= github.com/filecoin-project/specs-storage v0.1.0 h1:PkDgTOT5W5Ao7752onjDl4QSv+sgOVdJbvFjOnD5w94= github.com/filecoin-project/specs-storage v0.1.0/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea h1:iixjULRQFPn7Q9KlIqfwLJnlAXO10bbkI+xy5GKGdLY= github.com/filecoin-project/specs-storage v0.1.1-0.20200622113353-88a9704877ea/go.mod h1:Pr5ntAaxsh+sLG/LYiL4tKzvA83Vk5vLODYhfNwOg7k= -github.com/filecoin-project/storage-fsm v0.0.0-20200626155829-408c9a7b3336 h1:zg2YbDReOfovC9g2M7YmtL/RQe0hBZiIOYeuy/NAV4Y= -github.com/filecoin-project/storage-fsm v0.0.0-20200626155829-408c9a7b3336/go.mod h1:e1FIsgLiVFP0ybBdHeGEbhCu3idjCDtEJj+hMgaSJpI= +github.com/filecoin-project/storage-fsm v0.0.0-20200701221241-171e0d0e4bf9 h1:X6TkCA+aT0TJxjL8S8agEVjqHBVgIe9WrvdHlYcNW3M= +github.com/filecoin-project/storage-fsm v0.0.0-20200701221241-171e0d0e4bf9/go.mod h1:SXO4VnXG056B/lXHL8HZv54eMqlsyynm+v93BlLwlOY= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 0f915a7e95..9efd2d174c 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -189,6 +189,10 @@ func (sm *StorageMinerAPI) SectorRemove(ctx context.Context, id abi.SectorNumber return sm.Miner.RemoveSector(ctx, id) } +func (sm *StorageMinerAPI) SectorMarkForUpgrade(ctx context.Context, id abi.SectorNumber) error { + return sm.Miner.MarkForUpgrade(id) +} + func (sm *StorageMinerAPI) WorkerConnect(ctx context.Context, url string) error { w, err := connectRemoteWorker(ctx, sm, url) if err != nil { diff --git a/node/node_test.go b/node/node_test.go index fdba20e822..12d4b305e7 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -530,3 +530,13 @@ func TestWindowedPost(t *testing.T) { test.TestWindowPost(t, mockSbBuilder, 5*time.Millisecond, 10) } + +func TestCCUpgrade(t *testing.T) { + logging.SetLogLevel("miner", "ERROR") + logging.SetLogLevel("chainstore", "ERROR") + logging.SetLogLevel("chain", "ERROR") + logging.SetLogLevel("sub", "ERROR") + logging.SetLogLevel("storageminer", "ERROR") + + test.TestCCUpgrade(t, mockSbBuilder, 5*time.Millisecond) +} diff --git a/storage/sealing.go b/storage/sealing.go index 75a1c50114..3176017bfb 100644 --- a/storage/sealing.go +++ b/storage/sealing.go @@ -43,3 +43,7 @@ func (m *Miner) ForceSectorState(ctx context.Context, id abi.SectorNumber, state func (m *Miner) RemoveSector(ctx context.Context, id abi.SectorNumber) error { return m.sealing.Remove(ctx, id) } + +func (m *Miner) MarkForUpgrade(id abi.SectorNumber) error { + return m.sealing.MarkForUpgrade(id) +}