Add cli tests for mempool

This commit is contained in:
Darko Brdareski 2022-02-21 11:28:45 +01:00
parent 6feae1993d
commit c3817652dc
2 changed files with 559 additions and 24 deletions

View File

@ -60,6 +60,8 @@ var MpoolPending = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
afmt := NewAppFmt(cctx.App)
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -72,7 +74,7 @@ var MpoolPending = &cli.Command{
if tos := cctx.String("to"); tos != "" { if tos := cctx.String("to"); tos != "" {
a, err := address.NewFromString(tos) a, err := address.NewFromString(tos)
if err != nil { if err != nil {
return fmt.Errorf("given 'to' address %q was invalid: %w", tos, err) return xerrors.Errorf("given 'to' address %q was invalid: %w", tos, err)
} }
toa = a toa = a
} }
@ -80,7 +82,7 @@ var MpoolPending = &cli.Command{
if froms := cctx.String("from"); froms != "" { if froms := cctx.String("from"); froms != "" {
a, err := address.NewFromString(froms) a, err := address.NewFromString(froms)
if err != nil { if err != nil {
return fmt.Errorf("given 'from' address %q was invalid: %w", froms, err) return xerrors.Errorf("given 'from' address %q was invalid: %w", froms, err)
} }
froma = a froma = a
} }
@ -119,13 +121,13 @@ var MpoolPending = &cli.Command{
} }
if cctx.Bool("cids") { if cctx.Bool("cids") {
fmt.Println(msg.Cid()) afmt.Println(msg.Cid())
} else { } else {
out, err := json.MarshalIndent(msg, "", " ") out, err := json.MarshalIndent(msg, "", " ")
if err != nil { if err != nil {
return err return err
} }
fmt.Println(string(out)) afmt.Println(string(out))
} }
} }
@ -216,6 +218,8 @@ var MpoolStat = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
afmt := NewAppFmt(cctx.App)
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -234,6 +238,7 @@ var MpoolStat = &cli.Command{
currTs := ts currTs := ts
for i := 0; i < cctx.Int("basefee-lookback"); i++ { for i := 0; i < cctx.Int("basefee-lookback"); i++ {
currTs, err = api.ChainGetTipSet(ctx, currTs.Parents()) currTs, err = api.ChainGetTipSet(ctx, currTs.Parents())
if err != nil { if err != nil {
return xerrors.Errorf("walking chain: %w", err) return xerrors.Errorf("walking chain: %w", err)
} }
@ -296,7 +301,7 @@ var MpoolStat = &cli.Command{
for a, bkt := range buckets { for a, bkt := range buckets {
act, err := api.StateGetActor(ctx, a, ts.Key()) act, err := api.StateGetActor(ctx, a, ts.Key())
if err != nil { if err != nil {
fmt.Printf("%s, err: %s\n", a, err) afmt.Printf("%s, err: %s\n", a, err)
continue continue
} }
@ -350,11 +355,11 @@ var MpoolStat = &cli.Command{
total.belowPast += stat.belowPast total.belowPast += stat.belowPast
total.gasLimit = big.Add(total.gasLimit, stat.gasLimit) total.gasLimit = big.Add(total.gasLimit, stat.gasLimit)
fmt.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) 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)
} }
fmt.Println("-----") afmt.Println("-----")
fmt.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) 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)
return nil return nil
}, },
@ -385,8 +390,9 @@ var MpoolReplaceCmd = &cli.Command{
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", 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",
}, },
}, },
ArgsUsage: "<from nonce> | <message-cid>", ArgsUsage: "<from> <nonce> | <message-cid>",
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
afmt := NewAppFmt(cctx.App)
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
@ -407,13 +413,14 @@ var MpoolReplaceCmd = &cli.Command{
msg, err := api.ChainGetMessage(ctx, mcid) msg, err := api.ChainGetMessage(ctx, mcid)
if err != nil { if err != nil {
return fmt.Errorf("could not find referenced message: %w", err) return xerrors.Errorf("could not find referenced message: %w", err)
} }
from = msg.From from = msg.From
nonce = msg.Nonce nonce = msg.Nonce
case 2: case 2:
f, err := address.NewFromString(cctx.Args().Get(0)) arg0 := cctx.Args().Get(0)
f, err := address.NewFromString(arg0)
if err != nil { if err != nil {
return err return err
} }
@ -448,7 +455,7 @@ var MpoolReplaceCmd = &cli.Command{
} }
if found == nil { if found == nil {
return fmt.Errorf("no pending message found from %s with nonce %d", from, nonce) return xerrors.Errorf("no pending message found from %s with nonce %d", from, nonce)
} }
msg := found.Message msg := found.Message
@ -460,7 +467,7 @@ var MpoolReplaceCmd = &cli.Command{
if cctx.IsSet("fee-limit") { if cctx.IsSet("fee-limit") {
maxFee, err := types.ParseFIL(cctx.String("fee-limit")) maxFee, err := types.ParseFIL(cctx.String("fee-limit"))
if err != nil { if err != nil {
return fmt.Errorf("parsing max-spend: %w", err) return xerrors.Errorf("parsing max-spend: %w", err)
} }
mss = &lapi.MessageSendSpec{ mss = &lapi.MessageSendSpec{
MaxFee: abi.TokenAmount(maxFee), MaxFee: abi.TokenAmount(maxFee),
@ -472,7 +479,7 @@ var MpoolReplaceCmd = &cli.Command{
msg.GasPremium = abi.NewTokenAmount(0) msg.GasPremium = abi.NewTokenAmount(0)
retm, err := api.GasEstimateMessageGas(ctx, &msg, mss, types.EmptyTSK) retm, err := api.GasEstimateMessageGas(ctx, &msg, mss, types.EmptyTSK)
if err != nil { if err != nil {
return fmt.Errorf("failed to estimate gas values: %w", err) return xerrors.Errorf("failed to estimate gas values: %w", err)
} }
msg.GasPremium = big.Max(retm.GasPremium, minRBF) msg.GasPremium = big.Max(retm.GasPremium, minRBF)
@ -489,26 +496,26 @@ var MpoolReplaceCmd = &cli.Command{
} }
msg.GasPremium, err = types.BigFromString(cctx.String("gas-premium")) msg.GasPremium, err = types.BigFromString(cctx.String("gas-premium"))
if err != nil { if err != nil {
return fmt.Errorf("parsing gas-premium: %w", err) return xerrors.Errorf("parsing gas-premium: %w", err)
} }
// TODO: estimate fee cap here // TODO: estimate fee cap here
msg.GasFeeCap, err = types.BigFromString(cctx.String("gas-feecap")) msg.GasFeeCap, err = types.BigFromString(cctx.String("gas-feecap"))
if err != nil { if err != nil {
return fmt.Errorf("parsing gas-feecap: %w", err) return xerrors.Errorf("parsing gas-feecap: %w", err)
} }
} }
smsg, err := api.WalletSignMessage(ctx, msg.From, &msg) smsg, err := api.WalletSignMessage(ctx, msg.From, &msg)
if err != nil { if err != nil {
return fmt.Errorf("failed to sign message: %w", err) return xerrors.Errorf("failed to sign message: %w", err)
} }
cid, err := api.MpoolPush(ctx, smsg) cid, err := api.MpoolPush(ctx, smsg)
if err != nil { if err != nil {
return fmt.Errorf("failed to push new message to mempool: %w", err) return xerrors.Errorf("failed to push new message to mempool: %w", err)
} }
fmt.Println("new message cid: ", cid) afmt.Println("new message cid: ", cid)
return nil return nil
}, },
} }
@ -531,6 +538,8 @@ var MpoolFindCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
afmt := NewAppFmt(cctx.App)
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -548,7 +557,7 @@ var MpoolFindCmd = &cli.Command{
if cctx.IsSet("to") { if cctx.IsSet("to") {
a, err := address.NewFromString(cctx.String("to")) a, err := address.NewFromString(cctx.String("to"))
if err != nil { if err != nil {
return fmt.Errorf("'to' address was invalid: %w", err) return xerrors.Errorf("'to' address was invalid: %w", err)
} }
toFilter = a toFilter = a
@ -557,7 +566,7 @@ var MpoolFindCmd = &cli.Command{
if cctx.IsSet("from") { if cctx.IsSet("from") {
a, err := address.NewFromString(cctx.String("from")) a, err := address.NewFromString(cctx.String("from"))
if err != nil { if err != nil {
return fmt.Errorf("'from' address was invalid: %w", err) return xerrors.Errorf("'from' address was invalid: %w", err)
} }
fromFilter = a fromFilter = a
@ -591,7 +600,7 @@ var MpoolFindCmd = &cli.Command{
return err return err
} }
fmt.Println(string(b)) afmt.Println(string(b))
return nil return nil
}, },
} }
@ -605,6 +614,8 @@ var MpoolConfig = &cli.Command{
return cli.ShowCommandHelp(cctx, cctx.Command.Name) return cli.ShowCommandHelp(cctx, cctx.Command.Name)
} }
afmt := NewAppFmt(cctx.App)
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -624,7 +635,7 @@ var MpoolConfig = &cli.Command{
return err return err
} }
fmt.Println(string(bytes)) afmt.Println(string(bytes))
} else { } else {
cfg := new(types.MpoolConfig) cfg := new(types.MpoolConfig)
bytes := []byte(cctx.Args().Get(0)) bytes := []byte(cctx.Args().Get(0))
@ -651,6 +662,8 @@ var MpoolGasPerfCmd = &cli.Command{
}, },
}, },
Action: func(cctx *cli.Context) error { Action: func(cctx *cli.Context) error {
afmt := NewAppFmt(cctx.App)
api, closer, err := GetFullNodeAPI(cctx) api, closer, err := GetFullNodeAPI(cctx)
if err != nil { if err != nil {
return err return err
@ -717,7 +730,7 @@ var MpoolGasPerfCmd = &cli.Command{
gasReward := getGasReward(m) gasReward := getGasReward(m)
gasPerf := getGasPerf(gasReward, m.Message.GasLimit) gasPerf := getGasPerf(gasReward, m.Message.GasLimit)
fmt.Printf("%s\t%d\t%s\t%f\n", m.Message.From, m.Message.Nonce, gasReward, gasPerf) afmt.Printf("%s\t%d\t%s\t%f\n", m.Message.From, m.Message.Nonce, gasReward, gasPerf)
} }
return nil return nil

522
cli/mpool_test.go Normal file
View File

@ -0,0 +1,522 @@
package cli
import (
"context"
"fmt"
"testing"
"encoding/json"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/types/mock"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
func TestStat(t *testing.T) {
t.Run("local", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolStat))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// add blocks to the chain
first := mock.TipSet(mock.MkBlock(nil, 5, 4))
head := mock.TipSet(mock.MkBlock(first, 15, 7))
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
// mock actor to return for the sender
actor := types.Actor{Nonce: 2, Balance: big.NewInt(200000)}
gomock.InOrder(
mockApi.EXPECT().ChainHead(ctx).Return(head, nil),
mockApi.EXPECT().ChainGetTipSet(ctx, head.Parents()).Return(first, nil),
mockApi.EXPECT().WalletList(ctx).Return([]address.Address{senderAddr, toAddr}, nil),
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
mockApi.EXPECT().StateGetActor(ctx, senderAddr, head.Key()).Return(&actor, nil),
)
err = app.Run([]string{"mpool", "stat", "--basefee-lookback", "1", "--local"})
assert.NoError(t, err)
assert.Contains(t, buf.String(), "Nonce past: 1")
})
t.Run("all", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolStat))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// add blocks to the chain
first := mock.TipSet(mock.MkBlock(nil, 5, 4))
head := mock.TipSet(mock.MkBlock(first, 15, 7))
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
// mock actor to return for the sender
actor := types.Actor{Nonce: 2, Balance: big.NewInt(200000)}
gomock.InOrder(
mockApi.EXPECT().ChainHead(ctx).Return(head, nil),
mockApi.EXPECT().ChainGetTipSet(ctx, head.Parents()).Return(first, nil),
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
mockApi.EXPECT().StateGetActor(ctx, senderAddr, head.Key()).Return(&actor, nil),
)
err = app.Run([]string{"mpool", "stat", "--basefee-lookback", "1"})
assert.NoError(t, err)
assert.Contains(t, buf.String(), "Nonce past: 1")
})
}
func TestPending(t *testing.T) {
t.Run("all", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
)
err = app.Run([]string{"mpool", "pending", "--cids"})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
t.Run("local", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().WalletList(ctx).Return([]address.Address{senderAddr}, nil),
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
)
err = app.Run([]string{"mpool", "pending", "--local"})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
t.Run("to", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
)
err = app.Run([]string{"mpool", "pending", "--to", sm.Message.To.String()})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
t.Run("from", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolPending))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
)
err = app.Run([]string{"mpool", "pending", "--from", sm.Message.From.String()})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
}
func TestReplace(t *testing.T) {
t.Run("manual", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolReplaceCmd))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().ChainGetMessage(ctx, sm.Cid()).Return(&sm.Message, nil),
mockApi.EXPECT().ChainHead(ctx).Return(nil, nil),
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
mockApi.EXPECT().WalletSignMessage(ctx, sm.Message.From, &sm.Message).Return(sm, nil),
mockApi.EXPECT().MpoolPush(ctx, sm).Return(sm.Cid(), nil),
)
err = app.Run([]string{"mpool", "replace", "--gas-premium", "1", "--gas-feecap", "100", sm.Cid().String()})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
t.Run("auto", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolReplaceCmd))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
// gas fee param should be equal to the one passed in the cli invocation (used below)
maxFee := "1000000"
parsedFee, err := types.ParseFIL(maxFee)
if err != nil {
t.Fatal(err)
}
mss := api.MessageSendSpec{MaxFee: abi.TokenAmount(parsedFee)}
gomock.InOrder(
mockApi.EXPECT().ChainGetMessage(ctx, sm.Cid()).Return(&sm.Message, nil),
mockApi.EXPECT().ChainHead(ctx).Return(nil, nil),
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
// use gomock.any to match the message in expected api calls
// since the replace function modifies the message between calls, it would be pointless to try to match the exact argument
mockApi.EXPECT().GasEstimateMessageGas(ctx, gomock.Any(), &mss, types.EmptyTSK).Return(&sm.Message, nil),
mockApi.EXPECT().WalletSignMessage(ctx, sm.Message.From, gomock.Any()).Return(sm, nil),
mockApi.EXPECT().MpoolPush(ctx, sm).Return(sm.Cid(), nil),
)
err = app.Run([]string{"mpool", "replace", "--auto", "--fee-limit", maxFee, sm.Cid().String()})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
}
func TestFindMsg(t *testing.T) {
t.Run("from", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolFindCmd))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
)
err = app.Run([]string{"mpool", "find", "--from", sm.Message.From.String()})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
t.Run("to", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolFindCmd))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
)
err = app.Run([]string{"mpool", "find", "--to", sm.Message.To.String()})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
t.Run("method", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolFindCmd))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 1, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
)
err = app.Run([]string{"mpool", "find", "--method", sm.Message.Method.String()})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Cid().String())
})
}
func TestGasPerf(t *testing.T) {
t.Run("all", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolGasPerfCmd))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// add blocks to the chain
first := mock.TipSet(mock.MkBlock(nil, 5, 4))
head := mock.TipSet(mock.MkBlock(first, 15, 7))
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 13, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
mockApi.EXPECT().ChainHead(ctx).Return(head, nil),
)
err = app.Run([]string{"mpool", "gas-perf", "--all", "true"})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Message.From.String())
assert.Contains(t, buf.String(), fmt.Sprint(sm.Message.Nonce))
})
t.Run("local", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolGasPerfCmd))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// add blocks to the chain
first := mock.TipSet(mock.MkBlock(nil, 5, 4))
head := mock.TipSet(mock.MkBlock(first, 15, 7))
// create a signed message to be returned as a pending message
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
toAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
sm := mock.MkMessage(senderAddr, toAddr, 13, w)
gomock.InOrder(
mockApi.EXPECT().MpoolPending(ctx, types.EmptyTSK).Return([]*types.SignedMessage{sm}, nil),
mockApi.EXPECT().WalletList(ctx).Return([]address.Address{senderAddr}, nil),
mockApi.EXPECT().ChainHead(ctx).Return(head, nil),
)
err = app.Run([]string{"mpool", "gas-perf"})
assert.NoError(t, err)
assert.Contains(t, buf.String(), sm.Message.From.String())
assert.Contains(t, buf.String(), fmt.Sprint(sm.Message.Nonce))
})
}
func TestConfig(t *testing.T) {
t.Run("get", func(t *testing.T) {
app, mockApi, buf, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolConfig))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
mpoolCfg := &types.MpoolConfig{PriorityAddrs: []address.Address{senderAddr}, SizeLimitHigh: 1234567, SizeLimitLow: 6, ReplaceByFeeRatio: 0.25}
gomock.InOrder(
mockApi.EXPECT().MpoolGetConfig(ctx).Return(mpoolCfg, nil),
)
err = app.Run([]string{"mpool", "config"})
assert.NoError(t, err)
assert.Contains(t, buf.String(), mpoolCfg.PriorityAddrs[0].String())
assert.Contains(t, buf.String(), fmt.Sprint(mpoolCfg.SizeLimitHigh))
assert.Contains(t, buf.String(), fmt.Sprint(mpoolCfg.SizeLimitLow))
assert.Contains(t, buf.String(), fmt.Sprint(mpoolCfg.ReplaceByFeeRatio))
})
t.Run("set", func(t *testing.T) {
app, mockApi, _, done := NewMockAppWithFullAPI(t, WithCategory("mpool", MpoolConfig))
defer done()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
senderAddr, err := w.WalletNew(context.Background(), types.KTSecp256k1)
if err != nil {
t.Fatal(err)
}
mpoolCfg := &types.MpoolConfig{PriorityAddrs: []address.Address{senderAddr}, SizeLimitHigh: 234567, SizeLimitLow: 3, ReplaceByFeeRatio: 0.33}
gomock.InOrder(
mockApi.EXPECT().MpoolSetConfig(ctx, mpoolCfg).Return(nil),
)
bytes, err := json.Marshal(mpoolCfg)
if err != nil {
t.Fatal(err)
}
err = app.Run([]string{"mpool", "config", string(bytes)})
assert.NoError(t, err)
})
}