diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 06cbe65e7..653844c02 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -12,6 +12,7 @@ import ( "time" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/crypto" "github.com/hashicorp/go-multierror" lru "github.com/hashicorp/golang-lru" @@ -160,6 +161,22 @@ func ComputeMinRBF(curPrem abi.TokenAmount) abi.TokenAmount { return types.BigAdd(minPrice, types.NewInt(1)) } +func CapGasFee(msg *types.Message, maxFee abi.TokenAmount) { + if maxFee.Equals(big.Zero()) { + maxFee = types.NewInt(build.FilecoinPrecision / 10) + } + + gl := types.NewInt(uint64(msg.GasLimit)) + totalFee := types.BigMul(msg.GasFeeCap, gl) + + if totalFee.LessThanEqual(maxFee) { + return + } + + msg.GasFeeCap = big.Div(maxFee, gl) + msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap +} + func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict bool) (bool, error) { nextNonce := ms.nextNonce nonceGap := false diff --git a/cli/mpool.go b/cli/mpool.go index 6ae94356a..65f4ef942 100644 --- a/cli/mpool.go +++ b/cli/mpool.go @@ -303,6 +303,10 @@ var mpoolReplaceCmd = &cli.Command{ Name: "auto", Usage: "automatically reprice the specified message", }, + &cli.StringFlag{ + Name: "max-fee", + Usage: "Spend up to X FIL for this message (applicable for auto mode)", + }, }, ArgsUsage: "[from] [nonce]", Action: func(cctx *cli.Context) error { @@ -353,17 +357,30 @@ var mpoolReplaceCmd = &cli.Command{ msg := found.Message if cctx.Bool("auto") { + minRBF := messagepool.ComputeMinRBF(msg.GasPremium) + + var mss *lapi.MessageSendSpec + if cctx.IsSet("max-fee") { + maxFee, err := types.BigFromString(cctx.String("max-fee")) + if err != nil { + return fmt.Errorf("parsing max-spend: %w", err) + } + mss = &lapi.MessageSendSpec{ + MaxFee: maxFee, + } + } + // msg.GasLimit = 0 // TODO: need to fix the way we estimate gas limits to account for the messages already being in the mempool msg.GasFeeCap = abi.NewTokenAmount(0) msg.GasPremium = abi.NewTokenAmount(0) - retm, err := api.GasEstimateMessageGas(ctx, &msg, &lapi.MessageSendSpec{}, types.EmptyTSK) + retm, err := api.GasEstimateMessageGas(ctx, &msg, mss, types.EmptyTSK) if err != nil { return fmt.Errorf("failed to estimate gas values: %w", err) } - msg.GasFeeCap = retm.GasFeeCap - minRBF := messagepool.ComputeMinRBF(msg.GasPremium) msg.GasPremium = big.Max(retm.GasPremium, minRBF) + msg.GasFeeCap = big.Max(retm.GasFeeCap, msg.GasPremium) + messagepool.CapGasFee(&msg, mss.Get().MaxFee) } else { msg.GasLimit = cctx.Int64("gas-limit") msg.GasPremium, err = types.BigFromString(cctx.String("gas-premium")) diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 40ab88b6b..a597059e4 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -211,23 +211,7 @@ func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, msg.GasFeeCap = feeCap } - capGasFee(msg, spec.Get().MaxFee) + messagepool.CapGasFee(msg, spec.Get().MaxFee) return msg, nil } - -func capGasFee(msg *types.Message, maxFee abi.TokenAmount) { - if maxFee.Equals(big.Zero()) { - maxFee = types.NewInt(build.FilecoinPrecision / 10) - } - - gl := types.NewInt(uint64(msg.GasLimit)) - totalFee := types.BigMul(msg.GasFeeCap, gl) - - if totalFee.LessThanEqual(maxFee) { - return - } - - msg.GasFeeCap = big.Div(maxFee, gl) - msg.GasPremium = big.Min(msg.GasFeeCap, msg.GasPremium) // cap premium at FeeCap -}