lotus/cli/mpool.go

744 lines
16 KiB
Go
Raw Permalink Normal View History

2019-07-09 22:58:51 +00:00
package cli
import (
"encoding/json"
2019-07-09 22:58:51 +00:00
"fmt"
stdbig "math/big"
2020-03-10 00:44:08 +00:00
"sort"
2020-07-22 21:19:59 +00:00
"strconv"
2019-07-09 22:58:51 +00:00
"github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
2020-06-05 22:59:01 +00:00
"golang.org/x/xerrors"
2019-11-23 01:26:32 +00:00
"github.com/filecoin-project/go-address"
2020-09-07 03:49:10 +00:00
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
2020-03-10 00:26:10 +00:00
2020-09-08 22:47:40 +00:00
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/messagepool"
2019-11-23 01:26:32 +00:00
"github.com/filecoin-project/lotus/chain/types"
2020-10-29 19:50:04 +00:00
"github.com/filecoin-project/lotus/node/config"
2019-07-09 22:58:51 +00:00
)
2021-03-23 23:28:27 +00:00
var MpoolCmd = &cli.Command{
2019-07-09 22:58:51 +00:00
Name: "mpool",
Usage: "Manage message pool",
Subcommands: []*cli.Command{
2021-03-23 23:28:27 +00:00
MpoolPending,
MpoolClear,
MpoolSub,
MpoolStat,
MpoolReplaceCmd,
MpoolFindCmd,
MpoolConfig,
MpoolGasPerfCmd,
mpoolManage,
2019-07-09 22:58:51 +00:00
},
}
2021-03-23 23:28:27 +00:00
var MpoolPending = &cli.Command{
2019-07-09 22:58:51 +00:00
Name: "pending",
Usage: "Get pending messages",
2020-04-29 19:52:04 +00:00
Flags: []cli.Flag{
&cli.BoolFlag{
2020-04-30 11:19:37 +00:00
Name: "local",
2020-04-29 19:52:04 +00:00
Usage: "print pending messages for addresses in local wallet only",
},
2020-10-01 15:51:01 +00:00
&cli.BoolFlag{
Name: "cids",
Usage: "only print cids of messages in output",
},
2020-12-10 09:21:32 +00:00
&cli.StringFlag{
Name: "to",
Usage: "return messages to a given address",
},
&cli.StringFlag{
Name: "from",
Usage: "return messages from a given address",
},
2020-04-29 19:52:04 +00:00
},
2019-07-09 22:58:51 +00:00
Action: func(cctx *cli.Context) error {
2022-02-21 10:28:45 +00:00
afmt := NewAppFmt(cctx.App)
2019-10-03 18:12:30 +00:00
api, closer, err := GetFullNodeAPI(cctx)
2019-07-12 04:09:04 +00:00
if err != nil {
return err
}
2019-10-03 18:12:30 +00:00
defer closer()
2019-07-12 04:09:04 +00:00
2019-07-18 23:16:23 +00:00
ctx := ReqContext(cctx)
2019-07-09 22:58:51 +00:00
2020-12-10 09:21:32 +00:00
var toa, froma address.Address
if tos := cctx.String("to"); tos != "" {
a, err := address.NewFromString(tos)
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("given 'to' address %q was invalid: %w", tos, err)
2020-12-10 09:21:32 +00:00
}
toa = a
}
if froms := cctx.String("from"); froms != "" {
a, err := address.NewFromString(froms)
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("given 'from' address %q was invalid: %w", froms, err)
2020-12-10 09:21:32 +00:00
}
froma = a
}
2020-04-29 19:52:04 +00:00
var filter map[address.Address]struct{}
if cctx.Bool("local") {
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{}{}
}
}
msgs, err := api.MpoolPending(ctx, types.EmptyTSK)
2019-07-09 22:58:51 +00:00
if err != nil {
return err
}
for _, msg := range msgs {
2020-04-30 11:19:37 +00:00
if filter != nil {
2020-04-29 19:52:04 +00:00
if _, has := filter[msg.Message.From]; !has {
continue
}
}
2020-12-10 09:21:32 +00:00
if toa != address.Undef && msg.Message.To != toa {
continue
}
if froma != address.Undef && msg.Message.From != froma {
continue
}
2020-10-01 15:51:01 +00:00
if cctx.Bool("cids") {
2022-02-21 10:28:45 +00:00
afmt.Println(msg.Cid())
2020-10-01 15:51:01 +00:00
} else {
out, err := json.MarshalIndent(msg, "", " ")
if err != nil {
return err
}
2022-02-21 10:28:45 +00:00
afmt.Println(string(out))
}
2019-07-09 22:58:51 +00:00
}
return nil
},
}
2019-11-17 07:44:06 +00:00
// Deprecated: MpoolClear is now available at `lotus-shed mpool clear`
2021-03-23 23:28:27 +00:00
var MpoolClear = &cli.Command{
Name: "clear",
Usage: "Clear all pending messages from the mpool (USE WITH CARE) (DEPRECATED)",
Hidden: true,
2020-08-21 17:59:40 +00:00
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "local",
Usage: "also clear local messages",
2020-08-21 17:59:40 +00:00
},
&cli.BoolFlag{
Name: "really-do-it",
Usage: "must be specified for the action to take effect",
},
2020-08-21 17:59:40 +00:00
},
2020-08-21 17:31:25 +00:00
Action: func(cctx *cli.Context) error {
fmt.Println("DEPRECATED: This behavior is being moved to `lotus-shed mpool clear`")
2020-08-21 17:31:25 +00:00
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
really := cctx.Bool("really-do-it")
if !really {
//nolint:golint
2020-08-24 15:41:43 +00:00
return fmt.Errorf("--really-do-it must be specified for this action to have an effect; you have been warned")
}
2020-08-21 17:59:40 +00:00
local := cctx.Bool("local")
2020-08-21 17:31:25 +00:00
2020-08-21 17:59:40 +00:00
ctx := ReqContext(cctx)
return api.MpoolClear(ctx, local)
2020-08-21 17:31:25 +00:00
},
}
2021-03-23 23:28:27 +00:00
var MpoolSub = &cli.Command{
2019-11-17 07:44:06 +00:00
Name: "sub",
2020-07-21 01:30:21 +00:00
Usage: "Subscribe to mpool changes",
2019-11-17 07:44:06 +00:00
Action: func(cctx *cli.Context) error {
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
sub, err := api.MpoolSub(ctx)
if err != nil {
return err
}
for {
select {
case update := <-sub:
out, err := json.MarshalIndent(update, "", " ")
if err != nil {
return err
}
fmt.Println(string(out))
case <-ctx.Done():
return nil
}
}
},
}
2019-11-23 01:26:32 +00:00
2021-03-23 23:28:27 +00:00
var MpoolStat = &cli.Command{
2019-11-23 01:26:32 +00:00
Name: "stat",
Usage: "print mempool stats",
2020-04-29 19:52:04 +00:00
Flags: []cli.Flag{
&cli.BoolFlag{
2020-04-30 11:19:37 +00:00
Name: "local",
2020-04-29 19:52:04 +00:00
Usage: "print stats for addresses in local wallet only",
},
&cli.IntFlag{
Name: "basefee-lookback",
Usage: "number of blocks to look back for minimum basefee",
Value: 60,
},
2020-04-29 19:52:04 +00:00
},
2019-11-23 01:26:32 +00:00
Action: func(cctx *cli.Context) error {
2022-02-21 10:28:45 +00:00
afmt := NewAppFmt(cctx.App)
2019-11-23 01:26:32 +00:00
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
ts, err := api.ChainHead(ctx)
if err != nil {
return xerrors.Errorf("getting chain head: %w", err)
}
currBF := ts.Blocks()[0].ParentBaseFee
minBF := currBF
{
currTs := ts
for i := 0; i < cctx.Int("basefee-lookback"); i++ {
currTs, err = api.ChainGetTipSet(ctx, currTs.Parents())
2022-02-21 10:28:45 +00:00
if err != nil {
return xerrors.Errorf("walking chain: %w", err)
}
if newBF := currTs.Blocks()[0].ParentBaseFee; newBF.LessThan(minBF) {
minBF = newBF
}
}
}
2019-11-23 01:26:32 +00:00
2020-04-29 19:52:04 +00:00
var filter map[address.Address]struct{}
if cctx.Bool("local") {
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{}{}
}
}
msgs, err := api.MpoolPending(ctx, types.EmptyTSK)
2019-11-23 01:26:32 +00:00
if err != nil {
return err
}
type statBucket struct {
msgs map[uint64]*types.SignedMessage
}
type mpStat struct {
addr string
past, cur, future uint64
belowCurr, belowPast uint64
2020-11-27 14:55:59 +00:00
gasLimit big.Int
}
2019-11-23 01:26:32 +00:00
buckets := map[address.Address]*statBucket{}
2019-11-23 01:26:32 +00:00
for _, v := range msgs {
2020-04-30 11:19:37 +00:00
if filter != nil {
2020-04-29 19:52:04 +00:00
if _, has := filter[v.Message.From]; !has {
continue
}
}
2019-11-23 01:26:32 +00:00
bkt, ok := buckets[v.Message.From]
if !ok {
bkt = &statBucket{
msgs: map[uint64]*types.SignedMessage{},
}
buckets[v.Message.From] = bkt
}
bkt.msgs[v.Message.Nonce] = v
}
2020-03-10 00:44:08 +00:00
var out []mpStat
2019-11-23 01:26:32 +00:00
for a, bkt := range buckets {
act, err := api.StateGetActor(ctx, a, ts.Key())
2019-11-23 01:26:32 +00:00
if err != nil {
2022-02-21 10:28:45 +00:00
afmt.Printf("%s, err: %s\n", a, err)
continue
2019-11-23 01:26:32 +00:00
}
cur := act.Nonce
for {
_, ok := bkt.msgs[cur]
if !ok {
break
}
cur++
}
var s mpStat
s.addr = a.String()
2020-11-27 14:55:59 +00:00
s.gasLimit = big.Zero()
2019-11-23 19:01:56 +00:00
for _, m := range bkt.msgs {
if m.Message.Nonce < act.Nonce {
s.past++
} else if m.Message.Nonce > cur {
s.future++
} else {
s.cur++
}
if m.Message.GasFeeCap.LessThan(currBF) {
s.belowCurr++
2019-11-23 19:01:56 +00:00
}
if m.Message.GasFeeCap.LessThan(minBF) {
s.belowPast++
2019-11-23 19:01:56 +00:00
}
2020-11-27 14:55:59 +00:00
s.gasLimit = big.Add(s.gasLimit, types.NewInt(uint64(m.Message.GasLimit)))
2019-11-23 19:01:56 +00:00
}
out = append(out, s)
2020-03-10 00:44:08 +00:00
}
sort.Slice(out, func(i, j int) bool {
return out[i].addr < out[j].addr
})
2020-07-27 16:23:01 +00:00
var total mpStat
2020-11-27 14:55:59 +00:00
total.gasLimit = big.Zero()
2020-07-27 16:23:01 +00:00
2020-03-10 00:44:08 +00:00
for _, stat := range out {
2020-07-27 16:23:01 +00:00
total.past += stat.past
total.cur += stat.cur
total.future += stat.future
total.belowCurr += stat.belowCurr
total.belowPast += stat.belowPast
2020-11-27 14:55:59 +00:00
total.gasLimit = big.Add(total.gasLimit, stat.gasLimit)
2020-07-27 16:23:01 +00:00
2022-02-21 10:28:45 +00:00
afmt.Printf("%s: Nonce past: %d, cur: %d, future: %d; FeeCap cur: %d, min-%d: %d, gasLimit: %s\n", stat.addr, stat.past, stat.cur, stat.future, stat.belowCurr, cctx.Int("basefee-lookback"), stat.belowPast, stat.gasLimit)
2019-11-23 01:26:32 +00:00
}
2022-02-21 10:28:45 +00:00
afmt.Println("-----")
afmt.Printf("total: Nonce past: %d, cur: %d, future: %d; FeeCap cur: %d, min-%d: %d, gasLimit: %s\n", total.past, total.cur, total.future, total.belowCurr, cctx.Int("basefee-lookback"), total.belowPast, total.gasLimit)
2020-07-27 16:23:01 +00:00
2019-11-23 01:26:32 +00:00
return nil
},
}
2020-07-22 21:19:59 +00:00
2021-03-23 23:28:27 +00:00
var MpoolReplaceCmd = &cli.Command{
2020-07-22 21:19:59 +00:00
Name: "replace",
Usage: "replace a message in the mempool",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "gas-feecap",
2020-12-26 11:20:53 +00:00
Usage: "gas feecap for new message (burn and pay to miner, attoFIL/GasUnit)",
},
&cli.StringFlag{
Name: "gas-premium",
2020-12-26 11:20:53 +00:00
Usage: "gas price for new message (pay to miner, attoFIL/GasUnit)",
2020-07-22 21:19:59 +00:00
},
&cli.Int64Flag{
Name: "gas-limit",
2020-12-26 11:20:53 +00:00
Usage: "gas limit for new message (GasUnit)",
2020-07-22 21:19:59 +00:00
},
2020-09-08 22:47:40 +00:00
&cli.BoolFlag{
Name: "auto",
Usage: "automatically reprice the specified message",
},
&cli.StringFlag{
2021-07-29 03:59:59 +00:00
Name: "fee-limit",
2021-07-29 04:28:15 +00:00
Usage: "Spend up to X FIL for this message in units of FIL. Previously when flag was `max-fee` units were in attoFIL. Applicable for auto mode",
},
2020-07-22 21:19:59 +00:00
},
2022-02-21 10:28:45 +00:00
ArgsUsage: "<from> <nonce> | <message-cid>",
2020-07-22 21:19:59 +00:00
Action: func(cctx *cli.Context) error {
2022-02-21 10:28:45 +00:00
afmt := NewAppFmt(cctx.App)
2020-07-22 21:19:59 +00:00
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
2020-10-01 15:51:01 +00:00
var from address.Address
var nonce uint64
2022-09-14 18:33:29 +00:00
switch cctx.NArg() {
2020-10-01 15:51:01 +00:00
case 1:
mcid, err := cid.Decode(cctx.Args().First())
if err != nil {
return err
}
msg, err := api.ChainGetMessage(ctx, mcid)
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("could not find referenced message: %w", err)
2020-10-01 15:51:01 +00:00
}
from = msg.From
nonce = msg.Nonce
case 2:
2022-02-21 10:28:45 +00:00
arg0 := cctx.Args().Get(0)
f, err := address.NewFromString(arg0)
2020-10-01 15:51:01 +00:00
if err != nil {
return err
}
n, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
if err != nil {
return err
}
from = f
nonce = n
default:
return cli.ShowCommandHelp(cctx, cctx.Command.Name)
}
2020-07-22 21:19:59 +00:00
ts, err := api.ChainHead(ctx)
if err != nil {
return xerrors.Errorf("getting chain head: %w", err)
}
pending, err := api.MpoolPending(ctx, ts.Key())
if err != nil {
return err
}
var found *types.SignedMessage
for _, p := range pending {
if p.Message.From == from && p.Message.Nonce == nonce {
found = p
break
}
}
if found == nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("no pending message found from %s with nonce %d", from, nonce)
2020-07-22 21:19:59 +00:00
}
msg := found.Message
2020-09-08 22:47:40 +00:00
if cctx.Bool("auto") {
cfg, err := api.MpoolGetConfig(ctx)
if err != nil {
return xerrors.Errorf("failed to lookup the message pool config: %w", err)
}
defaultRBF := messagepool.ComputeRBF(msg.GasPremium, cfg.ReplaceByFeeRatio)
var mss *lapi.MessageSendSpec
2021-07-29 03:59:59 +00:00
if cctx.IsSet("fee-limit") {
maxFee, err := types.ParseFIL(cctx.String("fee-limit"))
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("parsing max-spend: %w", err)
}
mss = &lapi.MessageSendSpec{
2021-07-29 03:59:59 +00:00
MaxFee: abi.TokenAmount(maxFee),
}
}
2020-09-08 22:47:40 +00:00
// 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, mss, types.EmptyTSK)
2020-09-08 22:47:40 +00:00
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("failed to estimate gas values: %w", err)
2020-09-08 22:47:40 +00:00
}
msg.GasPremium = big.Max(retm.GasPremium, defaultRBF)
msg.GasFeeCap = big.Max(retm.GasFeeCap, msg.GasPremium)
2020-10-29 19:50:04 +00:00
mff := func() (abi.TokenAmount, error) {
feat: curio: web based config edit (#11822) * cfg edit 1 * jsonschema deps * feat: lp mig - first few steps * lp mig: default tasks * code comments * docs * lp-mig-progress * shared * comments and todos * fix: curio: rename lotus-provider to curio (#11645) * rename provider to curio * install gotext * fix lint errors, mod tidy * fix typo * fix API_INFO and add gotext to circleCI * add back gotext * add gotext after remerge * lp: channels doc * finish easy-migration TODOs * out generate * merging and more renames * avoid make-all * minor doc stuff * cu: make gen * make gen fix * make gen * tryfix * go mod tidy * minor ez migration fixes * ez setup - ui cleanups * better error message * guided setup colors * better path to saveconfigtolayer * loadconfigwithupgrades fix * readMiner oops * guided - homedir * err if miner is running * prompt error should exit * process already running, miner_id sectors in migration * dont prompt for language a second time * check miner stopped * unlock repo * render and sql oops * curio easyMig - some fixes * easyMigration runs successfully * lint * part 2 of last * message * merge addtl * fixing guided setup for myself * warn-on-no-post * EditorLoads * cleanups and styles * create info * fix tests * make gen * change layout, add help button * Duration custom json * mjs naming --------- Co-authored-by: LexLuthr <88259624+LexLuthr@users.noreply.github.com> Co-authored-by: LexLuthr <lexluthr@protocol.ai> Co-authored-by: LexLuthr <lexluthr@curiostorage.org>
2024-04-16 14:30:27 +00:00
return abi.TokenAmount(config.DefaultDefaultMaxFee()), nil
2020-10-29 19:50:04 +00:00
}
messagepool.CapGasFee(mff, &msg, mss)
2020-09-08 22:47:40 +00:00
} else {
if cctx.IsSet("gas-limit") {
msg.GasLimit = cctx.Int64("gas-limit")
}
2020-09-08 22:47:40 +00:00
msg.GasPremium, err = types.BigFromString(cctx.String("gas-premium"))
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("parsing gas-premium: %w", err)
2020-09-08 22:47:40 +00:00
}
// TODO: estimate fee cap here
msg.GasFeeCap, err = types.BigFromString(cctx.String("gas-feecap"))
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("parsing gas-feecap: %w", err)
2020-09-08 22:47:40 +00:00
}
}
2020-07-22 21:19:59 +00:00
smsg, err := api.WalletSignMessage(ctx, msg.From, &msg)
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("failed to sign message: %w", err)
2020-07-22 21:19:59 +00:00
}
cid, err := api.MpoolPush(ctx, smsg)
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("failed to push new message to mempool: %w", err)
2020-07-22 21:19:59 +00:00
}
2022-02-21 10:28:45 +00:00
afmt.Println("new message cid: ", cid)
2020-07-22 21:19:59 +00:00
return nil
},
}
2020-07-22 22:07:02 +00:00
2021-03-23 23:28:27 +00:00
var MpoolFindCmd = &cli.Command{
2020-07-22 22:07:02 +00:00
Name: "find",
Usage: "find a message in the mempool",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "from",
Usage: "search for messages with given 'from' address",
},
&cli.StringFlag{
Name: "to",
Usage: "search for messages with given 'to' address",
},
&cli.Int64Flag{
Name: "method",
Usage: "search for messages with given method",
},
},
Action: func(cctx *cli.Context) error {
2022-02-21 10:28:45 +00:00
afmt := NewAppFmt(cctx.App)
2020-07-22 22:07:02 +00:00
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
pending, err := api.MpoolPending(ctx, types.EmptyTSK)
if err != nil {
return err
}
var toFilter, fromFilter address.Address
if cctx.IsSet("to") {
a, err := address.NewFromString(cctx.String("to"))
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("'to' address was invalid: %w", err)
2020-07-22 22:07:02 +00:00
}
toFilter = a
}
if cctx.IsSet("from") {
a, err := address.NewFromString(cctx.String("from"))
if err != nil {
2022-02-21 10:28:45 +00:00
return xerrors.Errorf("'from' address was invalid: %w", err)
2020-07-22 22:07:02 +00:00
}
fromFilter = a
}
var methodFilter *abi.MethodNum
if cctx.IsSet("method") {
m := abi.MethodNum(cctx.Int64("method"))
methodFilter = &m
}
var out []*types.SignedMessage
for _, m := range pending {
if toFilter != address.Undef && m.Message.To != toFilter {
continue
}
if fromFilter != address.Undef && m.Message.From != fromFilter {
continue
}
if methodFilter != nil && *methodFilter != m.Message.Method {
continue
}
out = append(out, m)
}
b, err := json.MarshalIndent(out, "", " ")
if err != nil {
return err
}
2022-02-21 10:28:45 +00:00
afmt.Println(string(b))
2020-07-22 22:07:02 +00:00
return nil
},
}
2020-08-16 06:57:53 +00:00
2021-03-23 23:28:27 +00:00
var MpoolConfig = &cli.Command{
2020-08-16 06:57:53 +00:00
Name: "config",
Usage: "get or set current mpool configuration",
ArgsUsage: "[new-config]",
Action: func(cctx *cli.Context) error {
2022-09-14 18:33:29 +00:00
if cctx.NArg() > 1 {
return IncorrectNumArgs(cctx)
2020-08-16 06:57:53 +00:00
}
2022-02-21 10:28:45 +00:00
afmt := NewAppFmt(cctx.App)
2020-08-16 06:57:53 +00:00
api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)
2022-09-14 18:33:29 +00:00
if cctx.NArg() == 0 {
2020-08-16 06:57:53 +00:00
cfg, err := api.MpoolGetConfig(ctx)
if err != nil {
return err
}
bytes, err := json.Marshal(cfg)
if err != nil {
return err
}
2022-02-21 10:28:45 +00:00
afmt.Println(string(bytes))
2020-08-16 06:57:53 +00:00
} else {
cfg := new(types.MpoolConfig)
bytes := []byte(cctx.Args().Get(0))
err := json.Unmarshal(bytes, cfg)
if err != nil {
return err
}
return api.MpoolSetConfig(ctx, cfg)
}
return nil
},
}
2021-03-23 23:28:27 +00:00
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 {
2022-02-21 10:28:45 +00:00
afmt := NewAppFmt(cctx.App)
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)
2022-02-21 10:28:45 +00:00
afmt.Printf("%s\t%d\t%s\t%f\n", m.Message.From, m.Message.Nonce, gasReward, gasPerf)
}
return nil
},
}