From 96c05451f462e8ed872bb8fa468cfecb88f7eb79 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:24:35 +0100 Subject: [PATCH] test(test/systemtests): Add GasImprovement test (backport #22927) (#23067) Co-authored-by: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Co-authored-by: Julien Robert --- tests/systemtests/tx_test.go | 114 +++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/tests/systemtests/tx_test.go b/tests/systemtests/tx_test.go index 6d8074a340..e0cca5c724 100644 --- a/tests/systemtests/tx_test.go +++ b/tests/systemtests/tx_test.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "os" + "strings" "testing" "github.com/stretchr/testify/require" @@ -1086,3 +1087,116 @@ func readTestAminoTxBinary(t *testing.T, aminoCodec *codec.LegacyAmino) ([]byte, require.NoError(t, err) return txJSONBytes, &stdTx } + +func TestSimulateTx_GasImprovements(t *testing.T) { + if !systest.IsV2() { + t.Skip("This test was made for testing gas improvements for v2. It doesn't work as is for v1, because of how the v1 handles out of gas issues compared to v2 (server error instead of proper response). This makes this test not compatible with v1.") + } + + systest.Sut.ResetChain(t) + + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) + // get validator address + valAddr := cli.GetKeyAddr("node0") + // use node 1 as granter + granter := cli.GetKeyAddr("node1") + + require.NotEmpty(t, valAddr) + + // add new key + receiverAddr := cli.AddKey("account1") + + systest.Sut.StartChain(t) + + baseURL := systest.Sut.APIAddress() + + // node1 grant to node0 + grantCmdArgs := []string{"tx", "feegrant", "grant", granter, valAddr, "--chain-id=" + cli.ChainID()} + rsp := cli.Run(grantCmdArgs...) + txResult, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) + systest.RequireTxSuccess(t, txResult) + + sendSimulateCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + cli.ChainID(), "--sign-mode=direct", "--generate-only"} + bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + cli.ChainID()} + testCases := []struct { + name string + simulateArgs []string + txArgs []string + }{ + { + "simulate without fees", + sendSimulateCmdArgs, + bankSendCmdArgs, + }, + { + "simulate with fees", + append(sendSimulateCmdArgs, "--fees=1stake"), + bankSendCmdArgs, + }, + { + "simulate without fee-granter", + sendSimulateCmdArgs, + append(bankSendCmdArgs, fmt.Sprintf("--fee-granter=%s", granter)), + }, + { + "simulate with fee-granter", + append(sendSimulateCmdArgs, fmt.Sprintf("--fee-granter=%s", granter)), + append(bankSendCmdArgs, fmt.Sprintf("--fee-granter=%s", granter)), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + txlen := 1 + gasSimulated := make([]int64, txlen) + gasAdjustment := make([]float64, txlen) + + for i := 0; i < txlen; i++ { + // create unsign tx + res := cli.RunCommandWithArgs(tc.simulateArgs...) + txFile := systest.StoreTempFile(t, []byte(res)) + + res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), "--from="+valAddr, "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home="+systest.Sut.NodeDir(0)) + signedTxFile := systest.StoreTempFile(t, []byte(res)) + + res = cli.RunCommandWithArgs("tx", "encode", signedTxFile.Name()) + txBz, err := base64.StdEncoding.DecodeString(res) + require.NoError(t, err) + + reqBz, err := json.Marshal(&tx.SimulateRequest{TxBytes: txBz}) + require.NoError(t, err) + + resBz, err := testutil.PostRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/simulate", baseURL), "application/json", reqBz) + require.NoError(t, err) + gasUsed := gjson.Get(string(resBz), "gas_info.gas_used").Int() + require.True(t, gasUsed > 0) + gasSimulated[i] = gasUsed + } + + for i := 0; i < txlen; i++ { + // Submit tx with gas return from simulate + gasAdjustment[i] = 0.99 + // test valid transaction + shouldRerun := true + for shouldRerun { + gasAdjustment[i] = gasAdjustment[i] + 0.01 + gasUse := int64(gasAdjustment[i] * float64(gasSimulated[i])) + rsp := cli.Run(append(tc.txArgs, fmt.Sprintf("--gas=%d", gasUse))...) + // rerun if tx err and increase gas-adjustment by 1% + shouldRerun = strings.Contains(gjson.Get(rsp, "raw_log").String(), "out of gas") || gjson.Get(rsp, "gas_used").Int() == int64(0) || gjson.Get(rsp, "code").Int() != 0 + fmt.Println("gasAdjustment", i, gasAdjustment[i]) + } + } + + // Calculate average adjustments + total := 0.0 + for i := 0; i < txlen; i++ { + total = total + gasAdjustment[i] + } + average := total / float64(txlen) + result := fmt.Sprintf("Test case %s average gas adjustment is: %f", tc.name, average) + fmt.Println(result) + }) + } +}