diff --git a/api/types.go b/api/types.go index 96f9fa63d..fd7ce0187 100644 --- a/api/types.go +++ b/api/types.go @@ -56,9 +56,17 @@ type PubsubScore struct { Score *pubsub.PeerScoreSnapshot } +// MessageSendSpec contains optional fields which modify message sending behavior type MessageSendSpec struct { - MaxFee abi.TokenAmount + // MaxFee specifies a cap on network fees related to this message + MaxFee abi.TokenAmount + + // MsgUuid specifies a unique message identifier which can be used on node (or node cluster) + // level to prevent double-sends of messages even when nonce generation is not handled by sender MsgUuid uuid.UUID + + // MaximizeFeeCap makes message FeeCap be based entirely on MaxFee + MaximizeFeeCap bool } type MpoolMessageWhole struct { diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index d0d6cc1ce..b4c139b97 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 8860d7071..1c6f717c0 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 6dc3f2239..d1496ceb9 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -210,8 +210,10 @@ func ComputeRBF(curPrem abi.TokenAmount, replaceByFeeRatio types.Percent) abi.To func CapGasFee(mff dtypes.DefaultMaxFeeFunc, msg *types.Message, sendSpec *api.MessageSendSpec) { var maxFee abi.TokenAmount + var maximizeFeeCap bool if sendSpec != nil { maxFee = sendSpec.MaxFee + maximizeFeeCap = sendSpec.MaximizeFeeCap } if maxFee.Int == nil || maxFee.Equals(big.Zero()) { mf, err := mff() @@ -222,15 +224,12 @@ func CapGasFee(mff dtypes.DefaultMaxFeeFunc, msg *types.Message, sendSpec *api.M maxFee = mf } - gl := types.NewInt(uint64(msg.GasLimit)) - totalFee := types.BigMul(msg.GasFeeCap, gl) - - if totalFee.LessThanEqual(maxFee) { - msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap - return + gaslimit := types.NewInt(uint64(msg.GasLimit)) + totalFee := types.BigMul(msg.GasFeeCap, gaslimit) + if maximizeFeeCap || totalFee.GreaterThan(maxFee) { + msg.GasFeeCap = big.Div(maxFee, gaslimit) } - msg.GasFeeCap = big.Div(maxFee, gl) msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap } diff --git a/documentation/en/api-v0-methods.md b/documentation/en/api-v0-methods.md index 742f3de8e..9110c1c3b 100644 --- a/documentation/en/api-v0-methods.md +++ b/documentation/en/api-v0-methods.md @@ -2289,7 +2289,8 @@ Inputs: }, { "MaxFee": "0", - "MsgUuid": "07070707-0707-0707-0707-070707070707" + "MsgUuid": "07070707-0707-0707-0707-070707070707", + "MaximizeFeeCap": true }, [ { @@ -2766,7 +2767,8 @@ Inputs: ], { "MaxFee": "0", - "MsgUuid": "07070707-0707-0707-0707-070707070707" + "MsgUuid": "07070707-0707-0707-0707-070707070707", + "MaximizeFeeCap": true } ] ``` @@ -3025,7 +3027,8 @@ Inputs: }, { "MaxFee": "0", - "MsgUuid": "07070707-0707-0707-0707-070707070707" + "MsgUuid": "07070707-0707-0707-0707-070707070707", + "MaximizeFeeCap": true } ] ``` diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index e2c249395..1dae12101 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -3357,7 +3357,8 @@ Inputs: }, { "MaxFee": "0", - "MsgUuid": "07070707-0707-0707-0707-070707070707" + "MsgUuid": "07070707-0707-0707-0707-070707070707", + "MaximizeFeeCap": true }, [ { @@ -3834,7 +3835,8 @@ Inputs: ], { "MaxFee": "0", - "MsgUuid": "07070707-0707-0707-0707-070707070707" + "MsgUuid": "07070707-0707-0707-0707-070707070707", + "MaximizeFeeCap": true } ] ``` @@ -4226,7 +4228,8 @@ Inputs: }, { "MaxFee": "0", - "MsgUuid": "07070707-0707-0707-0707-070707070707" + "MsgUuid": "07070707-0707-0707-0707-070707070707", + "MaximizeFeeCap": true } ] ``` diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index f887ee942..68bb76f1a 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -775,6 +775,10 @@ # env var: LOTUS_FEES_MAXMARKETBALANCEADDFEE #MaxMarketBalanceAddFee = "0.007 FIL" + # type: bool + # env var: LOTUS_FEES_MAXIMIZEWINDOWPOSTFEECAP + #MaximizeWindowPoStFeeCap = true + [Fees.MaxPreCommitBatchGasFee] # type: types.FIL # env var: LOTUS_FEES_MAXPRECOMMITBATCHGASFEE_BASE diff --git a/node/config/def.go b/node/config/def.go index 6df19665d..d85b44f69 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -253,6 +253,8 @@ func DefaultStorageMiner() *StorageMiner { MaxWindowPoStGasFee: types.MustParseFIL("5"), MaxPublishDealsFee: types.MustParseFIL("0.05"), MaxMarketBalanceAddFee: types.MustParseFIL("0.007"), + + MaximizeWindowPoStFeeCap: true, }, Addresses: MinerAddressConfig{ diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 4ea235704..26bcdd073 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -721,6 +721,12 @@ over the worker address if this flag is set.`, Name: "MaxMarketBalanceAddFee", Type: "types.FIL", + Comment: ``, + }, + { + Name: "MaximizeWindowPoStFeeCap", + Type: "bool", + Comment: ``, }, }, diff --git a/node/config/types.go b/node/config/types.go index 95721a579..bec3a0bc9 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -490,6 +490,8 @@ type MinerFeeConfig struct { MaxWindowPoStGasFee types.FIL MaxPublishDealsFee types.FIL MaxMarketBalanceAddFee types.FIL + + MaximizeWindowPoStFeeCap bool } type MinerAddressConfig struct { diff --git a/storage/wdpost/wdpost_run.go b/storage/wdpost/wdpost_run.go index 0168bc706..8871d832d 100644 --- a/storage/wdpost/wdpost_run.go +++ b/storage/wdpost/wdpost_run.go @@ -650,7 +650,7 @@ func (s *WindowPoStScheduler) submitPoStMessage(ctx context.Context, proof *mine Params: enc, Value: types.NewInt(0), } - spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)} + spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee), MaximizeFeeCap: s.feeCfg.MaximizeWindowPoStFeeCap} if err := s.prepareMessage(ctx, msg, spec); err != nil { return nil, err } diff --git a/storage/wdpost/wdpost_run_faults.go b/storage/wdpost/wdpost_run_faults.go index f36b30d35..582e61f9d 100644 --- a/storage/wdpost/wdpost_run_faults.go +++ b/storage/wdpost/wdpost_run_faults.go @@ -168,11 +168,11 @@ func (s *WindowPoStScheduler) declareRecoveries(ctx context.Context, dlIdx uint6 Params: enc, Value: types.NewInt(0), } - spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)} + spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee), MaximizeFeeCap: s.feeCfg.MaximizeWindowPoStFeeCap} if err := s.prepareMessage(ctx, msg, spec); err != nil { return nil, nil, err } - sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)}) + sm, err := s.api.MpoolPushMessage(ctx, msg, spec) if err != nil { return nil, nil, xerrors.Errorf("pushing message to mpool: %w", err) }