Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

benchmark evm message calls #717

Merged
merged 2 commits into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions scripts/gen-tests-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
solc --combined-json bin,abi --allow-paths . ./tests/solidity/suites/staking/contracts/test/mocks/StandardTokenMock.sol \
| jq ".contracts.\"./tests/solidity/suites/staking/contracts/test/mocks/StandardTokenMock.sol:StandardTokenMock\"" \
> x/evm/types/ERC20Contract.json

solc --combined-json bin,abi --allow-paths . ./tests/solidity/suites/basic/contracts/TestMessageCall.sol \
| jq ".contracts.\"./tests/solidity/suites/basic/contracts/TestMessageCall.sol:TestMessageCall\"" \
> x/evm/types/TestMessageCall.json
25 changes: 25 additions & 0 deletions tests/solidity/suites/basic/contracts/TestMessageCall.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
pragma solidity 0.5.17;

contract Inner {
event TestEvent(uint256);
function test() public returns (uint256) {
emit TestEvent(42);
return 42;
}
}

contract TestMessageCall {
Inner _inner;
constructor() public {
_inner = new Inner();
}

// benchmarks
function benchmarkMessageCall(uint iterations) public returns (uint256) {
uint256 n = 0;
for (uint i=0; i < iterations; i++) {
n += _inner.test();
}
return n;
}
}
47 changes: 47 additions & 0 deletions x/evm/keeper/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ func SetupContract(b *testing.B) (*KeeperTestSuite, common.Address) {
return &suite, contractAddr
}

func SetupTestMessageCall(b *testing.B) (*KeeperTestSuite, common.Address) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

amt := sdk.Coins{ethermint.NewPhotonCoinInt64(1000000000000000000)}
err := suite.app.BankKeeper.MintCoins(suite.ctx, types.ModuleName, amt)
require.NoError(b, err)
err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, suite.address.Bytes(), amt)
require.NoError(b, err)

contractAddr := suite.DeployTestMessageCall(b)
suite.Commit()

return &suite, contractAddr
}

type TxBuilder func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx

func DoBenchmark(b *testing.B, txBuilder TxBuilder) {
Expand Down Expand Up @@ -97,6 +113,37 @@ func BenchmarkTokenMint(b *testing.B) {
})
}

func BenchmarkMessageCall(b *testing.B) {
suite, contract := SetupTestMessageCall(b)

input, err := types.TestMessageCall.ABI.Pack("benchmarkMessageCall", big.NewInt(10000))
require.NoError(b, err)
nonce := suite.app.EvmKeeper.GetNonce(suite.address)
msg := types.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &contract, big.NewInt(0), 25000000, big.NewInt(1), nil, nil, input, nil)

msg.From = suite.address.Hex()
err = msg.Sign(ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()), suite.signer)
require.NoError(b, err)

b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
ctx, _ := suite.ctx.CacheContext()

// deduct fee first
txData, err := types.UnpackTxData(msg.Data)
require.NoError(b, err)

fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdk.NewIntFromBigInt(txData.Fee()))}
err = authante.DeductFees(suite.app.BankKeeper, suite.ctx, suite.app.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees)
require.NoError(b, err)

rsp, err := suite.app.EvmKeeper.EthereumTx(sdk.WrapSDKContext(ctx), msg)
require.NoError(b, err)
require.False(b, rsp.Failed())
}
}

func DoBenchmarkDeepContextStack(b *testing.B, depth int) {
begin := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
end := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
Expand Down
55 changes: 55 additions & 0 deletions x/evm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,61 @@ func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAdd
return ercTransferTx
}

// DeployTestMessageCall deploy a test erc20 contract and returns the contract address
func (suite *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.Address {
ctx := sdk.WrapSDKContext(suite.ctx)
chainID := suite.app.EvmKeeper.ChainID()

data := types.TestMessageCall.Bin
args, err := json.Marshal(&types.TransactionArgs{
From: &suite.address,
Data: (*hexutil.Bytes)(&data),
})
require.NoError(t, err)

res, err := suite.queryClient.EstimateGas(ctx, &types.EthCallRequest{
Args: args,
GasCap: uint64(config.DefaultGasCap),
})
require.NoError(t, err)

nonce := suite.app.EvmKeeper.GetNonce(suite.address)

var erc20DeployTx *types.MsgEthereumTx
if suite.dynamicTxFee {
erc20DeployTx = types.NewTxContract(
chainID,
nonce,
nil, // amount
res.Gas, // gasLimit
nil, // gasPrice
suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx),
big.NewInt(1),
data, // input
&ethtypes.AccessList{}, // accesses
)
} else {
erc20DeployTx = types.NewTxContract(
chainID,
nonce,
nil, // amount
res.Gas, // gasLimit
nil, // gasPrice
nil, nil,
data, // input
nil, // accesses
)
}

erc20DeployTx.From = suite.address.Hex()
err = erc20DeployTx.Sign(ethtypes.LatestSignerForChainID(chainID), suite.signer)
require.NoError(t, err)
rsp, err := suite.app.EvmKeeper.EthereumTx(ctx, erc20DeployTx)
require.NoError(t, err)
require.Empty(t, rsp.VmError)
return crypto.CreateAddress(suite.address, nonce)
}

func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
4 changes: 4 additions & 0 deletions x/evm/types/TestMessageCall.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"abi": "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"iterations\",\"type\":\"uint256\"}],\"name\":\"benchmarkMessageCall\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
"bin": "608060405234801561001057600080fd5b5060405161001d9061007e565b604051809103906000f080158015610039573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061008a565b60dd8061021483390190565b61017b806100996000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806376e489f014610030575b600080fd5b61005c6004803603602081101561004657600080fd5b8101908080359060200190929190505050610072565b6040518082815260200191505060405180910390f35b6000806000905060008090505b8381101561013c576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f8a8fd6d6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156100f057600080fd5b505af1158015610104573d6000803e3d6000fd5b505050506040513d602081101561011a57600080fd5b810190808051906020019092919050505082019150808060010191505061007f565b508091505091905056fea265627a7a723158203bb5ea1d2b128eb07e834f8b4cab93aab73270ef20cb80c1d5e0e2ee4f10b7c264736f6c634300051100326080604052348015600f57600080fd5b5060bf8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063f8a8fd6d14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b60007f1440c4dd67b4344ea1905ec0318995133b550f168b4ee959a0da6b503d7d2414602a6040518082815260200191505060405180910390a1602a90509056fea265627a7a723158209236549244199cceaef9525385c8b6fccaf6390440ece080e2046d9f4a0035f564736f6c63430005110032"
}
15 changes: 15 additions & 0 deletions x/evm/types/compiled_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ var (

// ERC20Contract is the compiled test erc20 contract
ERC20Contract CompiledContract

//go:embed TestMessageCall.json
testMessageCallJSON []byte

// TestMessageCall is the compiled message call benchmark contract
TestMessageCall CompiledContract
)

func init() {
Expand All @@ -85,4 +91,13 @@ func init() {
if len(ERC20Contract.Bin) == 0 {
panic("load contract failed")
}

err = json.Unmarshal(testMessageCallJSON, &TestMessageCall)
if err != nil {
panic(err)
}

if len(TestMessageCall.Bin) == 0 {
panic("load contract failed")
}
}