github.com/klaytn/klaytn@v1.12.1/tests/apply_tx_test.go (about)

     1  // Copyright 2019 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package tests
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"fmt"
    22  	"math/big"
    23  	"os"
    24  	"reflect"
    25  	"runtime"
    26  	"runtime/pprof"
    27  	"strings"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/klaytn/klaytn/blockchain/types"
    32  	"github.com/klaytn/klaytn/blockchain/types/accountkey"
    33  	"github.com/klaytn/klaytn/blockchain/vm"
    34  	"github.com/klaytn/klaytn/common"
    35  	"github.com/klaytn/klaytn/common/profile"
    36  	"github.com/klaytn/klaytn/crypto"
    37  	"github.com/klaytn/klaytn/log"
    38  	"github.com/klaytn/klaytn/params"
    39  	"github.com/stretchr/testify/assert"
    40  )
    41  
    42  var benchName string
    43  
    44  type genTx func(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction
    45  
    46  // BenchmarkTxPerformanceCompatible compares performance between a legacy transaction and new transaction types.
    47  // It compares the following:
    48  // - legacy value transfer vs. new value transfer
    49  // - legacy smart contract deploy vs. new smart contract deploy
    50  func BenchmarkTxPerformanceCompatible(b *testing.B) {
    51  	testfns := []genTx{
    52  		genLegacyValueTransfer,
    53  		genNewValueTransfer,
    54  		genLegacySmartContractDeploy,
    55  		genNewSmartContractDeploy,
    56  	}
    57  
    58  	for _, fn := range testfns {
    59  		fnname := getFunctionName(fn)
    60  		fnname = fnname[strings.LastIndex(fnname, ".")+1:]
    61  		if strings.Contains(fnname, "New") {
    62  			benchName = "New/" + strings.Split(fnname, "New")[1]
    63  		} else {
    64  			benchName = "Legacy/" + strings.Split(fnname, "Legacy")[1]
    65  		}
    66  		b.Run(benchName, func(b *testing.B) {
    67  			benchmarkTxPerformanceCompatible(b, fn)
    68  		})
    69  	}
    70  }
    71  
    72  // BenchmarkTxPerformanceSmartContractExecution compares performance between a legacy transaction and new transaction types.
    73  // This needs one more step "deploying a smart contract" compared to BenchmarkTxPerformanceCompatible.
    74  // It compares the following:
    75  // - legacy smart contract execution vs. new smart contract execution.
    76  func BenchmarkTxPerformanceSmartContractExecution(b *testing.B) {
    77  	testfns := []genTx{
    78  		genLegacySmartContractExecution,
    79  		genNewSmartContractExecution,
    80  	}
    81  
    82  	for _, fn := range testfns {
    83  		fnname := getFunctionName(fn)
    84  		fnname = fnname[strings.LastIndex(fnname, ".")+1:]
    85  		if strings.Contains(fnname, "New") {
    86  			benchName = "New/" + strings.Split(fnname, "New")[1]
    87  		} else {
    88  			benchName = "Legacy/" + strings.Split(fnname, "Legacy")[1]
    89  		}
    90  		b.Run(benchName, func(b *testing.B) {
    91  			benchmarkTxPerformanceSmartContractExecution(b, fn)
    92  		})
    93  	}
    94  }
    95  
    96  // BenchmarkTxPerformanceNew measures performance of newly introduced transaction types.
    97  // This requires one more step "account creation of a Klaytn account" compared to BenchmarkTxPerformanceCompatible.
    98  func BenchmarkTxPerformanceNew(b *testing.B) {
    99  	testfns := []genTx{
   100  		genNewAccountUpdateMultisig3,
   101  		genNewAccountUpdateRoleBasedSingle,
   102  		genNewAccountUpdateRoleBasedMultisig3,
   103  		genNewAccountUpdateAccountKeyPublic,
   104  		genNewFeeDelegatedValueTransfer,
   105  		genNewFeeDelegatedValueTransferWithRatio,
   106  		genNewCancel,
   107  	}
   108  
   109  	// sender account
   110  	sender, err := createDecoupledAccount("c64f2cd1196e2a1791365b00c4bc07ab8f047b73152e4617c6ed06ac221a4b0c",
   111  		common.HexToAddress("0x75c3098be5e4b63fbac05838daaee378dd48098d"))
   112  	assert.Equal(b, nil, err)
   113  
   114  	for _, fn := range testfns {
   115  		fnname := getFunctionName(fn)
   116  		fnname = fnname[strings.LastIndex(fnname, ".")+1:]
   117  		if strings.Contains(fnname, "New") {
   118  			benchName = "New/" + strings.Split(fnname, "New")[1]
   119  		} else {
   120  			benchName = "Legacy/" + strings.Split(fnname, "Legacy")[1]
   121  		}
   122  		b.Run(benchName, func(b *testing.B) {
   123  			sender.Nonce = 0
   124  			benchmarkTxPerformanceNew(b, fn, sender)
   125  		})
   126  	}
   127  }
   128  
   129  func BenchmarkTxPerformanceNewMultisig(b *testing.B) {
   130  	testfns := []genTx{
   131  		genNewAccountUpdateMultisig3,
   132  		genNewAccountUpdateRoleBasedSingle,
   133  		genNewAccountUpdateRoleBasedMultisig3,
   134  		genNewAccountUpdateAccountKeyPublic,
   135  		genNewFeeDelegatedValueTransfer,
   136  		genNewFeeDelegatedValueTransferWithRatio,
   137  		genNewCancel,
   138  	}
   139  
   140  	// sender account
   141  	sender, err := createMultisigAccount(uint(2),
   142  		[]uint{1, 1, 1},
   143  		[]string{
   144  			"bb113e82881499a7a361e8354a5b68f6c6885c7bcba09ea2b0891480396c322e",
   145  			"a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989",
   146  			"c32c471b732e2f56103e2f8e8cfd52792ef548f05f326e546a7d1fbf9d0419ec",
   147  		},
   148  		common.HexToAddress("0xbbfa38050bf3167c887c086758f448ce067ea8ea"))
   149  	assert.Equal(b, nil, err)
   150  
   151  	for _, fn := range testfns {
   152  		fnname := getFunctionName(fn)
   153  		fnname = fnname[strings.LastIndex(fnname, ".")+1:]
   154  		if strings.Contains(fnname, "New") {
   155  			benchName = "New/" + strings.Split(fnname, "New")[1]
   156  		} else {
   157  			benchName = "Legacy/" + strings.Split(fnname, "Legacy")[1]
   158  		}
   159  		b.Run(benchName, func(b *testing.B) {
   160  			sender.Nonce = 0
   161  			benchmarkTxPerformanceNew(b, fn, sender)
   162  		})
   163  	}
   164  }
   165  
   166  func BenchmarkTxPerformanceNewRoleBasedSingle(b *testing.B) {
   167  	testfns := []genTx{
   168  		genNewAccountUpdateMultisig3,
   169  		genNewAccountUpdateRoleBasedSingle,
   170  		genNewAccountUpdateRoleBasedMultisig3,
   171  		genNewAccountUpdateAccountKeyPublic,
   172  		genNewFeeDelegatedValueTransfer,
   173  		genNewFeeDelegatedValueTransferWithRatio,
   174  		genNewCancel,
   175  	}
   176  
   177  	// sender account
   178  	k1, err := crypto.HexToECDSA("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
   179  	if err != nil {
   180  		panic(err)
   181  	}
   182  	pubkey := accountkey.NewAccountKeyPublicWithValue(&k1.PublicKey)
   183  	sender := &TestAccountType{
   184  		Addr:   common.HexToAddress("0x75c3098be5e4b63fbac05838daaee378dd48098d"),
   185  		Keys:   []*ecdsa.PrivateKey{k1},
   186  		Nonce:  uint64(0),
   187  		AccKey: accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{pubkey, pubkey, pubkey}),
   188  	}
   189  
   190  	for _, fn := range testfns {
   191  		fnname := getFunctionName(fn)
   192  		fnname = fnname[strings.LastIndex(fnname, ".")+1:]
   193  		if strings.Contains(fnname, "New") {
   194  			benchName = "New/" + strings.Split(fnname, "New")[1]
   195  		} else {
   196  			benchName = "Legacy/" + strings.Split(fnname, "Legacy")[1]
   197  		}
   198  		b.Run(benchName, func(b *testing.B) {
   199  			sender.Nonce = 0
   200  			benchmarkTxPerformanceNew(b, fn, sender)
   201  		})
   202  	}
   203  }
   204  
   205  func BenchmarkTxPerformanceNewRoleBasedMultisig3(b *testing.B) {
   206  	testfns := []genTx{
   207  		genNewAccountUpdateMultisig3,
   208  		genNewAccountUpdateRoleBasedSingle,
   209  		genNewAccountUpdateRoleBasedMultisig3,
   210  		genNewAccountUpdateAccountKeyPublic,
   211  		genNewFeeDelegatedValueTransfer,
   212  		genNewFeeDelegatedValueTransferWithRatio,
   213  		genNewCancel,
   214  	}
   215  
   216  	// sender account
   217  	k1, err := crypto.HexToECDSA("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
   218  	if err != nil {
   219  		panic(err)
   220  	}
   221  	k2, err := crypto.HexToECDSA("c64f2cd1196e2a1791365b00c4bc07ab8f047b73152e4617c6ed06ac221a4b0c")
   222  	if err != nil {
   223  		panic(err)
   224  	}
   225  	k3, err := crypto.HexToECDSA("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20")
   226  	if err != nil {
   227  		panic(err)
   228  	}
   229  
   230  	keys := accountkey.WeightedPublicKeys{
   231  		accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k1.PublicKey)),
   232  		accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k2.PublicKey)),
   233  		accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k3.PublicKey)),
   234  	}
   235  	threshold := uint(2)
   236  	pubkey := accountkey.NewAccountKeyWeightedMultiSigWithValues(threshold, keys)
   237  	sender := &TestAccountType{
   238  		Addr:   common.HexToAddress("0x75c3098be5e4b63fbac05838daaee378dd48098d"),
   239  		Keys:   []*ecdsa.PrivateKey{k1, k2, k3},
   240  		Nonce:  uint64(0),
   241  		AccKey: accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{pubkey, pubkey, pubkey}),
   242  	}
   243  
   244  	for _, fn := range testfns {
   245  		fnname := getFunctionName(fn)
   246  		fnname = fnname[strings.LastIndex(fnname, ".")+1:]
   247  		if strings.Contains(fnname, "New") {
   248  			benchName = "New/" + strings.Split(fnname, "New")[1]
   249  		} else {
   250  			benchName = "Legacy/" + strings.Split(fnname, "Legacy")[1]
   251  		}
   252  		b.Run(benchName, func(b *testing.B) {
   253  			sender.Nonce = 0
   254  			benchmarkTxPerformanceNew(b, fn, sender)
   255  		})
   256  	}
   257  }
   258  
   259  func benchmarkTxPerformanceCompatible(b *testing.B, genTx genTx) {
   260  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   261  
   262  	// Initialize blockchain
   263  	bcdata, err := NewBCData(6, 4)
   264  	if err != nil {
   265  		b.Fatal(err)
   266  	}
   267  	defer bcdata.Shutdown()
   268  
   269  	// Initialize address-balance map for verification
   270  	accountMap := NewAccountMap()
   271  	if err := accountMap.Initialize(bcdata); err != nil {
   272  		b.Fatal(err)
   273  	}
   274  
   275  	// reservoir account
   276  	reservoir := &TestAccountType{
   277  		Addr:  *bcdata.addrs[0],
   278  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   279  		Nonce: uint64(0),
   280  	}
   281  
   282  	// anonymous account
   283  	anon, err := createAnonymousAccount("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20")
   284  	assert.Equal(b, nil, err)
   285  
   286  	if testing.Verbose() {
   287  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   288  		fmt.Println("anonAddr = ", anon.Addr.String())
   289  	}
   290  
   291  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   292  
   293  	// Prepare a next block header.
   294  	author := bcdata.addrs[0]
   295  	vmConfig := &vm.Config{
   296  		JumpTable: vm.ConstantinopleInstructionSet,
   297  	}
   298  	parent := bcdata.bc.CurrentBlock()
   299  	num := parent.Number()
   300  	header := &types.Header{
   301  		ParentHash: parent.Hash(),
   302  		Number:     num.Add(num, common.Big1),
   303  		Extra:      parent.Extra(),
   304  		Time:       new(big.Int).Add(parent.Time(), common.Big1),
   305  	}
   306  	if err := bcdata.engine.Prepare(bcdata.bc, header); err != nil {
   307  		b.Fatal(err)
   308  	}
   309  
   310  	state, err := bcdata.bc.State()
   311  	assert.Equal(b, nil, err)
   312  
   313  	txs := make([]*types.Transaction, b.N)
   314  
   315  	// Generate transactions.
   316  	for i := 0; i < b.N; i++ {
   317  		tx := genTx(signer, reservoir, anon)
   318  
   319  		txs[i] = tx
   320  
   321  		reservoir.Nonce += 1
   322  
   323  		// execute this to cache ecrecover.
   324  		tx.AsMessageWithAccountKeyPicker(signer, state, header.Number.Uint64())
   325  	}
   326  
   327  	if isProfileEnabled() {
   328  		fname := strings.Replace(benchName, "/", ".", -1)
   329  		f, err := os.Create(fname + ".cpu.out")
   330  		if err != nil {
   331  			panic(err)
   332  		}
   333  		pprof.StartCPUProfile(f)
   334  		defer pprof.StopCPUProfile()
   335  	}
   336  	b.ResetTimer()
   337  	// Execute ApplyTransaction to measure performance of the given transaction type.
   338  	for i := 0; i < b.N; i++ {
   339  		usedGas := uint64(0)
   340  		_, _, err = bcdata.bc.ApplyTransaction(bcdata.bc.Config(), author, state, header, txs[i], &usedGas, vmConfig)
   341  		assert.Equal(b, nil, err)
   342  	}
   343  	b.StopTimer()
   344  }
   345  
   346  func benchmarkTxPerformanceSmartContractExecution(b *testing.B, genTx genTx) {
   347  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   348  	prof := profile.NewProfiler()
   349  
   350  	// Initialize blockchain
   351  	start := time.Now()
   352  	bcdata, err := NewBCData(6, 4)
   353  	if err != nil {
   354  		b.Fatal(err)
   355  	}
   356  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   357  	defer bcdata.Shutdown()
   358  
   359  	// Initialize address-balance map for verification
   360  	start = time.Now()
   361  	accountMap := NewAccountMap()
   362  	if err := accountMap.Initialize(bcdata); err != nil {
   363  		b.Fatal(err)
   364  	}
   365  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   366  
   367  	// reservoir account
   368  	reservoir := &TestAccountType{
   369  		Addr:  *bcdata.addrs[0],
   370  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   371  		Nonce: uint64(0),
   372  	}
   373  
   374  	if testing.Verbose() {
   375  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   376  	}
   377  
   378  	contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989")
   379  	contract.Addr = common.Address{}
   380  
   381  	gasPrice := new(big.Int).SetUint64(0)
   382  	gasLimit := uint64(100000000000)
   383  
   384  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   385  
   386  	// Deploy smart contract (reservoir -> contract)
   387  	{
   388  		var txs types.Transactions
   389  
   390  		code := "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"
   391  		amount := new(big.Int).SetUint64(0)
   392  
   393  		values := map[types.TxValueKeyType]interface{}{
   394  			types.TxValueKeyNonce:         reservoir.Nonce,
   395  			types.TxValueKeyFrom:          reservoir.Addr,
   396  			types.TxValueKeyTo:            (*common.Address)(nil),
   397  			types.TxValueKeyAmount:        amount,
   398  			types.TxValueKeyGasLimit:      gasLimit,
   399  			types.TxValueKeyGasPrice:      gasPrice,
   400  			types.TxValueKeyHumanReadable: false,
   401  			types.TxValueKeyData:          common.FromHex(code),
   402  		}
   403  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values)
   404  		assert.Equal(b, nil, err)
   405  
   406  		err = tx.SignWithKeys(signer, reservoir.Keys)
   407  		assert.Equal(b, nil, err)
   408  
   409  		txs = append(txs, tx)
   410  
   411  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   412  			b.Fatal(err)
   413  		}
   414  
   415  		contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   416  
   417  		reservoir.Nonce += 1
   418  	}
   419  
   420  	// Prepare a next block header.
   421  	author := bcdata.addrs[0]
   422  	vmConfig := &vm.Config{
   423  		JumpTable: vm.ConstantinopleInstructionSet,
   424  	}
   425  	parent := bcdata.bc.CurrentBlock()
   426  	num := parent.Number()
   427  	header := &types.Header{
   428  		ParentHash: parent.Hash(),
   429  		Number:     num.Add(num, common.Big1),
   430  		Extra:      parent.Extra(),
   431  		Time:       new(big.Int).Add(parent.Time(), common.Big1),
   432  	}
   433  	if err := bcdata.engine.Prepare(bcdata.bc, header); err != nil {
   434  		b.Fatal(err)
   435  	}
   436  
   437  	state, err := bcdata.bc.State()
   438  	assert.Equal(b, nil, err)
   439  
   440  	txs := make([]*types.Transaction, b.N)
   441  
   442  	// Generate transactions.
   443  	for i := 0; i < b.N; i++ {
   444  		tx := genTx(signer, reservoir, contract)
   445  
   446  		txs[i] = tx
   447  
   448  		reservoir.Nonce += 1
   449  
   450  		tx.AsMessageWithAccountKeyPicker(signer, state, header.Number.Uint64())
   451  	}
   452  
   453  	if isProfileEnabled() {
   454  		fname := strings.Replace(benchName, "/", ".", -1)
   455  		f, err := os.Create(fname + ".cpu.out")
   456  		if err != nil {
   457  			panic(err)
   458  		}
   459  		pprof.StartCPUProfile(f)
   460  		defer pprof.StopCPUProfile()
   461  	}
   462  	b.ResetTimer()
   463  	// Execute ApplyTransaction to measure performance of the given transaction type.
   464  	for i := 0; i < b.N; i++ {
   465  		usedGas := uint64(0)
   466  		_, _, err = bcdata.bc.ApplyTransaction(bcdata.bc.Config(), author, state, header, txs[i], &usedGas, vmConfig)
   467  		assert.Equal(b, nil, err)
   468  	}
   469  	b.StopTimer()
   470  
   471  	if testing.Verbose() {
   472  		prof.PrintProfileInfo()
   473  	}
   474  }
   475  
   476  func benchmarkTxPerformanceNew(b *testing.B, genTx genTx, sender *TestAccountType) {
   477  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   478  	prof := profile.NewProfiler()
   479  
   480  	// Initialize blockchain
   481  	bcdata, err := NewBCData(6, 4)
   482  	if err != nil {
   483  		b.Fatal(err)
   484  	}
   485  	defer bcdata.Shutdown()
   486  
   487  	// Initialize address-balance map for verification
   488  	accountMap := NewAccountMap()
   489  	if err := accountMap.Initialize(bcdata); err != nil {
   490  		b.Fatal(err)
   491  	}
   492  
   493  	// reservoir account
   494  	reservoir := &TestAccountType{
   495  		Addr:  *bcdata.addrs[0],
   496  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   497  		Nonce: uint64(0),
   498  	}
   499  
   500  	anon, err := createAnonymousAccount("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20")
   501  
   502  	if testing.Verbose() {
   503  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   504  		fmt.Println("decoupledAddr = ", sender.Addr.String())
   505  		fmt.Println("anonAddr = ", anon.Addr.String())
   506  	}
   507  
   508  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   509  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
   510  
   511  	// Create an account sender using TxTypeValueTransfer.
   512  	{
   513  		var txs types.Transactions
   514  
   515  		amount := new(big.Int).SetUint64(1000000000000)
   516  		values := map[types.TxValueKeyType]interface{}{
   517  			types.TxValueKeyNonce:    reservoir.Nonce,
   518  			types.TxValueKeyFrom:     reservoir.Addr,
   519  			types.TxValueKeyTo:       sender.Addr,
   520  			types.TxValueKeyAmount:   amount,
   521  			types.TxValueKeyGasLimit: gasLimit,
   522  			types.TxValueKeyGasPrice: gasPrice,
   523  		}
   524  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
   525  		assert.Equal(b, nil, err)
   526  
   527  		err = tx.SignWithKeys(signer, reservoir.Keys)
   528  		assert.Equal(b, nil, err)
   529  
   530  		txs = append(txs, tx)
   531  
   532  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   533  			b.Fatal(err)
   534  		}
   535  		reservoir.Nonce += 1
   536  	}
   537  
   538  	// Prepare a next block header.
   539  	author := bcdata.addrs[0]
   540  	vmConfig := &vm.Config{
   541  		JumpTable: vm.ConstantinopleInstructionSet,
   542  	}
   543  	parent := bcdata.bc.CurrentBlock()
   544  	num := parent.Number()
   545  	header := &types.Header{
   546  		ParentHash: parent.Hash(),
   547  		Number:     num.Add(num, common.Big1),
   548  		Extra:      parent.Extra(),
   549  		Time:       new(big.Int).Add(parent.Time(), common.Big1),
   550  	}
   551  	if err := bcdata.engine.Prepare(bcdata.bc, header); err != nil {
   552  		b.Fatal(err)
   553  	}
   554  
   555  	state, err := bcdata.bc.State()
   556  	assert.Equal(b, nil, err)
   557  
   558  	txs := make([]*types.Transaction, b.N)
   559  
   560  	// Generate transactions.
   561  	for i := 0; i < b.N; i++ {
   562  		tx := genTx(signer, sender, anon)
   563  
   564  		txs[i] = tx
   565  
   566  		sender.Nonce += 1
   567  
   568  		tx.AsMessageWithAccountKeyPicker(signer, state, header.Number.Uint64())
   569  	}
   570  
   571  	if isProfileEnabled() {
   572  		fname := strings.Replace(benchName, "/", ".", -1)
   573  		f, err := os.Create(fname + ".cpu.out")
   574  		if err != nil {
   575  			panic(err)
   576  		}
   577  		pprof.StartCPUProfile(f)
   578  		defer pprof.StopCPUProfile()
   579  	}
   580  	b.ResetTimer()
   581  	// Execute ApplyTransaction to measure performance of the given transaction type.
   582  	for i := 0; i < b.N; i++ {
   583  		usedGas := uint64(0)
   584  		_, _, err = bcdata.bc.ApplyTransaction(bcdata.bc.Config(), author, state, header, txs[i], &usedGas, vmConfig)
   585  		assert.Equal(b, nil, err)
   586  	}
   587  	b.StopTimer()
   588  
   589  	if testing.Verbose() {
   590  		prof.PrintProfileInfo()
   591  	}
   592  }
   593  
   594  func genLegacyValueTransfer(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   595  	amount := big.NewInt(100)
   596  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   597  	tx := types.NewTransaction(from.Nonce, to.Addr, amount, gasLimit, gasPrice, []byte{})
   598  	err := tx.SignWithKeys(signer, from.Keys)
   599  	if err != nil {
   600  		panic(err)
   601  	}
   602  
   603  	return tx
   604  }
   605  
   606  func genNewValueTransfer(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   607  	amount := big.NewInt(100)
   608  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   609  	tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, map[types.TxValueKeyType]interface{}{
   610  		types.TxValueKeyNonce:    from.Nonce,
   611  		types.TxValueKeyTo:       to.Addr,
   612  		types.TxValueKeyAmount:   amount,
   613  		types.TxValueKeyGasLimit: gasLimit,
   614  		types.TxValueKeyGasPrice: gasPrice,
   615  		types.TxValueKeyFrom:     from.Addr,
   616  	})
   617  	if err != nil {
   618  		panic(err)
   619  	}
   620  
   621  	err = tx.SignWithKeys(signer, from.Keys)
   622  	if err != nil {
   623  		panic(err)
   624  	}
   625  
   626  	return tx
   627  }
   628  
   629  func genLegacySmartContractDeploy(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   630  	amount := big.NewInt(0)
   631  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   632  	data := common.Hex2Bytes("608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029")
   633  	tx := types.NewContractCreation(from.Nonce, amount, gasLimit, gasPrice, data)
   634  	err := tx.SignWithKeys(signer, from.Keys)
   635  	if err != nil {
   636  		panic(err)
   637  	}
   638  
   639  	return tx
   640  }
   641  
   642  func genNewSmartContractDeploy(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   643  	amount := big.NewInt(0)
   644  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   645  	tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, map[types.TxValueKeyType]interface{}{
   646  		types.TxValueKeyNonce:         from.Nonce,
   647  		types.TxValueKeyAmount:        amount,
   648  		types.TxValueKeyGasLimit:      gasLimit,
   649  		types.TxValueKeyGasPrice:      gasPrice,
   650  		types.TxValueKeyHumanReadable: false,
   651  		types.TxValueKeyTo:            (*common.Address)(nil),
   652  		types.TxValueKeyCodeFormat:    params.CodeFormatEVM,
   653  		types.TxValueKeyFrom:          from.Addr,
   654  		// The binary below is a compiled binary of contracts/reward/contract/KlaytnReward.sol.
   655  		types.TxValueKeyData: common.Hex2Bytes("608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"),
   656  	})
   657  	if err != nil {
   658  		panic(err)
   659  	}
   660  
   661  	err = tx.SignWithKeys(signer, from.Keys)
   662  	if err != nil {
   663  		panic(err)
   664  	}
   665  
   666  	return tx
   667  }
   668  
   669  func genAccountKeyWeightedMultisig() (accountkey.AccountKey, []*ecdsa.PrivateKey) {
   670  	threshold := uint(2)
   671  	numKeys := 3
   672  	keys := make(accountkey.WeightedPublicKeys, numKeys)
   673  	prvKeys := make([]*ecdsa.PrivateKey, numKeys)
   674  
   675  	for i := 0; i < numKeys; i++ {
   676  		prvKeys[i], _ = crypto.GenerateKey()
   677  		keys[i] = accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&prvKeys[i].PublicKey))
   678  	}
   679  
   680  	return accountkey.NewAccountKeyWeightedMultiSigWithValues(threshold, keys), prvKeys
   681  }
   682  
   683  func genNewAccountUpdateMultisig3(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   684  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   685  	keys, prvKeys := genAccountKeyWeightedMultisig()
   686  	tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, map[types.TxValueKeyType]interface{}{
   687  		types.TxValueKeyNonce:         from.Nonce,
   688  		types.TxValueKeyGasLimit:      gasLimit,
   689  		types.TxValueKeyGasPrice:      gasPrice,
   690  		types.TxValueKeyFrom:          from.Addr,
   691  		types.TxValueKeyHumanReadable: false,
   692  		types.TxValueKeyAccountKey:    keys,
   693  	})
   694  	if err != nil {
   695  		panic(err)
   696  	}
   697  
   698  	err = tx.SignWithKeys(signer, from.Keys)
   699  	if err != nil {
   700  		panic(err)
   701  	}
   702  
   703  	from.Keys = prvKeys
   704  	from.AccKey = keys
   705  	return tx
   706  }
   707  
   708  func genAccountKeyRoleBasedSingle() (accountkey.AccountKey, []*ecdsa.PrivateKey) {
   709  	k1, err := crypto.HexToECDSA("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
   710  	if err != nil {
   711  		panic(err)
   712  	}
   713  	txKey := accountkey.NewAccountKeyPublicWithValue(&k1.PublicKey)
   714  
   715  	return accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{txKey, txKey, txKey}), []*ecdsa.PrivateKey{k1}
   716  }
   717  
   718  func genNewAccountUpdateRoleBasedSingle(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   719  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   720  	keys, prvKeys := genAccountKeyRoleBasedSingle()
   721  	tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, map[types.TxValueKeyType]interface{}{
   722  		types.TxValueKeyNonce:         from.Nonce,
   723  		types.TxValueKeyGasLimit:      gasLimit,
   724  		types.TxValueKeyGasPrice:      gasPrice,
   725  		types.TxValueKeyFrom:          from.Addr,
   726  		types.TxValueKeyHumanReadable: false,
   727  		types.TxValueKeyAccountKey:    keys,
   728  	})
   729  	if err != nil {
   730  		panic(err)
   731  	}
   732  
   733  	err = tx.SignWithKeys(signer, from.Keys)
   734  	if err != nil {
   735  		panic(err)
   736  	}
   737  
   738  	from.Keys = prvKeys
   739  	from.AccKey = keys
   740  	return tx
   741  }
   742  
   743  func genAccountKeyRoleBasedMultisig3() (accountkey.AccountKey, []*ecdsa.PrivateKey) {
   744  	threshold := uint(2)
   745  
   746  	k1, err := crypto.HexToECDSA("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
   747  	if err != nil {
   748  		panic(err)
   749  	}
   750  	k2, err := crypto.HexToECDSA("c64f2cd1196e2a1791365b00c4bc07ab8f047b73152e4617c6ed06ac221a4b0c")
   751  	if err != nil {
   752  		panic(err)
   753  	}
   754  	k3, err := crypto.HexToECDSA("ed580f5bd71a2ee4dae5cb43e331b7d0318596e561e6add7844271ed94156b20")
   755  	if err != nil {
   756  		panic(err)
   757  	}
   758  
   759  	keys := accountkey.WeightedPublicKeys{
   760  		accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k1.PublicKey)),
   761  		accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k2.PublicKey)),
   762  		accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k3.PublicKey)),
   763  	}
   764  	txKey := accountkey.NewAccountKeyWeightedMultiSigWithValues(threshold, keys)
   765  
   766  	return accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{txKey, txKey, txKey}), []*ecdsa.PrivateKey{k1, k2, k3}
   767  }
   768  
   769  func genNewAccountUpdateRoleBasedMultisig3(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   770  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   771  	keys, prvKeys := genAccountKeyRoleBasedMultisig3()
   772  	tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, map[types.TxValueKeyType]interface{}{
   773  		types.TxValueKeyNonce:         from.Nonce,
   774  		types.TxValueKeyGasLimit:      gasLimit,
   775  		types.TxValueKeyGasPrice:      gasPrice,
   776  		types.TxValueKeyFrom:          from.Addr,
   777  		types.TxValueKeyHumanReadable: false,
   778  		types.TxValueKeyAccountKey:    keys,
   779  	})
   780  	if err != nil {
   781  		panic(err)
   782  	}
   783  
   784  	err = tx.SignWithKeys(signer, from.Keys)
   785  	if err != nil {
   786  		panic(err)
   787  	}
   788  
   789  	from.Keys = prvKeys
   790  	from.AccKey = keys
   791  	return tx
   792  }
   793  
   794  func genNewFeeDelegatedValueTransfer(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   795  	amount := big.NewInt(100)
   796  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   797  	tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, map[types.TxValueKeyType]interface{}{
   798  		types.TxValueKeyNonce:    from.Nonce,
   799  		types.TxValueKeyTo:       to.Addr,
   800  		types.TxValueKeyAmount:   amount,
   801  		types.TxValueKeyGasLimit: gasLimit,
   802  		types.TxValueKeyGasPrice: gasPrice,
   803  		types.TxValueKeyFrom:     from.Addr,
   804  		types.TxValueKeyFeePayer: from.Addr,
   805  	})
   806  	if err != nil {
   807  		panic(err)
   808  	}
   809  
   810  	err = tx.SignWithKeys(signer, from.Keys)
   811  	if err != nil {
   812  		panic(err)
   813  	}
   814  
   815  	err = tx.SignFeePayerWithKeys(signer, from.Keys)
   816  	if err != nil {
   817  		panic(err)
   818  	}
   819  
   820  	return tx
   821  }
   822  
   823  func genNewFeeDelegatedValueTransferWithRatio(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   824  	amount := big.NewInt(100)
   825  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   826  	tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransferWithRatio, map[types.TxValueKeyType]interface{}{
   827  		types.TxValueKeyNonce:              from.Nonce,
   828  		types.TxValueKeyTo:                 to.Addr,
   829  		types.TxValueKeyAmount:             amount,
   830  		types.TxValueKeyGasLimit:           gasLimit,
   831  		types.TxValueKeyGasPrice:           gasPrice,
   832  		types.TxValueKeyFrom:               from.Addr,
   833  		types.TxValueKeyFeePayer:           from.Addr,
   834  		types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30),
   835  	})
   836  	if err != nil {
   837  		panic(err)
   838  	}
   839  
   840  	err = tx.SignWithKeys(signer, from.Keys)
   841  	if err != nil {
   842  		panic(err)
   843  	}
   844  
   845  	err = tx.SignFeePayerWithKeys(signer, from.Keys)
   846  	if err != nil {
   847  		panic(err)
   848  	}
   849  
   850  	return tx
   851  }
   852  
   853  func genLegacySmartContractExecution(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   854  	amount := big.NewInt(100)
   855  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   856  	data := common.Hex2Bytes("6353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2")
   857  	tx := types.NewTransaction(from.Nonce, to.Addr, amount, gasLimit, gasPrice, data)
   858  	err := tx.SignWithKeys(signer, from.Keys)
   859  	if err != nil {
   860  		panic(err)
   861  	}
   862  
   863  	return tx
   864  }
   865  
   866  func genNewSmartContractExecution(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   867  	amount := big.NewInt(100)
   868  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   869  	tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, map[types.TxValueKeyType]interface{}{
   870  		types.TxValueKeyNonce:    from.Nonce,
   871  		types.TxValueKeyTo:       to.Addr,
   872  		types.TxValueKeyAmount:   amount,
   873  		types.TxValueKeyGasLimit: gasLimit,
   874  		types.TxValueKeyGasPrice: gasPrice,
   875  		types.TxValueKeyFrom:     from.Addr,
   876  		// An abi-packed bytes calling "reward" of contracts/reward/contract/KlaytnReward.sol with an address "bc5951f055a85f41a3b62fd6f68ab7de76d299b2".
   877  		types.TxValueKeyData: common.Hex2Bytes("6353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2"),
   878  	})
   879  	if err != nil {
   880  		panic(err)
   881  	}
   882  
   883  	err = tx.SignWithKeys(signer, from.Keys)
   884  	if err != nil {
   885  		panic(err)
   886  	}
   887  
   888  	return tx
   889  }
   890  
   891  func genNewAccountUpdateAccountKeyPublic(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   892  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   893  	k, _ := crypto.GenerateKey()
   894  	tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, map[types.TxValueKeyType]interface{}{
   895  		types.TxValueKeyNonce:      from.Nonce,
   896  		types.TxValueKeyGasLimit:   gasLimit,
   897  		types.TxValueKeyGasPrice:   gasPrice,
   898  		types.TxValueKeyFrom:       from.Addr,
   899  		types.TxValueKeyAccountKey: accountkey.NewAccountKeyPublicWithValue(&k.PublicKey),
   900  	})
   901  	if err != nil {
   902  		panic(err)
   903  	}
   904  
   905  	err = tx.SignWithKeys(signer, from.Keys)
   906  	if err != nil {
   907  		panic(err)
   908  	}
   909  
   910  	from.Keys = []*ecdsa.PrivateKey{k}
   911  	from.AccKey = accountkey.NewAccountKeyPublicWithValue(&k.PublicKey)
   912  
   913  	return tx
   914  }
   915  
   916  func genNewCancel(signer types.Signer, from *TestAccountType, to *TestAccountType) *types.Transaction {
   917  	gasPrice := new(big.Int).SetUint64(25 * params.Ston)
   918  	tx, err := types.NewTransactionWithMap(types.TxTypeCancel, map[types.TxValueKeyType]interface{}{
   919  		types.TxValueKeyNonce:    from.Nonce,
   920  		types.TxValueKeyGasLimit: gasLimit,
   921  		types.TxValueKeyGasPrice: gasPrice,
   922  		types.TxValueKeyFrom:     from.Addr,
   923  	})
   924  	if err != nil {
   925  		panic(err)
   926  	}
   927  
   928  	err = tx.SignWithKeys(signer, from.Keys)
   929  	if err != nil {
   930  		panic(err)
   931  	}
   932  
   933  	return tx
   934  }
   935  
   936  func getFunctionName(i interface{}) string {
   937  	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
   938  }
   939  
   940  func isProfileEnabled() bool {
   941  	return os.Getenv("PROFILE") != ""
   942  }