github.com/klaytn/klaytn@v1.12.1/crypto/create_address_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 crypto
    18  
    19  import (
    20  	"encoding/binary"
    21  	"fmt"
    22  	"math/rand"
    23  	"reflect"
    24  	"runtime"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/klaytn/klaytn/common"
    29  	"github.com/klaytn/klaytn/rlp"
    30  )
    31  
    32  // BenchmarkCreateAddress measures performance of two address generation methods:
    33  // createAddressUsingCode: hash(address, nonce, code)
    34  // createAddressUsingCodeHash: hash(address, nonce, codeHash)
    35  //
    36  // This benchmark is created to measure performance difference of hashing twice with shorter data
    37  // and hashing once with long data.
    38  func BenchmarkCreateAddress(b *testing.B) {
    39  	addr := common.HexToAddress("333c3310824b7c685133f2bedb2ca4b8b4df633d")
    40  	nonce := uint64(1023)
    41  
    42  	fns := []func(addr common.Address, nonce uint64, code []byte) common.Address{
    43  		createAddressUsingCode,
    44  		createAddressUsingCodeHash,
    45  	}
    46  
    47  	const MaxCodeSize uint = 10 * 1024
    48  
    49  	for codeSize := uint(0); codeSize <= MaxCodeSize; codeSize += 640 {
    50  		code := randCode(codeSize)
    51  
    52  		for _, f := range fns {
    53  			fname := getFunctionName(f)
    54  			fname = fname[strings.LastIndex(fname, ".")+1:]
    55  
    56  			benchName := fmt.Sprintf("%s/%d", fname, codeSize)
    57  
    58  			b.Run(benchName, func(b *testing.B) {
    59  				for i := 0; i < b.N; i++ {
    60  					_ = f(addr, nonce, code)
    61  				}
    62  			})
    63  		}
    64  	}
    65  }
    66  
    67  func randCode(codeSize uint) []byte {
    68  	code := make([]byte, 0, codeSize)
    69  	rand.Seed(0)
    70  	r := rand.Uint64()
    71  	b := make([]byte, 8)
    72  	binary.LittleEndian.PutUint64(b, r)
    73  	code = append(code, b...)
    74  
    75  	return code
    76  }
    77  
    78  func createAddressUsingCodeHash(addr common.Address, nonce uint64, code []byte) common.Address {
    79  	codeHash := Keccak256Hash(code)
    80  
    81  	data, _ := rlp.EncodeToBytes(struct {
    82  		Addr     common.Address
    83  		nonce    uint64
    84  		codeHash common.Hash
    85  	}{addr, nonce, codeHash})
    86  
    87  	return common.BytesToAddress(Keccak256(data)[12:])
    88  }
    89  
    90  func createAddressUsingCode(addr common.Address, nonce uint64, code []byte) common.Address {
    91  	data, _ := rlp.EncodeToBytes(struct {
    92  		Addr     common.Address
    93  		nonce    uint64
    94  		codeHash []byte
    95  	}{addr, nonce, code})
    96  
    97  	return common.BytesToAddress(Keccak256(data)[12:])
    98  }
    99  
   100  func getFunctionName(i interface{}) string {
   101  	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
   102  }