diff --git a/cli/mpool.go b/cli/mpool.go index 6561e2cbc..6ae94356a 100644 --- a/cli/mpool.go +++ b/cli/mpool.go @@ -3,6 +3,7 @@ package cli import ( "encoding/json" "fmt" + stdbig "math/big" "sort" "strconv" @@ -14,6 +15,7 @@ import ( "github.com/filecoin-project/go-state-types/big" lapi "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/types" ) @@ -29,6 +31,7 @@ var mpoolCmd = &cli.Command{ mpoolReplaceCmd, mpoolFindCmd, mpoolConfig, + mpoolGasPerfCmd, }, } @@ -516,3 +519,86 @@ var mpoolConfig = &cli.Command{ return nil }, } + +var mpoolGasPerfCmd = &cli.Command{ + Name: "gas-perf", + Usage: "Check gas performance of messages in mempool", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "all", + Usage: "print gas performance for all mempool messages (default only prints for local)", + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + + ctx := ReqContext(cctx) + + msgs, err := api.MpoolPending(ctx, types.EmptyTSK) + if err != nil { + return err + } + + var filter map[address.Address]struct{} + if !cctx.Bool("all") { + filter = map[address.Address]struct{}{} + + addrss, err := api.WalletList(ctx) + if err != nil { + return xerrors.Errorf("getting local addresses: %w", err) + } + + for _, a := range addrss { + filter[a] = struct{}{} + } + + var filtered []*types.SignedMessage + for _, msg := range msgs { + if _, has := filter[msg.Message.From]; !has { + continue + } + filtered = append(filtered, msg) + } + msgs = filtered + } + + ts, err := api.ChainHead(ctx) + if err != nil { + return xerrors.Errorf("failed to get chain head: %w", err) + } + + baseFee := ts.Blocks()[0].ParentBaseFee + + bigBlockGasLimit := big.NewInt(build.BlockGasLimit) + + getGasReward := func(msg *types.SignedMessage) big.Int { + maxPremium := types.BigSub(msg.Message.GasFeeCap, baseFee) + if types.BigCmp(maxPremium, msg.Message.GasPremium) < 0 { + maxPremium = msg.Message.GasPremium + } + return types.BigMul(maxPremium, types.NewInt(uint64(msg.Message.GasLimit))) + } + + getGasPerf := func(gasReward big.Int, gasLimit int64) float64 { + // gasPerf = gasReward * build.BlockGasLimit / gasLimit + a := new(stdbig.Rat).SetInt(new(stdbig.Int).Mul(gasReward.Int, bigBlockGasLimit.Int)) + b := stdbig.NewRat(1, gasLimit) + c := new(stdbig.Rat).Mul(a, b) + r, _ := c.Float64() + return r + } + + for _, m := range msgs { + gasReward := getGasReward(m) + gasPerf := getGasPerf(gasReward, m.Message.GasLimit) + + fmt.Printf("%s\t%d\t%s\t%f\n", m.Message.From, m.Message.Nonce, gasReward, gasPerf) + } + + return nil + }, +}