Skip to content

Commit

Permalink
Problem: tx delivery performance is not benchmarked
Browse files Browse the repository at this point in the history
Solution:
- add the first benchmark for tx delivery
  • Loading branch information
yihuang committed Mar 14, 2023
1 parent afc82ed commit f22129e
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 2 deletions.
142 changes: 142 additions & 0 deletions app/bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package app

import (
"encoding/binary"
"encoding/json"
"math/big"
"testing"

sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/testutil/mock"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/crypto-org-chain/cronos/v2/x/cronos/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/evmos/ethermint/crypto/ethsecp256k1"
"github.com/evmos/ethermint/tests"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"
)

// BenchmarkERC20Transfer benchmarks execution of standard erc20 token transfer transactions
func BenchmarkERC20Transfer(b *testing.B) {
txsPerBlock := 1000
gasPrice := big.NewInt(100000000000)

encodingConfig := MakeEncodingConfig()
db := dbm.NewMemDB()
app := New(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encodingConfig, EmptyAppOptions{})

priv, err := ethsecp256k1.GenerateKey()
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
signer := tests.NewSigner(priv)
chainID := big.NewInt(777)
ethSigner := ethtypes.LatestSignerForChainID(chainID)

signTx := func(msg *evmtypes.MsgEthereumTx) ([]byte, error) {
msg.From = address.String()
if err := msg.Sign(ethSigner, signer); err != nil {
return nil, err
}
require.NoError(b, err)
tx, err := msg.BuildTx(encodingConfig.TxConfig.NewTxBuilder(), evmtypes.DefaultEVMDenom)
if err != nil {
return nil, err
}
return encodingConfig.TxConfig.TxEncoder()(tx)
}

privVal := mock.NewPV()
pubKey, err := privVal.GetPubKey()
consAddress := sdk.ConsAddress(pubKey.Address())
require.NoError(b, err)
validator := tmtypes.NewValidator(pubKey, 1)
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
acc := authtypes.NewBaseAccount(priv.PubKey().Address().Bytes(), priv.PubKey(), 0, 0)
balance := banktypes.Balance{
Address: acc.GetAddress().String(),
Coins: sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewIntWithDecimal(10000000, 18))),
}
genesisState := NewDefaultGenesisState(encodingConfig.Codec)
genesisState = genesisStateWithValSet(b, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)

appState, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(b, err)
app.InitChain(abci.RequestInitChain{
ChainId: SimAppChainID,
AppStateBytes: appState,
ConsensusParams: DefaultConsensusParams,
})
app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: 1,
ChainID: SimAppChainID,
ProposerAddress: consAddress,
},
})

// deploy contract
ctx := app.GetContextForDeliverTx(nil)
contractAddr, err := app.CronosKeeper.DeployModuleCRC21(ctx, "test")
require.NoError(b, err)

// mint to sender
amount := int64(100000000)
ret, err := app.CronosKeeper.CallModuleCRC21(ctx, contractAddr, "mint_by_cronos_module", address, big.NewInt(amount))
require.NoError(b, err)

// check balance
ret, err = app.CronosKeeper.CallModuleCRC21(ctx, contractAddr, "balanceOf", address)
require.NoError(b, err)
require.Equal(b, uint64(amount), binary.BigEndian.Uint64(ret[32-8:]))

app.EndBlock(abci.RequestEndBlock{})
app.Commit()

// prepare transactions
var transferTxs [][]byte
for i := 0; i < b.N; i++ {
for j := 0; j < txsPerBlock; j++ {
idx := int64(i*txsPerBlock + j)
recipient := common.BigToAddress(big.NewInt(idx))
data, err := types.ModuleCRC21Contract.ABI.Pack("transfer", recipient, big.NewInt(1))
bz, err := signTx(evmtypes.NewTx(chainID, uint64(idx), &contractAddr, big.NewInt(0), 210000, gasPrice, nil, nil, data, nil))
require.NoError(b, err)
transferTxs = append(transferTxs, bz)
}
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
app.BeginBlock(abci.RequestBeginBlock{
Header: tmproto.Header{
Height: int64(i) + 2,
ChainID: SimAppChainID,
ProposerAddress: consAddress,
},
})
for j := 0; j < txsPerBlock; j++ {
idx := i*txsPerBlock + j
res := app.DeliverTx(abci.RequestDeliverTx{
Tx: transferTxs[idx],
})
require.Equal(b, 0, int(res.Code))
}

// check remaining balance
ctx := app.GetContextForDeliverTx(nil)
ret, err = app.CronosKeeper.CallModuleCRC21(ctx, contractAddr, "balanceOf", address)
require.NoError(b, err)
require.Equal(b, uint64(amount)-uint64((i+1)*txsPerBlock), binary.BigEndian.Uint64(ret[32-8:]))

app.EndBlock(abci.RequestEndBlock{})
app.Commit()
}
}
4 changes: 2 additions & 2 deletions app/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const (
var DefaultConsensusParams = &abci.ConsensusParams{
Block: &abci.BlockParams{
MaxBytes: 200000,
MaxGas: 2000000,
MaxGas: 200000000,
},
Evidence: &tmproto.EvidenceParams{
MaxAgeNumBlocks: 302400,
Expand Down Expand Up @@ -131,7 +131,7 @@ func SetupWithGenesisValSet(t *testing.T, cronosAdmin string, valSet *tmtypes.Va
return app
}

func genesisStateWithValSet(t *testing.T,
func genesisStateWithValSet(t require.TestingT,
app *App, genesisState GenesisState,
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount,
balances ...banktypes.Balance,
Expand Down

0 comments on commit f22129e

Please sign in to comment.