diff --git a/api/api_storage.go b/api/api_storage.go index 6ce8e7f2e..6d8fe384e 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -57,6 +57,7 @@ type StorageMiner interface { DealsImportData(ctx context.Context, dealPropCid cid.Cid, file string) error DealsList(ctx context.Context) ([]storagemarket.StorageDeal, error) DealsSetAcceptingStorageDeals(context.Context, bool) error + DealsSetAcceptingRetrievalDeals(context.Context, bool) error DealsPieceCidBlocklist(context.Context) ([]cid.Cid, error) DealsSetPieceCidBlocklist(context.Context, []cid.Cid) error diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index e09b57df6..0c0acd05e 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -224,11 +224,12 @@ type StorageMinerStruct struct { StorageLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) error `perm:"admin"` StorageTryLock func(ctx context.Context, sector abi.SectorID, read stores.SectorFileType, write stores.SectorFileType) (bool, error) `perm:"admin"` - DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"` - DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"` - DealsSetAcceptingStorageDeals func(context.Context, bool) error `perm:"admin"` - DealsPieceCidBlocklist func(context.Context) ([]cid.Cid, error) `perm:"admin"` - DealsSetPieceCidBlocklist func(context.Context, []cid.Cid) error `perm:"read"` + DealsImportData func(ctx context.Context, dealPropCid cid.Cid, file string) error `perm:"write"` + DealsList func(ctx context.Context) ([]storagemarket.StorageDeal, error) `perm:"read"` + DealsSetAcceptingStorageDeals func(context.Context, bool) error `perm:"admin"` + DealsSetAcceptingRetrievalDeals func(context.Context, bool) error `perm:"admin"` + DealsPieceCidBlocklist func(context.Context) ([]cid.Cid, error) `perm:"admin"` + DealsSetPieceCidBlocklist func(context.Context, []cid.Cid) error `perm:"read"` StorageAddLocal func(ctx context.Context, path string) error `perm:"admin"` } @@ -881,6 +882,10 @@ func (c *StorageMinerStruct) DealsSetAcceptingStorageDeals(ctx context.Context, return c.Internal.DealsSetAcceptingStorageDeals(ctx, b) } +func (c *StorageMinerStruct) DealsSetAcceptingRetrievalDeals(ctx context.Context, b bool) error { + return c.Internal.DealsSetAcceptingRetrievalDeals(ctx, b) +} + func (c *StorageMinerStruct) DealsPieceCidBlocklist(ctx context.Context) ([]cid.Cid, error) { return c.Internal.DealsPieceCidBlocklist(ctx) } diff --git a/cmd/lotus-storage-miner/main.go b/cmd/lotus-storage-miner/main.go index bda94f54a..62efe9370 100644 --- a/cmd/lotus-storage-miner/main.go +++ b/cmd/lotus-storage-miner/main.go @@ -23,7 +23,8 @@ func main() { local := []*cli.Command{ actorCmd, - dealsCmd, + storageDealsCmd, + retrievalDealsCmd, infoCmd, initCmd, rewardsCmd, diff --git a/cmd/lotus-storage-miner/market.go b/cmd/lotus-storage-miner/market.go index c668456f0..e658be1cf 100644 --- a/cmd/lotus-storage-miner/market.go +++ b/cmd/lotus-storage-miner/market.go @@ -217,9 +217,9 @@ var getAskCmd = &cli.Command{ }, } -var dealsCmd = &cli.Command{ - Name: "deals", - Usage: "interact with your deals", +var storageDealsCmd = &cli.Command{ + Name: "storage-deals", + Usage: "Manage storage deals and related configuration", Subcommands: []*cli.Command{ dealsImportDataCmd, dealsListCmd, diff --git a/cmd/lotus-storage-miner/retrieval-deals.go b/cmd/lotus-storage-miner/retrieval-deals.go new file mode 100644 index 000000000..ee503fb2b --- /dev/null +++ b/cmd/lotus-storage-miner/retrieval-deals.go @@ -0,0 +1,45 @@ +package main + +import ( + lcli "github.com/filecoin-project/lotus/cli" + "github.com/urfave/cli/v2" +) + +var retrievalDealsCmd = &cli.Command{ + Name: "retrieval-deals", + Usage: "Manage retrieval deals and related configuration", + Subcommands: []*cli.Command{ + enableRetrievalCmd, + disableRetrievalCmd, + }, +} + +var enableRetrievalCmd = &cli.Command{ + Name: "enable", + Usage: "Configure the miner to consider retrieval deal proposals", + Flags: []cli.Flag{}, + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + return api.DealsSetAcceptingRetrievalDeals(lcli.DaemonContext(cctx), true) + }, +} + +var disableRetrievalCmd = &cli.Command{ + Name: "disable", + Usage: "Configure the miner to reject all retrieval deal proposals", + Flags: []cli.Flag{}, + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + return api.DealsSetAcceptingRetrievalDeals(lcli.DaemonContext(cctx), false) + }, +} diff --git a/node/builder.go b/node/builder.go index 3b6c6fbda..6b987dc28 100644 --- a/node/builder.go +++ b/node/builder.go @@ -313,6 +313,8 @@ func Online() Option { Override(new(gen.WinningPoStProver), storage.NewWinningPoStProver), Override(new(*miner.Miner), modules.SetupBlockProducer), + Override(new(dtypes.AcceptingRetrievalDealsConfigFunc), modules.NewAcceptingRetrievalDealsConfigFunc), + Override(new(dtypes.SetAcceptingRetrievalDealsConfigFunc), modules.NewSetAcceptingRetrievalDealsConfigFunc), Override(new(dtypes.AcceptingStorageDealsConfigFunc), modules.NewAcceptingStorageDealsConfigFunc), Override(new(dtypes.SetAcceptingStorageDealsConfigFunc), modules.NewSetAcceptingStorageDealsConfigFunc), Override(new(dtypes.StorageDealPieceCidBlocklistConfigFunc), modules.NewStorageDealPieceCidBlocklistConfigFunc), diff --git a/node/config/def.go b/node/config/def.go index 76a6a89ea..a86f87d24 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -34,8 +34,9 @@ type StorageMiner struct { } type DealmakingConfig struct { - AcceptingStorageDeals bool - PieceCidBlocklist []cid.Cid + AcceptingStorageDeals bool + AcceptingRetrievalDeals bool + PieceCidBlocklist []cid.Cid } // API contains configs for API endpoint @@ -123,8 +124,9 @@ func DefaultStorageMiner() *StorageMiner { }, Dealmaking: DealmakingConfig{ - AcceptingStorageDeals: true, - PieceCidBlocklist: []cid.Cid{}, + AcceptingStorageDeals: true, + AcceptingRetrievalDeals: true, + PieceCidBlocklist: []cid.Cid{}, }, } cfg.Common.API.ListenAddress = "/ip4/127.0.0.1/tcp/2345/http" diff --git a/node/impl/storminer.go b/node/impl/storminer.go index d7a8d4d33..b993d1b46 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -44,6 +44,7 @@ type StorageMinerAPI struct { *stores.Index SetAcceptingStorageDealsConfigFunc dtypes.SetAcceptingStorageDealsConfigFunc + SetAcceptingRetrievalDealsConfigFunc dtypes.SetAcceptingRetrievalDealsConfigFunc StorageDealPieceCidBlocklistConfigFunc dtypes.StorageDealPieceCidBlocklistConfigFunc SetStorageDealPieceCidBlocklistConfigFunc dtypes.SetStorageDealPieceCidBlocklistConfigFunc } @@ -228,6 +229,10 @@ func (sm *StorageMinerAPI) DealsSetAcceptingStorageDeals(ctx context.Context, b return sm.SetAcceptingStorageDealsConfigFunc(b) } +func (sm *StorageMinerAPI) DealsSetAcceptingRetrievalDeals(ctx context.Context, b bool) error { + return sm.SetAcceptingRetrievalDealsConfigFunc(b) +} + func (sm *StorageMinerAPI) DealsImportData(ctx context.Context, deal cid.Cid, fname string) error { fi, err := os.Open(fname) if err != nil { diff --git a/node/modules/dtypes/miner.go b/node/modules/dtypes/miner.go index 584642a3b..9ea8c3440 100644 --- a/node/modules/dtypes/miner.go +++ b/node/modules/dtypes/miner.go @@ -10,14 +10,22 @@ import ( type MinerAddress address.Address type MinerID abi.ActorID -// AcceptingStorageDealsFunc is a function which reads from miner config to -// determine if the user has disabled storage deals (or not). +// AcceptingStorageDealsConfigFunc is a function which reads from miner config +// to determine if the user has disabled storage deals (or not). type AcceptingStorageDealsConfigFunc func() (bool, error) -// SetAcceptingStorageDealsFunc is a function which is used to disable or enable -// storage deal acceptance. +// SetAcceptingStorageDealsConfigFunc is a function which is used to disable or +// enable storage deal acceptance. type SetAcceptingStorageDealsConfigFunc func(bool) error +// AcceptingRetrievalDealsConfigFunc is a function which reads from miner config +// to determine if the user has disabled retrieval acceptance (or not). +type AcceptingRetrievalDealsConfigFunc func() (bool, error) + +// SetAcceptingRetrievalDealsConfigFunc is a function which is used to disable +// or enable retrieval deal acceptance. +type SetAcceptingRetrievalDealsConfigFunc func(bool) error + // StorageDealPieceCidBlocklistConfigFunc is a function which reads from miner config // to obtain a list of CIDs for which the storage miner will not accept storage // proposals. diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index c6cadec34..3ccc5daa7 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -357,14 +357,31 @@ func StorageProvider(minerAddress dtypes.MinerAddress, ffiConfig *ffiwrapper.Con } // RetrievalProvider creates a new retrieval provider attached to the provider blockstore -func RetrievalProvider(h host.Host, miner *storage.Miner, sealer sectorstorage.SectorManager, full lapi.FullNode, ds dtypes.MetadataDS, pieceStore dtypes.ProviderPieceStore, ibs dtypes.StagingBlockstore) (retrievalmarket.RetrievalProvider, error) { +func RetrievalProvider(h host.Host, miner *storage.Miner, sealer sectorstorage.SectorManager, full lapi.FullNode, ds dtypes.MetadataDS, pieceStore dtypes.ProviderPieceStore, ibs dtypes.StagingBlockstore, isAcceptingFunc dtypes.AcceptingRetrievalDealsConfigFunc) (retrievalmarket.RetrievalProvider, error) { adapter := retrievaladapter.NewRetrievalProviderNode(miner, sealer, full) - address, err := minerAddrFromDS(ds) + + maddr, err := minerAddrFromDS(ds) if err != nil { return nil, err } - network := rmnet.NewFromLibp2pHost(h) - return retrievalimpl.NewProvider(address, adapter, network, pieceStore, ibs, namespace.Wrap(ds, datastore.NewKey("/retrievals/provider"))) + + netwk := rmnet.NewFromLibp2pHost(h) + + opt := retrievalimpl.DealDeciderOpt(func(ctx context.Context, state retrievalmarket.ProviderDealState) (bool, string, error) { + b, err := isAcceptingFunc() + if err != nil { + return false, "miner error", err + } + + if !b { + log.Warn("retrieval deal acceptance disabled; rejecting retrieval deal proposal from client") + return false, "miner is not accepting retrieval deals", nil + } + + return true, "", nil + }) + + return retrievalimpl.NewProvider(maddr, adapter, netwk, pieceStore, ibs, namespace.Wrap(ds, datastore.NewKey("/retrievals/provider")), opt) } func SectorStorage(mctx helpers.MetricsCtx, lc fx.Lifecycle, ls stores.LocalStorage, si stores.SectorIndex, cfg *ffiwrapper.Config, sc sectorstorage.SealerConfig, urls sectorstorage.URLs, sa sectorstorage.StorageAuth) (*sectorstorage.Manager, error) { @@ -399,6 +416,24 @@ func StorageAuth(ctx helpers.MetricsCtx, ca lapi.Common) (sectorstorage.StorageA return sectorstorage.StorageAuth(headers), nil } +func NewAcceptingRetrievalDealsConfigFunc(r repo.LockedRepo) (dtypes.AcceptingRetrievalDealsConfigFunc, error) { + return func() (out bool, err error) { + err = readCfg(r, func(cfg *config.StorageMiner) { + out = cfg.Dealmaking.AcceptingRetrievalDeals + }) + return + }, nil +} + +func NewSetAcceptingRetrievalDealsConfigFunc(r repo.LockedRepo) (dtypes.SetAcceptingRetrievalDealsConfigFunc, error) { + return func(b bool) (err error) { + err = mutateCfg(r, func(cfg *config.StorageMiner) { + cfg.Dealmaking.AcceptingRetrievalDeals = b + }) + return + }, nil +} + func NewAcceptingStorageDealsConfigFunc(r repo.LockedRepo) (dtypes.AcceptingStorageDealsConfigFunc, error) { return func() (out bool, err error) { err = readCfg(r, func(cfg *config.StorageMiner) {