Skip to content

Commit

Permalink
feat: flag to disable funds tagging (#1367)
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkmc authored Apr 27, 2023
1 parent 7d6409b commit 2c6d9fd
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 28 deletions.
69 changes: 41 additions & 28 deletions fundmanager/fundmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type fundManagerAPI interface {
}

type Config struct {
// Whether to enable fund tagging
Enabled bool
// The address of the storage miner, used as the target address when
// moving funds to escrow
StorageMiner address.Address
Expand Down Expand Up @@ -58,13 +60,19 @@ func New(cfg Config) func(api v1api.FullNode, fundsDB *db.FundsDB) *FundManager
}

type TagFundsResp struct {
Collateral abi.TokenAmount
// The amount of deal collateral tagged for this deal
Collateral abi.TokenAmount
// The amount of publish message funds tagged for this deal
PublishMessage abi.TokenAmount

TotalCollateral abi.TokenAmount
// The total amount of deal collateral tagged for all deals so far
TotalCollateral abi.TokenAmount
// The total amount of funds tagged for all publish messages so far
TotalPublishMessage abi.TokenAmount

AvailableCollateral abi.TokenAmount
// The total available funds for deal collateral
AvailableCollateral abi.TokenAmount
// The total available funds for deal publishing
AvailablePublishMessage abi.TokenAmount
}

Expand Down Expand Up @@ -92,39 +100,44 @@ func (m *FundManager) TagFunds(ctx context.Context, dealUuid uuid.UUID, proposal
return nil, fmt.Errorf("getting total tagged: %w", err)
}

dealCollateral := proposal.ProviderBalanceRequirement()
dealCollateralTag := abi.NewTokenAmount(0)
pubMsgTag := abi.NewTokenAmount(0)
availForDealCollat := big.Sub(marketBal.Available, tagged.Collateral)
if availForDealCollat.LessThan(dealCollateral) {
err := fmt.Errorf("%w: available funds %d is less than collateral needed for deal %d: "+
"available = funds in escrow %d - amount reserved for other deals %d",
ErrInsufficientFunds, availForDealCollat, dealCollateral, marketBal.Available, tagged.Collateral)
return nil, err
}

// Check that the provider has enough funds to send a PublishStorageDeals message
availForPubMsg := big.Sub(pubMsgBal, tagged.PubMsg)
if availForPubMsg.LessThan(m.cfg.PubMsgBalMin) {
err := fmt.Errorf("%w: available funds %d is less than needed for publish deals message %d: "+
"available = funds in publish deals wallet %d - amount reserved for other deals %d",
ErrInsufficientFunds, availForPubMsg, m.cfg.PubMsgBalMin, pubMsgBal, tagged.PubMsg)
return nil, err
}
if m.cfg.Enabled {
dealCollateralTag = proposal.ProviderBalanceRequirement()
if availForDealCollat.LessThan(dealCollateralTag) {
err := fmt.Errorf("%w: available funds %d is less than collateral needed for deal %d: "+
"available = funds in escrow %d - amount reserved for other deals %d",
ErrInsufficientFunds, availForDealCollat, dealCollateralTag, marketBal.Available, tagged.Collateral)
return nil, err
}

// Provider has enough funds to make deal, so persist tagged funds
err = m.persistTagged(ctx, dealUuid, dealCollateral, m.cfg.PubMsgBalMin)
if err != nil {
return nil, fmt.Errorf("saving total tagged: %w", err)
// Check that the provider has enough funds to send a PublishStorageDeals message
pubMsgTag = m.cfg.PubMsgBalMin
if availForPubMsg.LessThan(pubMsgTag) {
err := fmt.Errorf("%w: available funds %d is less than needed for publish deals message %d: "+
"available = funds in publish deals wallet %d - amount reserved for other deals %d",
ErrInsufficientFunds, availForPubMsg, pubMsgTag, pubMsgBal, tagged.PubMsg)
return nil, err
}

// Provider has enough funds to make deal, so persist tagged funds
err = m.persistTagged(ctx, dealUuid, dealCollateralTag, pubMsgTag)
if err != nil {
return nil, fmt.Errorf("saving total tagged: %w", err)
}
}

return &TagFundsResp{
Collateral: dealCollateral,
PublishMessage: m.cfg.PubMsgBalMin,
Collateral: dealCollateralTag,
PublishMessage: pubMsgTag,

TotalPublishMessage: big.Add(tagged.PubMsg, m.cfg.PubMsgBalMin),
TotalCollateral: big.Add(tagged.Collateral, dealCollateral),
TotalPublishMessage: big.Add(tagged.PubMsg, pubMsgTag),
TotalCollateral: big.Add(tagged.Collateral, dealCollateralTag),

AvailablePublishMessage: big.Sub(availForPubMsg, m.cfg.PubMsgBalMin),
AvailableCollateral: big.Sub(availForDealCollat, dealCollateral),
AvailablePublishMessage: big.Sub(availForPubMsg, pubMsgTag),
AvailableCollateral: big.Sub(availForDealCollat, dealCollateralTag),
}, nil
}

Expand Down
60 changes: 60 additions & 0 deletions fundmanager/fundmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func TestFundManager(t *testing.T) {
api: api,
db: fundsDB,
cfg: Config{
Enabled: true,
StorageMiner: address.TestAddress,
PubMsgWallet: address.TestAddress2,
PubMsgBalMin: abi.NewTokenAmount(10),
Expand Down Expand Up @@ -107,6 +108,65 @@ func TestFundManager(t *testing.T) {
req.EqualValues(10, total.PubMsg.Int64())
}

func TestFundManagerDisabled(t *testing.T) {
_ = logging.SetLogLevel("funds", "debug")

req := require.New(t)
ctx := context.Background()

sqldb := db.CreateTestTmpDB(t)
require.NoError(t, db.CreateAllBoostTables(ctx, sqldb, sqldb))

fundsDB := db.NewFundsDB(sqldb)

api := &mockApi{}
fm := &FundManager{
api: api,
db: fundsDB,
cfg: Config{
Enabled: false,
StorageMiner: address.TestAddress,
PubMsgWallet: address.TestAddress2,
PubMsgBalMin: abi.NewTokenAmount(10),
},
}

// There should be nothing tagged to start with
deals, err := db.GenerateDeals()
req.NoError(err)

// Tag funds for a deal with collateral 3
deal := deals[0]
prop := deal.ClientDealProposal.Proposal
prop.ProviderCollateral = abi.NewTokenAmount(3)
rsp, err := fm.TagFunds(ctx, deal.DealUuid, prop)
req.NoError(err)
req.NotNil(rsp)
b, err := api.WalletBalance(ctx, address.TestAddress2)
req.NoError(err)
mb, err := api.StateMarketBalance(ctx, address.TestAddress2, types.TipSetKey{})
req.NoError(err)
avail := big.Sub(mb.Escrow, mb.Locked)

ex := &TagFundsResp{
Collateral: abi.NewTokenAmount(0),
PublishMessage: abi.NewTokenAmount(0),

TotalCollateral: abi.NewTokenAmount(0),
TotalPublishMessage: abi.NewTokenAmount(0),

AvailableCollateral: avail,
AvailablePublishMessage: b,
}
req.Equal(ex, rsp)

total, err := fm.TotalTagged(ctx)
req.NoError(err)
// Total tagged for collateral and publish message should be 0
req.EqualValues(0, total.Collateral.Int64())
req.EqualValues(0, total.PubMsg.Int64())
}

type mockApi struct {
}

Expand Down
1 change: 1 addition & 0 deletions node/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ func ConfigBoost(cfg *config.Boost) Option {
Override(new(*paths.Remote), lotus_modules.RemoteStorage),

Override(new(*fundmanager.FundManager), fundmanager.New(fundmanager.Config{
Enabled: cfg.Dealmaking.FundsTaggingEnabled,
StorageMiner: walletMiner,
CollatWallet: walletDealCollat,
PubMsgWallet: walletPSD,
Expand Down
1 change: 1 addition & 0 deletions node/config/def.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func DefaultBoost() *Boost {
HttpTransferStallCheckPeriod: Duration(30 * time.Second),
DealLogDurationDays: 30,
SealingPipelineCacheTimeout: Duration(30 * time.Second),
FundsTaggingEnabled: true,
},

LotusDealmaking: lotus_config.DealmakingConfig{
Expand Down
8 changes: 8 additions & 0 deletions node/config/doc_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions node/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ type DealmakingConfig struct {
// lotus-miner API. SealingPipelineCacheTimeout defines cache timeout value in seconds. Default is 30 seconds.
// Any value less than 0 will result in use of default
SealingPipelineCacheTimeout Duration

// Whether to enable tagging of funds. If enabled, each time a deal is
// accepted boost will tag funds for that deal so that they cannot be used
// for any other deal.
FundsTaggingEnabled bool
}

type ContractDealsConfig struct {
Expand Down
1 change: 1 addition & 0 deletions storagemarket/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,7 @@ func NewHarness(t *testing.T, opts ...harnessOpt) *ProviderHarness {

// fund manager
fminitF := fundmanager.New(fundmanager.Config{
Enabled: true,
PubMsgBalMin: ph.MinPublishFees,
PubMsgWallet: pw,
CollatWallet: pcw,
Expand Down

0 comments on commit 2c6d9fd

Please sign in to comment.