github.com/klaytn/klaytn@v1.12.1/tests/klay_scenario_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  	"encoding/json"
    22  	"errors"
    23  	"fmt"
    24  	"math/big"
    25  	"math/rand"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/klaytn/klaytn/accounts/abi"
    31  	"github.com/klaytn/klaytn/blockchain/state"
    32  	"github.com/klaytn/klaytn/blockchain/types"
    33  	"github.com/klaytn/klaytn/blockchain/types/accountkey"
    34  	"github.com/klaytn/klaytn/blockchain/vm"
    35  	"github.com/klaytn/klaytn/common"
    36  	"github.com/klaytn/klaytn/common/compiler"
    37  	"github.com/klaytn/klaytn/common/profile"
    38  	"github.com/klaytn/klaytn/crypto"
    39  	"github.com/klaytn/klaytn/log"
    40  	"github.com/klaytn/klaytn/params"
    41  	"github.com/klaytn/klaytn/rlp"
    42  	"github.com/klaytn/klaytn/storage/database"
    43  	"github.com/stretchr/testify/assert"
    44  )
    45  
    46  var (
    47  	to       = common.HexToAddress("7b65B75d204aBed71587c9E519a89277766EE1d0")
    48  	feePayer = common.HexToAddress("5A0043070275d9f6054307Ee7348bD660849D90f")
    49  )
    50  
    51  const (
    52  	nonce    = uint64(1234)
    53  	gasLimit = uint64(100000000000)
    54  )
    55  
    56  type TestAccountType struct {
    57  	Addr   common.Address
    58  	Keys   []*ecdsa.PrivateKey
    59  	Nonce  uint64
    60  	AccKey accountkey.AccountKey
    61  }
    62  
    63  type TestCreateMultisigAccountParam struct {
    64  	Threshold uint
    65  	Weights   []uint
    66  	PrvKeys   []string
    67  }
    68  
    69  // createAnonymousAccount creates an account whose address is derived from the private key.
    70  func createAnonymousAccount(prvKeyHex string) (*TestAccountType, error) {
    71  	key, err := crypto.HexToECDSA(prvKeyHex)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	addr := crypto.PubkeyToAddress(key.PublicKey)
    77  
    78  	return &TestAccountType{
    79  		Addr:   addr,
    80  		Keys:   []*ecdsa.PrivateKey{key},
    81  		Nonce:  uint64(0),
    82  		AccKey: accountkey.NewAccountKeyLegacy(),
    83  	}, nil
    84  }
    85  
    86  // createDecoupledAccount creates an account whose address is decoupled with its private key.
    87  func createDecoupledAccount(prvKeyHex string, addr common.Address) (*TestAccountType, error) {
    88  	key, err := crypto.HexToECDSA(prvKeyHex)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	return &TestAccountType{
    94  		Addr:   addr,
    95  		Keys:   []*ecdsa.PrivateKey{key},
    96  		Nonce:  uint64(0),
    97  		AccKey: accountkey.NewAccountKeyPublicWithValue(&key.PublicKey),
    98  	}, nil
    99  }
   100  
   101  //
   102  
   103  // createMultisigAccount creates an account having multiple of keys.
   104  func createMultisigAccount(threshold uint, weights []uint, prvKeys []string, addr common.Address) (*TestAccountType, error) {
   105  	var err error
   106  
   107  	keys := make([]*ecdsa.PrivateKey, len(prvKeys))
   108  	weightedKeys := make(accountkey.WeightedPublicKeys, len(prvKeys))
   109  
   110  	for i, p := range prvKeys {
   111  		keys[i], err = crypto.HexToECDSA(p)
   112  		if err != nil {
   113  			return nil, err
   114  		}
   115  		weightedKeys[i] = accountkey.NewWeightedPublicKey(weights[i], (*accountkey.PublicKeySerializable)(&keys[i].PublicKey))
   116  	}
   117  
   118  	return &TestAccountType{
   119  		Addr:   addr,
   120  		Keys:   keys,
   121  		Nonce:  uint64(0),
   122  		AccKey: accountkey.NewAccountKeyWeightedMultiSigWithValues(threshold, weightedKeys),
   123  	}, nil
   124  }
   125  
   126  // createRoleBasedAccountWithAccountKeyPublic creates an account having keys that have role with AccountKeyPublic.
   127  func createRoleBasedAccountWithAccountKeyPublic(prvKeys []string, addr common.Address) (*TestRoleBasedAccountType, error) {
   128  	var err error
   129  
   130  	if len(prvKeys) != 3 {
   131  		return nil, errors.New("Need three key value for create role-based account")
   132  	}
   133  
   134  	keys := make([]*ecdsa.PrivateKey, len(prvKeys))
   135  
   136  	for i, p := range prvKeys {
   137  		keys[i], err = crypto.HexToECDSA(p)
   138  		if err != nil {
   139  			return nil, err
   140  		}
   141  	}
   142  
   143  	accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{
   144  		accountkey.NewAccountKeyPublicWithValue(&keys[0].PublicKey),
   145  		accountkey.NewAccountKeyPublicWithValue(&keys[1].PublicKey),
   146  		accountkey.NewAccountKeyPublicWithValue(&keys[2].PublicKey),
   147  	})
   148  
   149  	return &TestRoleBasedAccountType{
   150  		Addr:       addr,
   151  		TxKeys:     []*ecdsa.PrivateKey{keys[0]},
   152  		UpdateKeys: []*ecdsa.PrivateKey{keys[1]},
   153  		FeeKeys:    []*ecdsa.PrivateKey{keys[2]},
   154  		Nonce:      uint64(0),
   155  		AccKey:     accKey,
   156  	}, nil
   157  }
   158  
   159  // createRoleBasedAccountWithAccountKeyWeightedMultisig creates an account having keys that have role with AccountKeyWeightedMultisig.
   160  func createRoleBasedAccountWithAccountKeyWeightedMultiSig(multisigs []TestCreateMultisigAccountParam, addr common.Address) (*TestRoleBasedAccountType, error) {
   161  	var err error
   162  
   163  	if len(multisigs) != 3 {
   164  		return nil, errors.New("Need three key value for create role-based account")
   165  	}
   166  
   167  	prvKeys := make([][]*ecdsa.PrivateKey, len(multisigs))
   168  	multisigKeys := make([]*accountkey.AccountKeyWeightedMultiSig, len(multisigs))
   169  
   170  	for idx, multisig := range multisigs {
   171  		keys := make([]*ecdsa.PrivateKey, len(multisig.PrvKeys))
   172  		weightedKeys := make(accountkey.WeightedPublicKeys, len(multisig.PrvKeys))
   173  
   174  		for i, p := range multisig.PrvKeys {
   175  			keys[i], err = crypto.HexToECDSA(p)
   176  			if err != nil {
   177  				return nil, err
   178  			}
   179  			weightedKeys[i] = accountkey.NewWeightedPublicKey(multisig.Weights[i], (*accountkey.PublicKeySerializable)(&keys[i].PublicKey))
   180  		}
   181  		prvKeys[idx] = keys
   182  		multisigKeys[idx] = accountkey.NewAccountKeyWeightedMultiSigWithValues(multisig.Threshold, weightedKeys)
   183  	}
   184  
   185  	accKey := accountkey.NewAccountKeyRoleBasedWithValues(accountkey.AccountKeyRoleBased{multisigKeys[0], multisigKeys[1], multisigKeys[2]})
   186  
   187  	return &TestRoleBasedAccountType{
   188  		Addr:       addr,
   189  		TxKeys:     prvKeys[0],
   190  		UpdateKeys: prvKeys[1],
   191  		FeeKeys:    prvKeys[2],
   192  		Nonce:      uint64(0),
   193  		AccKey:     accKey,
   194  	}, nil
   195  }
   196  
   197  // TestFeeDelegatedWithSmallBalance tests the case that an account having a small amount of tokens transfers
   198  // all the tokens to another account with a fee payer.
   199  // This kinds of transactions were discarded in TxPool.promoteExecutable() because the total cost of
   200  // the transaction is larger than the amount of tokens the sender has.
   201  // Since we provide fee-delegated transactions, it is not true in the above case.
   202  // This test code should succeed.
   203  func TestFeeDelegatedWithSmallBalance(t *testing.T) {
   204  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   205  	prof := profile.NewProfiler()
   206  
   207  	// Initialize blockchain
   208  	start := time.Now()
   209  	bcdata, err := NewBCData(6, 4)
   210  	if err != nil {
   211  		t.Fatal(err)
   212  	}
   213  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   214  	defer bcdata.Shutdown()
   215  
   216  	// Initialize address-balance map for verification
   217  	start = time.Now()
   218  	accountMap := NewAccountMap()
   219  	if err := accountMap.Initialize(bcdata); err != nil {
   220  		t.Fatal(err)
   221  	}
   222  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   223  
   224  	// reservoir account
   225  	reservoir := &TestAccountType{
   226  		Addr:  *bcdata.addrs[0],
   227  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   228  		Nonce: uint64(0),
   229  	}
   230  
   231  	// anonymous account
   232  	anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
   233  	assert.Equal(t, nil, err)
   234  
   235  	if testing.Verbose() {
   236  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   237  		fmt.Println("anonAddr = ", anon.Addr.String())
   238  	}
   239  
   240  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   241  	gasPrice := big.NewInt(25 * params.Ston)
   242  
   243  	// 1. Transfer (reservoir -> anon) using a legacy transaction.
   244  	{
   245  		var txs types.Transactions
   246  
   247  		amount := new(big.Int).SetUint64(10000)
   248  		tx := types.NewTransaction(reservoir.Nonce,
   249  			anon.Addr, amount, gasLimit, gasPrice, []byte{})
   250  
   251  		err := tx.SignWithKeys(signer, reservoir.Keys)
   252  		assert.Equal(t, nil, err)
   253  		txs = append(txs, tx)
   254  
   255  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   256  			t.Fatal(err)
   257  		}
   258  		reservoir.Nonce += 1
   259  	}
   260  
   261  	// 2. Transfer (anon -> reservoir) using a TxTypeFeeDelegatedValueTransfer
   262  	{
   263  		amount := new(big.Int).SetUint64(10000)
   264  		values := map[types.TxValueKeyType]interface{}{
   265  			types.TxValueKeyNonce:    anon.Nonce,
   266  			types.TxValueKeyFrom:     anon.Addr,
   267  			types.TxValueKeyFeePayer: reservoir.Addr,
   268  			types.TxValueKeyTo:       reservoir.Addr,
   269  			types.TxValueKeyAmount:   amount,
   270  			types.TxValueKeyGasLimit: gasLimit,
   271  			types.TxValueKeyGasPrice: gasPrice,
   272  		}
   273  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, values)
   274  		assert.Equal(t, nil, err)
   275  
   276  		err = tx.SignWithKeys(signer, anon.Keys)
   277  		assert.Equal(t, nil, err)
   278  
   279  		err = tx.SignFeePayerWithKeys(signer, reservoir.Keys)
   280  		assert.Equal(t, nil, err)
   281  
   282  		p := makeTxPool(bcdata, 10)
   283  
   284  		p.AddRemote(tx)
   285  
   286  		if err := bcdata.GenABlockWithTxpool(accountMap, p, prof); err != nil {
   287  			t.Fatal(err)
   288  		}
   289  		anon.Nonce += 1
   290  	}
   291  
   292  	state, err := bcdata.bc.State()
   293  	assert.Equal(t, nil, err)
   294  	assert.Equal(t, uint64(0), state.GetBalance(anon.Addr).Uint64())
   295  }
   296  
   297  // TestSmartContractDeployAddress checks that the smart contract is deployed to the given address or not by
   298  // checking receipt.ContractAddress.
   299  func TestSmartContractDeployAddress(t *testing.T) {
   300  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   301  	prof := profile.NewProfiler()
   302  
   303  	// Initialize blockchain
   304  	start := time.Now()
   305  	bcdata, err := NewBCData(6, 4)
   306  	if err != nil {
   307  		t.Fatal(err)
   308  	}
   309  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   310  	defer bcdata.Shutdown()
   311  
   312  	// Initialize address-balance map for verification
   313  	start = time.Now()
   314  	accountMap := NewAccountMap()
   315  	if err := accountMap.Initialize(bcdata); err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   319  
   320  	// reservoir account
   321  	reservoir := &TestAccountType{
   322  		Addr:  *bcdata.addrs[0],
   323  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   324  		Nonce: uint64(0),
   325  	}
   326  
   327  	if testing.Verbose() {
   328  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   329  	}
   330  
   331  	contractAddr := common.Address{}
   332  
   333  	gasPrice := new(big.Int).SetUint64(0)
   334  	gasLimit := uint64(100000000000)
   335  
   336  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   337  
   338  	var code string
   339  
   340  	if isCompilerAvailable() {
   341  		filename := string("../contracts/reward/contract/KlaytnReward.sol")
   342  		codes, _ := compileSolidity(filename)
   343  		code = codes[0]
   344  	} else {
   345  		// Falling back to use compiled code.
   346  		code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"
   347  	}
   348  
   349  	// 1. Deploy smart contract (reservoir -> contract)
   350  	{
   351  		amount := new(big.Int).SetUint64(0)
   352  
   353  		values := map[types.TxValueKeyType]interface{}{
   354  			types.TxValueKeyNonce:         reservoir.Nonce,
   355  			types.TxValueKeyFrom:          reservoir.Addr,
   356  			types.TxValueKeyTo:            (*common.Address)(nil),
   357  			types.TxValueKeyAmount:        amount,
   358  			types.TxValueKeyGasLimit:      gasLimit,
   359  			types.TxValueKeyGasPrice:      gasPrice,
   360  			types.TxValueKeyHumanReadable: false,
   361  			types.TxValueKeyData:          common.FromHex(code),
   362  			types.TxValueKeyCodeFormat:    params.CodeFormatEVM,
   363  		}
   364  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values)
   365  		assert.Equal(t, nil, err)
   366  
   367  		err = tx.SignWithKeys(signer, reservoir.Keys)
   368  		assert.Equal(t, nil, err)
   369  
   370  		contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   371  
   372  		// check receipt
   373  		receipt, err := applyTransaction(t, bcdata, tx)
   374  		assert.Equal(t, nil, err)
   375  		assert.Equal(t, contractAddr, receipt.ContractAddress)
   376  	}
   377  }
   378  
   379  // TestSmartContractScenario tests the following scenario:
   380  // 1. Deploy smart contract (reservoir -> contract)
   381  // 2. Check the smart contract is deployed well.
   382  // 3. Execute "reward" function with amountToSend
   383  // 4. Validate "reward" function is executed correctly by executing "balanceOf".
   384  func TestSmartContractScenario(t *testing.T) {
   385  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   386  	prof := profile.NewProfiler()
   387  
   388  	// Initialize blockchain
   389  	start := time.Now()
   390  	bcdata, err := NewBCData(6, 4)
   391  	if err != nil {
   392  		t.Fatal(err)
   393  	}
   394  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   395  	defer bcdata.Shutdown()
   396  
   397  	// Initialize address-balance map for verification
   398  	start = time.Now()
   399  	accountMap := NewAccountMap()
   400  	if err := accountMap.Initialize(bcdata); err != nil {
   401  		t.Fatal(err)
   402  	}
   403  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   404  
   405  	// reservoir account
   406  	reservoir := &TestAccountType{
   407  		Addr:  *bcdata.addrs[0],
   408  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   409  		Nonce: uint64(0),
   410  	}
   411  
   412  	if testing.Verbose() {
   413  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   414  	}
   415  
   416  	contractAddr := common.Address{}
   417  
   418  	gasPrice := new(big.Int).SetUint64(0)
   419  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   420  
   421  	var abiStr string
   422  	var code string
   423  
   424  	if isCompilerAvailable() {
   425  		filename := string("../contracts/reward/contract/KlaytnReward.sol")
   426  		codes, abistrings := compileSolidity(filename)
   427  		code = codes[0]
   428  		abiStr = abistrings[0]
   429  	} else {
   430  		// Falling back to use compiled code.
   431  		code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"
   432  		abiStr = `[{"constant":true,"inputs":[],"name":"totalAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"}],"name":"reward","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]`
   433  	}
   434  
   435  	// 1. Deploy smart contract (reservoir -> contract)
   436  	{
   437  		var txs types.Transactions
   438  
   439  		amount := new(big.Int).SetUint64(0)
   440  
   441  		values := map[types.TxValueKeyType]interface{}{
   442  			types.TxValueKeyNonce:         reservoir.Nonce,
   443  			types.TxValueKeyFrom:          reservoir.Addr,
   444  			types.TxValueKeyTo:            (*common.Address)(nil),
   445  			types.TxValueKeyAmount:        amount,
   446  			types.TxValueKeyGasLimit:      gasLimit,
   447  			types.TxValueKeyGasPrice:      gasPrice,
   448  			types.TxValueKeyHumanReadable: false,
   449  			types.TxValueKeyData:          common.FromHex(code),
   450  			types.TxValueKeyCodeFormat:    params.CodeFormatEVM,
   451  		}
   452  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values)
   453  		assert.Equal(t, nil, err)
   454  
   455  		err = tx.SignWithKeys(signer, reservoir.Keys)
   456  		assert.Equal(t, nil, err)
   457  
   458  		txs = append(txs, tx)
   459  
   460  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   461  			t.Fatal(err)
   462  		}
   463  
   464  		contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   465  
   466  		reservoir.Nonce += 1
   467  	}
   468  
   469  	// 2. Check the smart contract is deployed well.
   470  	{
   471  		statedb, err := bcdata.bc.State()
   472  		if err != nil {
   473  			t.Fatal(err)
   474  		}
   475  		code := statedb.GetCode(contractAddr)
   476  		assert.Equal(t, 478, len(code))
   477  	}
   478  
   479  	// 3. Execute "reward" function with amountToSend
   480  	amountToSend := new(big.Int).SetUint64(10)
   481  	{
   482  		var txs types.Transactions
   483  
   484  		abii, err := abi.JSON(strings.NewReader(string(abiStr)))
   485  		assert.Equal(t, nil, err)
   486  
   487  		data, err := abii.Pack("reward", reservoir.Addr)
   488  		assert.Equal(t, nil, err)
   489  
   490  		values := map[types.TxValueKeyType]interface{}{
   491  			types.TxValueKeyNonce:    reservoir.Nonce,
   492  			types.TxValueKeyFrom:     reservoir.Addr,
   493  			types.TxValueKeyTo:       contractAddr,
   494  			types.TxValueKeyAmount:   amountToSend,
   495  			types.TxValueKeyGasLimit: gasLimit,
   496  			types.TxValueKeyGasPrice: gasPrice,
   497  			types.TxValueKeyData:     data,
   498  		}
   499  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values)
   500  		assert.Equal(t, nil, err)
   501  
   502  		err = tx.SignWithKeys(signer, reservoir.Keys)
   503  		assert.Equal(t, nil, err)
   504  
   505  		txs = append(txs, tx)
   506  
   507  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   508  			t.Fatal(err)
   509  		}
   510  		reservoir.Nonce += 1
   511  	}
   512  
   513  	// 4. Validate "reward" function is executed correctly by executing "balanceOf".
   514  	{
   515  		amount := new(big.Int).SetUint64(0)
   516  
   517  		abii, err := abi.JSON(strings.NewReader(string(abiStr)))
   518  		assert.Equal(t, nil, err)
   519  
   520  		data, err := abii.Pack("balanceOf", reservoir.Addr)
   521  		assert.Equal(t, nil, err)
   522  
   523  		values := map[types.TxValueKeyType]interface{}{
   524  			types.TxValueKeyNonce:    reservoir.Nonce,
   525  			types.TxValueKeyFrom:     reservoir.Addr,
   526  			types.TxValueKeyTo:       contractAddr,
   527  			types.TxValueKeyAmount:   amount,
   528  			types.TxValueKeyGasLimit: gasLimit,
   529  			types.TxValueKeyGasPrice: gasPrice,
   530  			types.TxValueKeyData:     data,
   531  		}
   532  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values)
   533  		assert.Equal(t, nil, err)
   534  
   535  		err = tx.SignWithKeys(signer, reservoir.Keys)
   536  		assert.Equal(t, nil, err)
   537  
   538  		ret, err := callContract(bcdata, tx)
   539  		assert.Equal(t, nil, err)
   540  
   541  		balance := new(big.Int)
   542  		abii.UnpackIntoInterface(&balance, "balanceOf", ret)
   543  
   544  		assert.Equal(t, amountToSend, balance)
   545  		reservoir.Nonce += 1
   546  	}
   547  
   548  	if testing.Verbose() {
   549  		prof.PrintProfileInfo()
   550  	}
   551  }
   552  
   553  // TestSmartContractSign tests value transfer and fee delegation of smart contract accounts.
   554  // It performs the following scenario:
   555  // 1. Deploy smart contract (reservoir -> contract)
   556  // 2. Check the smart contract is deployed well.
   557  // 3. Try value transfer. It should be failed.
   558  // 4. Try fee delegation. It should be failed.
   559  func TestSmartContractSign(t *testing.T) {
   560  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   561  	prof := profile.NewProfiler()
   562  
   563  	// Initialize blockchain
   564  	start := time.Now()
   565  	bcdata, err := NewBCData(6, 4)
   566  	if err != nil {
   567  		t.Fatal(err)
   568  	}
   569  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   570  	defer bcdata.Shutdown()
   571  
   572  	// Initialize address-balance map for verification
   573  	start = time.Now()
   574  	accountMap := NewAccountMap()
   575  	if err := accountMap.Initialize(bcdata); err != nil {
   576  		t.Fatal(err)
   577  	}
   578  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   579  
   580  	// reservoir account
   581  	reservoir := &TestAccountType{
   582  		Addr:  *bcdata.addrs[0],
   583  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   584  		Nonce: uint64(0),
   585  	}
   586  
   587  	reservoir2 := &TestAccountType{
   588  		Addr:  *bcdata.addrs[1],
   589  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[1]},
   590  		Nonce: uint64(0),
   591  	}
   592  
   593  	if testing.Verbose() {
   594  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   595  	}
   596  
   597  	contract, err := createAnonymousAccount("ed34b0cf47a0021e9897760f0a904a69260c2f638e0bcc805facb745ec3ff9ab")
   598  	assert.Equal(t, nil, err)
   599  
   600  	gasPrice := new(big.Int).SetUint64(0)
   601  	gasLimit := uint64(100000000000)
   602  
   603  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   604  
   605  	var code string
   606  
   607  	if isCompilerAvailable() {
   608  		filename := string("../contracts/reward/contract/KlaytnReward.sol")
   609  		codes, _ := compileSolidity(filename)
   610  		code = codes[0]
   611  	} else {
   612  		// Falling back to use compiled code.
   613  		code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"
   614  	}
   615  
   616  	// 1. Deploy smart contract (reservoir -> contract)
   617  	{
   618  		var txs types.Transactions
   619  
   620  		amount := new(big.Int).SetUint64(0)
   621  
   622  		values := map[types.TxValueKeyType]interface{}{
   623  			types.TxValueKeyNonce:         reservoir.Nonce,
   624  			types.TxValueKeyFrom:          reservoir.Addr,
   625  			types.TxValueKeyTo:            (*common.Address)(nil),
   626  			types.TxValueKeyAmount:        amount,
   627  			types.TxValueKeyGasLimit:      gasLimit,
   628  			types.TxValueKeyGasPrice:      gasPrice,
   629  			types.TxValueKeyHumanReadable: false,
   630  			types.TxValueKeyData:          common.FromHex(code),
   631  			types.TxValueKeyCodeFormat:    params.CodeFormatEVM,
   632  		}
   633  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values)
   634  		assert.Equal(t, nil, err)
   635  
   636  		err = tx.SignWithKeys(signer, reservoir.Keys)
   637  		assert.Equal(t, nil, err)
   638  
   639  		txs = append(txs, tx)
   640  
   641  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   642  			t.Fatal(err)
   643  		}
   644  
   645  		contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   646  
   647  		reservoir.Nonce += 1
   648  	}
   649  
   650  	// 2. Check the smart contract is deployed well.
   651  	{
   652  		statedb, err := bcdata.bc.State()
   653  		if err != nil {
   654  			t.Fatal(err)
   655  		}
   656  		code := statedb.GetCode(contract.Addr)
   657  		assert.Equal(t, 478, len(code))
   658  	}
   659  
   660  	// 3. Try value transfer. It should be failed.
   661  	{
   662  		amount := new(big.Int).SetUint64(100000000000)
   663  		values := map[types.TxValueKeyType]interface{}{
   664  			types.TxValueKeyNonce:    contract.Nonce,
   665  			types.TxValueKeyFrom:     contract.Addr,
   666  			types.TxValueKeyTo:       reservoir.Addr,
   667  			types.TxValueKeyAmount:   amount,
   668  			types.TxValueKeyGasLimit: gasLimit,
   669  			types.TxValueKeyGasPrice: gasPrice,
   670  		}
   671  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
   672  		assert.Equal(t, nil, err)
   673  		err = tx.SignWithKeys(signer, contract.Keys)
   674  		assert.Equal(t, nil, err)
   675  
   676  		receipt, err := applyTransaction(t, bcdata, tx)
   677  		assert.Equal(t, (*types.Receipt)(nil), receipt)
   678  		assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err)
   679  	}
   680  
   681  	// 4. Try fee delegation. It should be failed.
   682  	{
   683  		amount := new(big.Int).SetUint64(1000)
   684  		values := map[types.TxValueKeyType]interface{}{
   685  			types.TxValueKeyNonce:    reservoir.Nonce,
   686  			types.TxValueKeyFrom:     reservoir.Addr,
   687  			types.TxValueKeyTo:       reservoir2.Addr,
   688  			types.TxValueKeyAmount:   amount,
   689  			types.TxValueKeyGasLimit: gasLimit,
   690  			types.TxValueKeyGasPrice: gasPrice,
   691  			types.TxValueKeyFeePayer: contract.Addr,
   692  		}
   693  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, values)
   694  		assert.Equal(t, nil, err)
   695  
   696  		err = tx.SignWithKeys(signer, reservoir.Keys)
   697  		assert.Equal(t, nil, err)
   698  
   699  		err = tx.SignFeePayerWithKeys(signer, contract.Keys)
   700  		assert.Equal(t, nil, err)
   701  
   702  		receipt, err := applyTransaction(t, bcdata, tx)
   703  		assert.Equal(t, (*types.Receipt)(nil), receipt)
   704  		assert.Equal(t, types.ErrFeePayer(types.ErrInvalidAccountKey), err)
   705  	}
   706  }
   707  
   708  // TestFeeDelegatedSmartContractScenario tests the following scenario:
   709  // 1. Deploy smart contract (reservoir -> contract) with fee-delegation.
   710  // 2. Check the smart contract is deployed well.
   711  // 3. Execute "reward" function with amountToSend with fee-delegation.
   712  // 4. Validate "reward" function is executed correctly by executing "balanceOf".
   713  func TestFeeDelegatedSmartContractScenario(t *testing.T) {
   714  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   715  	prof := profile.NewProfiler()
   716  
   717  	// Initialize blockchain
   718  	start := time.Now()
   719  	bcdata, err := NewBCData(6, 4)
   720  	if err != nil {
   721  		t.Fatal(err)
   722  	}
   723  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   724  	defer bcdata.Shutdown()
   725  
   726  	// Initialize address-balance map for verification
   727  	start = time.Now()
   728  	accountMap := NewAccountMap()
   729  	if err := accountMap.Initialize(bcdata); err != nil {
   730  		t.Fatal(err)
   731  	}
   732  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   733  
   734  	// reservoir account
   735  	reservoir := &TestAccountType{
   736  		Addr:  *bcdata.addrs[0],
   737  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   738  		Nonce: uint64(0),
   739  	}
   740  
   741  	reservoir2 := &TestAccountType{
   742  		Addr:  *bcdata.addrs[1],
   743  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[1]},
   744  		Nonce: uint64(0),
   745  	}
   746  
   747  	if testing.Verbose() {
   748  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   749  	}
   750  
   751  	contractAddr := common.Address{}
   752  
   753  	gasPrice := new(big.Int).SetUint64(0)
   754  	gasLimit := uint64(100000000000)
   755  
   756  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   757  
   758  	var abiStr string
   759  	var code string
   760  
   761  	if isCompilerAvailable() {
   762  		filename := string("../contracts/reward/contract/KlaytnReward.sol")
   763  		codes, abistrings := compileSolidity(filename)
   764  		code = codes[0]
   765  		abiStr = abistrings[0]
   766  	} else {
   767  		// Falling back to use compiled code.
   768  		code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"
   769  		abiStr = `[{"constant":true,"inputs":[],"name":"totalAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"}],"name":"reward","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]`
   770  	}
   771  
   772  	// 1. Deploy smart contract (reservoir -> contract) with fee-delegation.
   773  	{
   774  		var txs types.Transactions
   775  
   776  		amount := new(big.Int).SetUint64(0)
   777  
   778  		values := map[types.TxValueKeyType]interface{}{
   779  			types.TxValueKeyNonce:         reservoir.Nonce,
   780  			types.TxValueKeyFrom:          reservoir.Addr,
   781  			types.TxValueKeyTo:            (*common.Address)(nil),
   782  			types.TxValueKeyAmount:        amount,
   783  			types.TxValueKeyGasLimit:      gasLimit,
   784  			types.TxValueKeyGasPrice:      gasPrice,
   785  			types.TxValueKeyHumanReadable: false,
   786  			types.TxValueKeyData:          common.FromHex(code),
   787  			types.TxValueKeyFeePayer:      reservoir2.Addr,
   788  			types.TxValueKeyCodeFormat:    params.CodeFormatEVM,
   789  		}
   790  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeploy, values)
   791  		assert.Equal(t, nil, err)
   792  
   793  		err = tx.SignWithKeys(signer, reservoir.Keys)
   794  		assert.Equal(t, nil, err)
   795  
   796  		err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys)
   797  		assert.Equal(t, nil, err)
   798  
   799  		txs = append(txs, tx)
   800  
   801  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   802  			t.Fatal(err)
   803  		}
   804  
   805  		contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   806  
   807  		reservoir.Nonce += 1
   808  	}
   809  
   810  	// 2. Check the smart contract is deployed well.
   811  	{
   812  		statedb, err := bcdata.bc.State()
   813  		if err != nil {
   814  			t.Fatal(err)
   815  		}
   816  		code := statedb.GetCode(contractAddr)
   817  		assert.Equal(t, 478, len(code))
   818  	}
   819  
   820  	// 3. Execute "reward" function with amountToSend with fee-delegation.
   821  	amountToSend := new(big.Int).SetUint64(10)
   822  	{
   823  		var txs types.Transactions
   824  
   825  		abii, err := abi.JSON(strings.NewReader(string(abiStr)))
   826  		assert.Equal(t, nil, err)
   827  
   828  		data, err := abii.Pack("reward", reservoir.Addr)
   829  		assert.Equal(t, nil, err)
   830  
   831  		values := map[types.TxValueKeyType]interface{}{
   832  			types.TxValueKeyNonce:    reservoir.Nonce,
   833  			types.TxValueKeyFrom:     reservoir.Addr,
   834  			types.TxValueKeyTo:       contractAddr,
   835  			types.TxValueKeyAmount:   amountToSend,
   836  			types.TxValueKeyGasLimit: gasLimit,
   837  			types.TxValueKeyGasPrice: gasPrice,
   838  			types.TxValueKeyData:     data,
   839  			types.TxValueKeyFeePayer: reservoir2.Addr,
   840  		}
   841  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractExecution, values)
   842  		assert.Equal(t, nil, err)
   843  
   844  		err = tx.SignWithKeys(signer, reservoir.Keys)
   845  		assert.Equal(t, nil, err)
   846  
   847  		err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys)
   848  		assert.Equal(t, nil, err)
   849  
   850  		txs = append(txs, tx)
   851  
   852  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   853  			t.Fatal(err)
   854  		}
   855  		reservoir.Nonce += 1
   856  	}
   857  
   858  	// 4. Validate "reward" function is executed correctly by executing "balanceOf".
   859  	{
   860  		amount := new(big.Int).SetUint64(0)
   861  
   862  		abii, err := abi.JSON(strings.NewReader(string(abiStr)))
   863  		assert.Equal(t, nil, err)
   864  
   865  		data, err := abii.Pack("balanceOf", reservoir.Addr)
   866  		assert.Equal(t, nil, err)
   867  
   868  		values := map[types.TxValueKeyType]interface{}{
   869  			types.TxValueKeyNonce:    reservoir.Nonce,
   870  			types.TxValueKeyFrom:     reservoir.Addr,
   871  			types.TxValueKeyTo:       contractAddr,
   872  			types.TxValueKeyAmount:   amount,
   873  			types.TxValueKeyGasLimit: gasLimit,
   874  			types.TxValueKeyGasPrice: gasPrice,
   875  			types.TxValueKeyData:     data,
   876  		}
   877  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values)
   878  		assert.Equal(t, nil, err)
   879  
   880  		err = tx.SignWithKeys(signer, reservoir.Keys)
   881  		assert.Equal(t, nil, err)
   882  
   883  		ret, err := callContract(bcdata, tx)
   884  		assert.Equal(t, nil, err)
   885  
   886  		balance := new(big.Int)
   887  		abii.UnpackIntoInterface(&balance, "balanceOf", ret)
   888  
   889  		assert.Equal(t, amountToSend, balance)
   890  		reservoir.Nonce += 1
   891  	}
   892  
   893  	if testing.Verbose() {
   894  		prof.PrintProfileInfo()
   895  	}
   896  }
   897  
   898  // TestFeeDelegatedSmartContractScenarioWithRatio tests the following scenario:
   899  // 1. Deploy smart contract (reservoir -> contract) with fee-delegation.
   900  // 2. Check the smart contract is deployed well.
   901  // 3. Execute "reward" function with amountToSend with fee-delegation.
   902  // 4. Validate "reward" function is executed correctly by executing "balanceOf".
   903  func TestFeeDelegatedSmartContractScenarioWithRatio(t *testing.T) {
   904  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   905  	prof := profile.NewProfiler()
   906  
   907  	// Initialize blockchain
   908  	start := time.Now()
   909  	bcdata, err := NewBCData(6, 4)
   910  	if err != nil {
   911  		t.Fatal(err)
   912  	}
   913  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   914  	defer bcdata.Shutdown()
   915  
   916  	// Initialize address-balance map for verification
   917  	start = time.Now()
   918  	accountMap := NewAccountMap()
   919  	if err := accountMap.Initialize(bcdata); err != nil {
   920  		t.Fatal(err)
   921  	}
   922  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   923  
   924  	// reservoir account
   925  	reservoir := &TestAccountType{
   926  		Addr:  *bcdata.addrs[0],
   927  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
   928  		Nonce: uint64(0),
   929  	}
   930  
   931  	reservoir2 := &TestAccountType{
   932  		Addr:  *bcdata.addrs[1],
   933  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[1]},
   934  		Nonce: uint64(0),
   935  	}
   936  
   937  	if testing.Verbose() {
   938  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
   939  	}
   940  
   941  	contractAddr := common.Address{}
   942  
   943  	gasPrice := new(big.Int).SetUint64(0)
   944  	gasLimit := uint64(100000000000)
   945  
   946  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
   947  
   948  	var abiStr string
   949  	var code string
   950  
   951  	if isCompilerAvailable() {
   952  		filename := string("../contracts/reward/contract/KlaytnReward.sol")
   953  		codes, abistrings := compileSolidity(filename)
   954  		code = codes[0]
   955  		abiStr = abistrings[0]
   956  	} else {
   957  		// Falling back to use compiled code.
   958  		code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"
   959  		abiStr = `[{"constant":true,"inputs":[],"name":"totalAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"}],"name":"reward","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"safeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]`
   960  	}
   961  
   962  	// 1. Deploy smart contract (reservoir -> contract) with fee-delegation.
   963  	{
   964  		var txs types.Transactions
   965  
   966  		amount := new(big.Int).SetUint64(0)
   967  
   968  		values := map[types.TxValueKeyType]interface{}{
   969  			types.TxValueKeyNonce:              reservoir.Nonce,
   970  			types.TxValueKeyFrom:               reservoir.Addr,
   971  			types.TxValueKeyTo:                 (*common.Address)(nil),
   972  			types.TxValueKeyAmount:             amount,
   973  			types.TxValueKeyGasLimit:           gasLimit,
   974  			types.TxValueKeyGasPrice:           gasPrice,
   975  			types.TxValueKeyHumanReadable:      false,
   976  			types.TxValueKeyData:               common.FromHex(code),
   977  			types.TxValueKeyFeePayer:           reservoir2.Addr,
   978  			types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30),
   979  			types.TxValueKeyCodeFormat:         params.CodeFormatEVM,
   980  		}
   981  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractDeployWithRatio, values)
   982  		assert.Equal(t, nil, err)
   983  
   984  		err = tx.SignWithKeys(signer, reservoir.Keys)
   985  		assert.Equal(t, nil, err)
   986  
   987  		err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys)
   988  		assert.Equal(t, nil, err)
   989  
   990  		txs = append(txs, tx)
   991  
   992  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   993  			t.Fatal(err)
   994  		}
   995  
   996  		contractAddr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   997  
   998  		reservoir.Nonce += 1
   999  	}
  1000  
  1001  	// 2. Check the smart contract is deployed well.
  1002  	{
  1003  		statedb, err := bcdata.bc.State()
  1004  		if err != nil {
  1005  			t.Fatal(err)
  1006  		}
  1007  		code := statedb.GetCode(contractAddr)
  1008  		assert.Equal(t, 478, len(code))
  1009  	}
  1010  
  1011  	// 3. Execute "reward" function with amountToSend with fee-delegation.
  1012  	amountToSend := new(big.Int).SetUint64(10)
  1013  	{
  1014  		var txs types.Transactions
  1015  
  1016  		abii, err := abi.JSON(strings.NewReader(string(abiStr)))
  1017  		assert.Equal(t, nil, err)
  1018  
  1019  		data, err := abii.Pack("reward", reservoir.Addr)
  1020  		assert.Equal(t, nil, err)
  1021  
  1022  		values := map[types.TxValueKeyType]interface{}{
  1023  			types.TxValueKeyNonce:              reservoir.Nonce,
  1024  			types.TxValueKeyFrom:               reservoir.Addr,
  1025  			types.TxValueKeyTo:                 contractAddr,
  1026  			types.TxValueKeyAmount:             amountToSend,
  1027  			types.TxValueKeyGasLimit:           gasLimit,
  1028  			types.TxValueKeyGasPrice:           gasPrice,
  1029  			types.TxValueKeyData:               data,
  1030  			types.TxValueKeyFeePayer:           reservoir2.Addr,
  1031  			types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30),
  1032  		}
  1033  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedSmartContractExecutionWithRatio, values)
  1034  		assert.Equal(t, nil, err)
  1035  
  1036  		err = tx.SignWithKeys(signer, reservoir.Keys)
  1037  		assert.Equal(t, nil, err)
  1038  
  1039  		err = tx.SignFeePayerWithKeys(signer, reservoir2.Keys)
  1040  		assert.Equal(t, nil, err)
  1041  
  1042  		txs = append(txs, tx)
  1043  
  1044  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1045  			t.Fatal(err)
  1046  		}
  1047  		reservoir.Nonce += 1
  1048  	}
  1049  
  1050  	// 4. Validate "reward" function is executed correctly by executing "balanceOf".
  1051  	{
  1052  		amount := new(big.Int).SetUint64(0)
  1053  
  1054  		abii, err := abi.JSON(strings.NewReader(string(abiStr)))
  1055  		assert.Equal(t, nil, err)
  1056  
  1057  		data, err := abii.Pack("balanceOf", reservoir.Addr)
  1058  		assert.Equal(t, nil, err)
  1059  
  1060  		values := map[types.TxValueKeyType]interface{}{
  1061  			types.TxValueKeyNonce:    reservoir.Nonce,
  1062  			types.TxValueKeyFrom:     reservoir.Addr,
  1063  			types.TxValueKeyTo:       contractAddr,
  1064  			types.TxValueKeyAmount:   amount,
  1065  			types.TxValueKeyGasLimit: gasLimit,
  1066  			types.TxValueKeyGasPrice: gasPrice,
  1067  			types.TxValueKeyData:     data,
  1068  		}
  1069  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values)
  1070  		assert.Equal(t, nil, err)
  1071  
  1072  		err = tx.SignWithKeys(signer, reservoir.Keys)
  1073  		assert.Equal(t, nil, err)
  1074  
  1075  		ret, err := callContract(bcdata, tx)
  1076  		assert.Equal(t, nil, err)
  1077  
  1078  		balance := new(big.Int)
  1079  		abii.UnpackIntoInterface(&balance, "balanceOf", ret)
  1080  
  1081  		assert.Equal(t, amountToSend, balance)
  1082  		reservoir.Nonce += 1
  1083  	}
  1084  
  1085  	if testing.Verbose() {
  1086  		prof.PrintProfileInfo()
  1087  	}
  1088  }
  1089  
  1090  // TestAccountUpdate tests a following scenario:
  1091  // 1. Transfer (reservoir -> anon) using a legacy transaction.
  1092  // 2. Key update of decoupled using AccountUpdate
  1093  // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1094  // 4. Key update of anon using AccountUpdate with multisig keys.
  1095  // 5. Transfer (anon-> reservoir) using TxTypeValueTransfer.
  1096  func TestAccountUpdate(t *testing.T) {
  1097  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
  1098  	prof := profile.NewProfiler()
  1099  
  1100  	// Initialize blockchain
  1101  	start := time.Now()
  1102  	bcdata, err := NewBCData(6, 4)
  1103  	if err != nil {
  1104  		t.Fatal(err)
  1105  	}
  1106  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
  1107  	defer bcdata.Shutdown()
  1108  
  1109  	// Initialize address-balance map for verification
  1110  	start = time.Now()
  1111  	accountMap := NewAccountMap()
  1112  	if err := accountMap.Initialize(bcdata); err != nil {
  1113  		t.Fatal(err)
  1114  	}
  1115  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
  1116  
  1117  	// reservoir account
  1118  	reservoir := &TestAccountType{
  1119  		Addr:  *bcdata.addrs[0],
  1120  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
  1121  		Nonce: uint64(0),
  1122  	}
  1123  
  1124  	// anonymous account
  1125  	anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
  1126  	assert.Equal(t, nil, err)
  1127  
  1128  	if testing.Verbose() {
  1129  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
  1130  		fmt.Println("anonAddr = ", anon.Addr.String())
  1131  	}
  1132  
  1133  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
  1134  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
  1135  	gasLimit := uint64(100000)
  1136  
  1137  	// 1. Transfer (reservoir -> anon) using a legacy transaction.
  1138  	{
  1139  		var txs types.Transactions
  1140  
  1141  		amount := new(big.Int).SetUint64(params.KLAY)
  1142  		tx := types.NewTransaction(reservoir.Nonce,
  1143  			anon.Addr, amount, gasLimit, gasPrice, []byte{})
  1144  
  1145  		err := tx.SignWithKeys(signer, reservoir.Keys)
  1146  		assert.Equal(t, nil, err)
  1147  		txs = append(txs, tx)
  1148  
  1149  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1150  			t.Fatal(err)
  1151  		}
  1152  		reservoir.Nonce += 1
  1153  	}
  1154  
  1155  	// 2. Key update of anon using AccountUpdate
  1156  	{
  1157  		var txs types.Transactions
  1158  
  1159  		newKey, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867")
  1160  		if err != nil {
  1161  			t.Fatal(err)
  1162  		}
  1163  
  1164  		values := map[types.TxValueKeyType]interface{}{
  1165  			types.TxValueKeyNonce:      anon.Nonce,
  1166  			types.TxValueKeyFrom:       anon.Addr,
  1167  			types.TxValueKeyGasLimit:   gasLimit,
  1168  			types.TxValueKeyGasPrice:   gasPrice,
  1169  			types.TxValueKeyAccountKey: accountkey.NewAccountKeyPublicWithValue(&newKey.PublicKey),
  1170  		}
  1171  		tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values)
  1172  		assert.Equal(t, nil, err)
  1173  
  1174  		err = tx.SignWithKeys(signer, anon.Keys)
  1175  		assert.Equal(t, nil, err)
  1176  
  1177  		txs = append(txs, tx)
  1178  
  1179  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1180  			t.Fatal(err)
  1181  		}
  1182  		anon.Nonce += 1
  1183  
  1184  		anon.Keys = []*ecdsa.PrivateKey{newKey}
  1185  	}
  1186  
  1187  	// 3. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1188  	{
  1189  		var txs types.Transactions
  1190  
  1191  		amount := new(big.Int).SetUint64(1000)
  1192  		values := map[types.TxValueKeyType]interface{}{
  1193  			types.TxValueKeyNonce:    anon.Nonce,
  1194  			types.TxValueKeyFrom:     anon.Addr,
  1195  			types.TxValueKeyTo:       reservoir.Addr,
  1196  			types.TxValueKeyAmount:   amount,
  1197  			types.TxValueKeyGasLimit: gasLimit,
  1198  			types.TxValueKeyGasPrice: gasPrice,
  1199  		}
  1200  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
  1201  		assert.Equal(t, nil, err)
  1202  
  1203  		err = tx.SignWithKeys(signer, anon.Keys)
  1204  		assert.Equal(t, nil, err)
  1205  
  1206  		txs = append(txs, tx)
  1207  
  1208  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1209  			t.Fatal(err)
  1210  		}
  1211  		anon.Nonce += 1
  1212  	}
  1213  
  1214  	// 4. Key update of anon using AccountUpdate with multisig keys.
  1215  	{
  1216  		var txs types.Transactions
  1217  
  1218  		k1, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867")
  1219  		if err != nil {
  1220  			t.Fatal(err)
  1221  		}
  1222  		k2, err := crypto.HexToECDSA("c64f2cd1196e2a1791365b00c4bc07ab8f047b73152e4617c6ed06ac221a4b0c")
  1223  		if err != nil {
  1224  			panic(err)
  1225  		}
  1226  		threshold := uint(2)
  1227  		keys := accountkey.WeightedPublicKeys{
  1228  			accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k1.PublicKey)),
  1229  			accountkey.NewWeightedPublicKey(1, (*accountkey.PublicKeySerializable)(&k2.PublicKey)),
  1230  		}
  1231  		newKey := accountkey.NewAccountKeyWeightedMultiSigWithValues(threshold, keys)
  1232  
  1233  		values := map[types.TxValueKeyType]interface{}{
  1234  			types.TxValueKeyNonce:      anon.Nonce,
  1235  			types.TxValueKeyFrom:       anon.Addr,
  1236  			types.TxValueKeyGasLimit:   gasLimit,
  1237  			types.TxValueKeyGasPrice:   gasPrice,
  1238  			types.TxValueKeyAccountKey: newKey,
  1239  		}
  1240  		tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values)
  1241  		assert.Equal(t, nil, err)
  1242  
  1243  		err = tx.SignWithKeys(signer, anon.Keys)
  1244  		assert.Equal(t, nil, err)
  1245  
  1246  		txs = append(txs, tx)
  1247  
  1248  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1249  			t.Fatal(err)
  1250  		}
  1251  		anon.Nonce += 1
  1252  
  1253  		anon.Keys = []*ecdsa.PrivateKey{k1, k2}
  1254  		anon.AccKey = newKey
  1255  	}
  1256  
  1257  	// 5. Transfer (anon-> reservoir) using TxTypeValueTransfer.
  1258  	{
  1259  		var txs types.Transactions
  1260  
  1261  		amount := new(big.Int).SetUint64(10000)
  1262  		values := map[types.TxValueKeyType]interface{}{
  1263  			types.TxValueKeyNonce:    anon.Nonce,
  1264  			types.TxValueKeyFrom:     anon.Addr,
  1265  			types.TxValueKeyTo:       reservoir.Addr,
  1266  			types.TxValueKeyAmount:   amount,
  1267  			types.TxValueKeyGasLimit: gasLimit,
  1268  			types.TxValueKeyGasPrice: gasPrice,
  1269  		}
  1270  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
  1271  		assert.Equal(t, nil, err)
  1272  
  1273  		err = tx.SignWithKeys(signer, anon.Keys)
  1274  		assert.Equal(t, nil, err)
  1275  
  1276  		txs = append(txs, tx)
  1277  
  1278  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1279  			t.Fatal(err)
  1280  		}
  1281  		anon.Nonce += 1
  1282  	}
  1283  
  1284  	if testing.Verbose() {
  1285  		prof.PrintProfileInfo()
  1286  	}
  1287  }
  1288  
  1289  // TestFeeDelegatedAccountUpdate tests a following scenario:
  1290  // 1. Transfer (reservoir -> anon) using a legacy transaction.
  1291  // 2. Key update of anon using TxTypeFeeDelegatedAccountUpdate
  1292  // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1293  func TestFeeDelegatedAccountUpdate(t *testing.T) {
  1294  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
  1295  	prof := profile.NewProfiler()
  1296  
  1297  	// Initialize blockchain
  1298  	start := time.Now()
  1299  	bcdata, err := NewBCData(6, 4)
  1300  	if err != nil {
  1301  		t.Fatal(err)
  1302  	}
  1303  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
  1304  	defer bcdata.Shutdown()
  1305  
  1306  	// Initialize address-balance map for verification
  1307  	start = time.Now()
  1308  	accountMap := NewAccountMap()
  1309  	if err := accountMap.Initialize(bcdata); err != nil {
  1310  		t.Fatal(err)
  1311  	}
  1312  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
  1313  
  1314  	// reservoir account
  1315  	reservoir := &TestAccountType{
  1316  		Addr:  *bcdata.addrs[0],
  1317  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
  1318  		Nonce: uint64(0),
  1319  	}
  1320  
  1321  	// anonymous account
  1322  	anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
  1323  	assert.Equal(t, nil, err)
  1324  
  1325  	if testing.Verbose() {
  1326  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
  1327  		fmt.Println("anonAddr = ", anon.Addr.String())
  1328  	}
  1329  
  1330  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
  1331  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
  1332  
  1333  	// 1. Transfer (reservoir -> anon) using a legacy transaction.
  1334  	{
  1335  		var txs types.Transactions
  1336  
  1337  		amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY))
  1338  		tx := types.NewTransaction(reservoir.Nonce,
  1339  			anon.Addr, amount, gasLimit, gasPrice, []byte{})
  1340  
  1341  		err := tx.SignWithKeys(signer, reservoir.Keys)
  1342  		assert.Equal(t, nil, err)
  1343  		txs = append(txs, tx)
  1344  
  1345  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1346  			t.Fatal(err)
  1347  		}
  1348  		reservoir.Nonce += 1
  1349  	}
  1350  
  1351  	// 2. Key update of anon using TxTypeFeeDelegatedAccountUpdate
  1352  	{
  1353  		var txs types.Transactions
  1354  
  1355  		newKey, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867")
  1356  		if err != nil {
  1357  			t.Fatal(err)
  1358  		}
  1359  
  1360  		values := map[types.TxValueKeyType]interface{}{
  1361  			types.TxValueKeyNonce:      anon.Nonce,
  1362  			types.TxValueKeyFrom:       anon.Addr,
  1363  			types.TxValueKeyGasLimit:   gasLimit,
  1364  			types.TxValueKeyGasPrice:   gasPrice,
  1365  			types.TxValueKeyAccountKey: accountkey.NewAccountKeyPublicWithValue(&newKey.PublicKey),
  1366  			types.TxValueKeyFeePayer:   reservoir.Addr,
  1367  		}
  1368  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedAccountUpdate, values)
  1369  		assert.Equal(t, nil, err)
  1370  
  1371  		err = tx.SignWithKeys(signer, anon.Keys)
  1372  		assert.Equal(t, nil, err)
  1373  
  1374  		err = tx.SignFeePayerWithKeys(signer, reservoir.Keys)
  1375  		assert.Equal(t, nil, err)
  1376  
  1377  		txs = append(txs, tx)
  1378  
  1379  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1380  			t.Fatal(err)
  1381  		}
  1382  		anon.Nonce += 1
  1383  
  1384  		anon.Keys = []*ecdsa.PrivateKey{newKey}
  1385  	}
  1386  
  1387  	// 3. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1388  	{
  1389  		var txs types.Transactions
  1390  
  1391  		amount := new(big.Int).SetUint64(1000)
  1392  		values := map[types.TxValueKeyType]interface{}{
  1393  			types.TxValueKeyNonce:    anon.Nonce,
  1394  			types.TxValueKeyFrom:     anon.Addr,
  1395  			types.TxValueKeyTo:       reservoir.Addr,
  1396  			types.TxValueKeyAmount:   amount,
  1397  			types.TxValueKeyGasLimit: gasLimit,
  1398  			types.TxValueKeyGasPrice: gasPrice,
  1399  		}
  1400  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
  1401  		assert.Equal(t, nil, err)
  1402  
  1403  		err = tx.SignWithKeys(signer, anon.Keys)
  1404  		assert.Equal(t, nil, err)
  1405  
  1406  		txs = append(txs, tx)
  1407  
  1408  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1409  			t.Fatal(err)
  1410  		}
  1411  		anon.Nonce += 1
  1412  	}
  1413  
  1414  	if testing.Verbose() {
  1415  		prof.PrintProfileInfo()
  1416  	}
  1417  }
  1418  
  1419  // TestFeeDelegatedAccountUpdateWithRatio tests a following scenario:
  1420  // 1. Transfer (reservoir -> anon) using a legacy transaction.
  1421  // 2. Key update of anon using TxTypeFeeDelegatedAccountUpdateWithRatio.
  1422  // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1423  func TestFeeDelegatedAccountUpdateWithRatio(t *testing.T) {
  1424  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
  1425  	prof := profile.NewProfiler()
  1426  
  1427  	// Initialize blockchain
  1428  	start := time.Now()
  1429  	bcdata, err := NewBCData(6, 4)
  1430  	if err != nil {
  1431  		t.Fatal(err)
  1432  	}
  1433  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
  1434  	defer bcdata.Shutdown()
  1435  
  1436  	// Initialize address-balance map for verification
  1437  	start = time.Now()
  1438  	accountMap := NewAccountMap()
  1439  	if err := accountMap.Initialize(bcdata); err != nil {
  1440  		t.Fatal(err)
  1441  	}
  1442  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
  1443  
  1444  	// reservoir account
  1445  	reservoir := &TestAccountType{
  1446  		Addr:  *bcdata.addrs[0],
  1447  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
  1448  		Nonce: uint64(0),
  1449  	}
  1450  
  1451  	// anonymous account
  1452  	anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
  1453  	assert.Equal(t, nil, err)
  1454  
  1455  	if testing.Verbose() {
  1456  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
  1457  		fmt.Println("anonAddr = ", anon.Addr.String())
  1458  	}
  1459  
  1460  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
  1461  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
  1462  
  1463  	// 1. Transfer (reservoir -> anon) using a legacy transaction.
  1464  	{
  1465  		var txs types.Transactions
  1466  
  1467  		amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY))
  1468  		tx := types.NewTransaction(reservoir.Nonce,
  1469  			anon.Addr, amount, gasLimit, gasPrice, []byte{})
  1470  
  1471  		err := tx.SignWithKeys(signer, reservoir.Keys)
  1472  		assert.Equal(t, nil, err)
  1473  		txs = append(txs, tx)
  1474  
  1475  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1476  			t.Fatal(err)
  1477  		}
  1478  		reservoir.Nonce += 1
  1479  	}
  1480  
  1481  	// 2. Key update of decoupled using TxTypeFeeDelegatedAccountUpdateWithRatio.
  1482  	{
  1483  		var txs types.Transactions
  1484  
  1485  		newKey, err := crypto.HexToECDSA("41bd2b972564206658eab115f26ff4db617e6eb39c81a557adc18d8305d2f867")
  1486  		if err != nil {
  1487  			t.Fatal(err)
  1488  		}
  1489  
  1490  		values := map[types.TxValueKeyType]interface{}{
  1491  			types.TxValueKeyNonce:              anon.Nonce,
  1492  			types.TxValueKeyFrom:               anon.Addr,
  1493  			types.TxValueKeyGasLimit:           gasLimit,
  1494  			types.TxValueKeyGasPrice:           gasPrice,
  1495  			types.TxValueKeyAccountKey:         accountkey.NewAccountKeyPublicWithValue(&newKey.PublicKey),
  1496  			types.TxValueKeyFeePayer:           reservoir.Addr,
  1497  			types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30),
  1498  		}
  1499  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedAccountUpdateWithRatio, values)
  1500  		assert.Equal(t, nil, err)
  1501  
  1502  		err = tx.SignWithKeys(signer, anon.Keys)
  1503  		assert.Equal(t, nil, err)
  1504  
  1505  		err = tx.SignFeePayerWithKeys(signer, reservoir.Keys)
  1506  		assert.Equal(t, nil, err)
  1507  
  1508  		txs = append(txs, tx)
  1509  
  1510  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1511  			t.Fatal(err)
  1512  		}
  1513  		anon.Nonce += 1
  1514  
  1515  		anon.Keys = []*ecdsa.PrivateKey{newKey}
  1516  	}
  1517  
  1518  	// 3. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1519  	{
  1520  		var txs types.Transactions
  1521  
  1522  		amount := new(big.Int).SetUint64(1000)
  1523  		values := map[types.TxValueKeyType]interface{}{
  1524  			types.TxValueKeyNonce:    anon.Nonce,
  1525  			types.TxValueKeyFrom:     anon.Addr,
  1526  			types.TxValueKeyTo:       reservoir.Addr,
  1527  			types.TxValueKeyAmount:   amount,
  1528  			types.TxValueKeyGasLimit: gasLimit,
  1529  			types.TxValueKeyGasPrice: gasPrice,
  1530  		}
  1531  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
  1532  		assert.Equal(t, nil, err)
  1533  
  1534  		err = tx.SignWithKeys(signer, anon.Keys)
  1535  		assert.Equal(t, nil, err)
  1536  
  1537  		txs = append(txs, tx)
  1538  
  1539  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1540  			t.Fatal(err)
  1541  		}
  1542  		anon.Nonce += 1
  1543  	}
  1544  
  1545  	if testing.Verbose() {
  1546  		prof.PrintProfileInfo()
  1547  	}
  1548  }
  1549  
  1550  // TestMultisigScenario tests a test case for a multi-sig accounts.
  1551  // 1. Create an account anon using LegacyTransaction.
  1552  // 2. Update the account with multisig key.
  1553  // 2. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1554  // 3. Transfer (anon -> reservoir) using TxTypeValueTransfer with only two keys.
  1555  // 4. FAILED-CASE: Transfer (anon -> reservoir) using TxTypeValueTransfer with only one key.
  1556  func TestMultisigScenario(t *testing.T) {
  1557  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
  1558  	prof := profile.NewProfiler()
  1559  
  1560  	// Initialize blockchain
  1561  	start := time.Now()
  1562  	bcdata, err := NewBCData(6, 4)
  1563  	if err != nil {
  1564  		t.Fatal(err)
  1565  	}
  1566  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
  1567  	defer bcdata.Shutdown()
  1568  
  1569  	// Initialize address-balance map for verification
  1570  	start = time.Now()
  1571  	accountMap := NewAccountMap()
  1572  	if err := accountMap.Initialize(bcdata); err != nil {
  1573  		t.Fatal(err)
  1574  	}
  1575  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
  1576  
  1577  	// reservoir account
  1578  	reservoir := &TestAccountType{
  1579  		Addr:  *bcdata.addrs[0],
  1580  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
  1581  		Nonce: uint64(0),
  1582  	}
  1583  
  1584  	// anonymous account
  1585  	anon, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
  1586  	assert.Equal(t, nil, err)
  1587  
  1588  	// multi-sig account
  1589  	multisig, err := createMultisigAccount(uint(2),
  1590  		[]uint{1, 1, 1},
  1591  		[]string{
  1592  			"bb113e82881499a7a361e8354a5b68f6c6885c7bcba09ea2b0891480396c322e",
  1593  			"a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989",
  1594  			"c32c471b732e2f56103e2f8e8cfd52792ef548f05f326e546a7d1fbf9d0419ec",
  1595  		},
  1596  		common.HexToAddress("0xbbfa38050bf3167c887c086758f448ce067ea8ea"))
  1597  
  1598  	if testing.Verbose() {
  1599  		fmt.Println("reservoirAddr = ", reservoir.Addr.String())
  1600  		fmt.Println("multisigAddr = ", multisig.Addr.String())
  1601  	}
  1602  
  1603  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
  1604  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
  1605  
  1606  	// 1. Create an account anon using LegacyTransaction.
  1607  	{
  1608  		var txs types.Transactions
  1609  
  1610  		amount := new(big.Int).Mul(big.NewInt(3000), new(big.Int).SetUint64(params.KLAY))
  1611  		tx := types.NewTransaction(reservoir.Nonce,
  1612  			anon.Addr, amount, gasLimit, gasPrice, []byte{})
  1613  
  1614  		err := tx.SignWithKeys(signer, reservoir.Keys)
  1615  		assert.Equal(t, nil, err)
  1616  		txs = append(txs, tx)
  1617  
  1618  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1619  			t.Fatal(err)
  1620  		}
  1621  		reservoir.Nonce += 1
  1622  	}
  1623  
  1624  	// 2. Update the account with multisig key.
  1625  	{
  1626  		var txs types.Transactions
  1627  
  1628  		values := map[types.TxValueKeyType]interface{}{
  1629  			types.TxValueKeyNonce:      anon.Nonce,
  1630  			types.TxValueKeyFrom:       anon.Addr,
  1631  			types.TxValueKeyGasLimit:   gasLimit,
  1632  			types.TxValueKeyGasPrice:   gasPrice,
  1633  			types.TxValueKeyAccountKey: multisig.AccKey,
  1634  		}
  1635  		tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, values)
  1636  		assert.Equal(t, nil, err)
  1637  
  1638  		err = tx.SignWithKeys(signer, anon.Keys)
  1639  		assert.Equal(t, nil, err)
  1640  
  1641  		txs = append(txs, tx)
  1642  
  1643  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1644  			t.Fatal(err)
  1645  		}
  1646  		anon.Nonce += 1
  1647  
  1648  		anon.AccKey = multisig.AccKey
  1649  		anon.Keys = multisig.Keys
  1650  	}
  1651  
  1652  	// 2. Transfer (anon -> reservoir) using TxTypeValueTransfer.
  1653  	{
  1654  		var txs types.Transactions
  1655  
  1656  		amount := new(big.Int).SetUint64(1000)
  1657  		values := map[types.TxValueKeyType]interface{}{
  1658  			types.TxValueKeyNonce:    anon.Nonce,
  1659  			types.TxValueKeyFrom:     anon.Addr,
  1660  			types.TxValueKeyTo:       reservoir.Addr,
  1661  			types.TxValueKeyAmount:   amount,
  1662  			types.TxValueKeyGasLimit: gasLimit,
  1663  			types.TxValueKeyGasPrice: gasPrice,
  1664  		}
  1665  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
  1666  		assert.Equal(t, nil, err)
  1667  
  1668  		err = tx.SignWithKeys(signer, anon.Keys)
  1669  		assert.Equal(t, nil, err)
  1670  
  1671  		txs = append(txs, tx)
  1672  
  1673  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1674  			t.Fatal(err)
  1675  		}
  1676  		anon.Nonce += 1
  1677  	}
  1678  
  1679  	// 3. Transfer (anon -> reservoir) using TxTypeValueTransfer with only two keys.
  1680  	{
  1681  		var txs types.Transactions
  1682  
  1683  		amount := new(big.Int).SetUint64(1000)
  1684  		values := map[types.TxValueKeyType]interface{}{
  1685  			types.TxValueKeyNonce:    anon.Nonce,
  1686  			types.TxValueKeyFrom:     anon.Addr,
  1687  			types.TxValueKeyTo:       reservoir.Addr,
  1688  			types.TxValueKeyAmount:   amount,
  1689  			types.TxValueKeyGasLimit: gasLimit,
  1690  			types.TxValueKeyGasPrice: gasPrice,
  1691  		}
  1692  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
  1693  		assert.Equal(t, nil, err)
  1694  
  1695  		err = tx.SignWithKeys(signer, anon.Keys[0:2])
  1696  		assert.Equal(t, nil, err)
  1697  
  1698  		txs = append(txs, tx)
  1699  
  1700  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
  1701  			t.Fatal(err)
  1702  		}
  1703  		anon.Nonce += 1
  1704  	}
  1705  
  1706  	// 4. FAILED-CASE: Transfer (anon -> reservoir) using TxTypeValueTransfer with only one key.
  1707  	{
  1708  		amount := new(big.Int).SetUint64(1000)
  1709  		values := map[types.TxValueKeyType]interface{}{
  1710  			types.TxValueKeyNonce:    anon.Nonce,
  1711  			types.TxValueKeyFrom:     anon.Addr,
  1712  			types.TxValueKeyTo:       reservoir.Addr,
  1713  			types.TxValueKeyAmount:   amount,
  1714  			types.TxValueKeyGasLimit: gasLimit,
  1715  			types.TxValueKeyGasPrice: gasPrice,
  1716  		}
  1717  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
  1718  		assert.Equal(t, nil, err)
  1719  
  1720  		err = tx.SignWithKeys(signer, anon.Keys[:1])
  1721  		assert.Equal(t, nil, err)
  1722  
  1723  		receipt, err := applyTransaction(t, bcdata, tx)
  1724  		assert.Equal(t, types.ErrSender(types.ErrInvalidAccountKey), err)
  1725  		assert.Equal(t, (*types.Receipt)(nil), receipt)
  1726  	}
  1727  
  1728  	if testing.Verbose() {
  1729  		prof.PrintProfileInfo()
  1730  	}
  1731  }
  1732  
  1733  // TestValidateSender tests ValidateSender with all transaction types.
  1734  func TestValidateSender(t *testing.T) {
  1735  	// anonymous account
  1736  	anon, err := createAnonymousAccount("1da6dfcb52128060cdd2108edb786ca0aff4ef1fa537574286eeabe5c2ebd5ca")
  1737  	assert.Equal(t, nil, err)
  1738  
  1739  	// decoupled account
  1740  	decoupled, err := createDecoupledAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab",
  1741  		common.HexToAddress("0x5104711f7faa9e2dadf593e43db1577a2887636f"))
  1742  	assert.Equal(t, nil, err)
  1743  
  1744  	initialBalance := big.NewInt(1000000)
  1745  
  1746  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil, nil)
  1747  	statedb.CreateEOA(anon.Addr, false, anon.AccKey)
  1748  	statedb.SetNonce(anon.Addr, nonce)
  1749  	statedb.SetBalance(anon.Addr, initialBalance)
  1750  
  1751  	statedb.CreateEOA(decoupled.Addr, false, decoupled.AccKey)
  1752  	statedb.SetNonce(decoupled.Addr, rand.Uint64())
  1753  	statedb.SetBalance(decoupled.Addr, initialBalance)
  1754  
  1755  	signer := types.MakeSigner(params.BFTTestChainConfig, big.NewInt(32))
  1756  	gasPrice := new(big.Int).SetUint64(0)
  1757  	gasLimit := uint64(100000000000)
  1758  	amount := new(big.Int).SetUint64(10000)
  1759  
  1760  	// LegacyTransaction
  1761  	{
  1762  		amount := new(big.Int).SetUint64(100000000000)
  1763  		tx := types.NewTransaction(anon.Nonce,
  1764  			decoupled.Addr, amount, gasLimit, gasPrice, []byte{})
  1765  
  1766  		err := tx.SignWithKeys(signer, anon.Keys)
  1767  		assert.Equal(t, nil, err)
  1768  
  1769  		_, err = tx.ValidateSender(signer, statedb, 0)
  1770  		assert.Equal(t, nil, err)
  1771  		assert.Equal(t, anon.Addr, tx.ValidatedSender())
  1772  	}
  1773  
  1774  	// TxTypeValueTransfer
  1775  	{
  1776  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, map[types.TxValueKeyType]interface{}{
  1777  			types.TxValueKeyNonce:    nonce,
  1778  			types.TxValueKeyFrom:     anon.Addr,
  1779  			types.TxValueKeyTo:       decoupled.Addr,
  1780  			types.TxValueKeyAmount:   amount,
  1781  			types.TxValueKeyGasLimit: gasLimit,
  1782  			types.TxValueKeyGasPrice: gasPrice,
  1783  		})
  1784  		assert.Equal(t, nil, err)
  1785  
  1786  		err = tx.SignWithKeys(signer, anon.Keys)
  1787  		assert.Equal(t, nil, err)
  1788  
  1789  		_, err = tx.ValidateSender(signer, statedb, 0)
  1790  		assert.Equal(t, nil, err)
  1791  		assert.Equal(t, anon.Addr, tx.ValidatedSender())
  1792  	}
  1793  
  1794  	// TxTypeValueTransfer
  1795  	{
  1796  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, map[types.TxValueKeyType]interface{}{
  1797  			types.TxValueKeyNonce:    nonce,
  1798  			types.TxValueKeyFrom:     decoupled.Addr,
  1799  			types.TxValueKeyTo:       decoupled.Addr,
  1800  			types.TxValueKeyAmount:   amount,
  1801  			types.TxValueKeyGasLimit: gasLimit,
  1802  			types.TxValueKeyGasPrice: gasPrice,
  1803  		})
  1804  		assert.Equal(t, nil, err)
  1805  
  1806  		err = tx.SignWithKeys(signer, decoupled.Keys)
  1807  		assert.Equal(t, nil, err)
  1808  
  1809  		_, err = tx.ValidateSender(signer, statedb, 0)
  1810  		assert.Equal(t, nil, err)
  1811  		assert.Equal(t, decoupled.Addr, tx.ValidatedSender())
  1812  	}
  1813  
  1814  	// TxTypeSmartContractDeploy
  1815  	{
  1816  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, map[types.TxValueKeyType]interface{}{
  1817  			types.TxValueKeyNonce:         nonce,
  1818  			types.TxValueKeyFrom:          decoupled.Addr,
  1819  			types.TxValueKeyTo:            &anon.Addr,
  1820  			types.TxValueKeyAmount:        amount,
  1821  			types.TxValueKeyGasLimit:      gasLimit,
  1822  			types.TxValueKeyGasPrice:      gasPrice,
  1823  			types.TxValueKeyHumanReadable: false,
  1824  			// The binary below is a compiled binary of contracts/reward/contract/KlaytnReward.sol.
  1825  			types.TxValueKeyData:       common.Hex2Bytes("608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"),
  1826  			types.TxValueKeyCodeFormat: params.CodeFormatEVM,
  1827  		})
  1828  		assert.Equal(t, nil, err)
  1829  
  1830  		err = tx.SignWithKeys(signer, decoupled.Keys)
  1831  		assert.Equal(t, nil, err)
  1832  
  1833  		_, err = tx.ValidateSender(signer, statedb, 0)
  1834  		assert.Equal(t, nil, err)
  1835  		assert.Equal(t, decoupled.Addr, tx.ValidatedSender())
  1836  	}
  1837  
  1838  	// TxTypeSmartContractExecution
  1839  	{
  1840  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractExecution, map[types.TxValueKeyType]interface{}{
  1841  			types.TxValueKeyNonce:    nonce,
  1842  			types.TxValueKeyFrom:     decoupled.Addr,
  1843  			types.TxValueKeyTo:       anon.Addr,
  1844  			types.TxValueKeyAmount:   amount,
  1845  			types.TxValueKeyGasLimit: gasLimit,
  1846  			types.TxValueKeyGasPrice: gasPrice,
  1847  			// A abi-packed bytes calling "reward" of contracts/reward/contract/KlaytnReward.sol with an address "bc5951f055a85f41a3b62fd6f68ab7de76d299b2".
  1848  			types.TxValueKeyData: common.Hex2Bytes("6353586b000000000000000000000000bc5951f055a85f41a3b62fd6f68ab7de76d299b2"),
  1849  		})
  1850  		assert.Equal(t, nil, err)
  1851  
  1852  		err = tx.SignWithKeys(signer, decoupled.Keys)
  1853  		assert.Equal(t, nil, err)
  1854  
  1855  		_, err = tx.ValidateSender(signer, statedb, 0)
  1856  		assert.Equal(t, nil, err)
  1857  		assert.Equal(t, decoupled.Addr, tx.ValidatedSender())
  1858  	}
  1859  
  1860  	// TxTypeChainDataAnchoring
  1861  	{
  1862  		dummyBlock := types.NewBlock(&types.Header{}, nil, nil)
  1863  
  1864  		scData, err := types.NewAnchoringDataType0(dummyBlock, 0, uint64(dummyBlock.Transactions().Len()))
  1865  		if err != nil {
  1866  			t.Fatal(err)
  1867  		}
  1868  		dataAnchoredRLP, _ := rlp.EncodeToBytes(scData)
  1869  
  1870  		values := map[types.TxValueKeyType]interface{}{
  1871  			types.TxValueKeyNonce:        anon.Nonce,
  1872  			types.TxValueKeyFrom:         anon.Addr,
  1873  			types.TxValueKeyGasLimit:     gasLimit,
  1874  			types.TxValueKeyGasPrice:     gasPrice,
  1875  			types.TxValueKeyAnchoredData: dataAnchoredRLP,
  1876  		}
  1877  		tx, err := types.NewTransactionWithMap(types.TxTypeChainDataAnchoring, values)
  1878  		if err != nil {
  1879  			t.Fatal(err)
  1880  		}
  1881  		err = tx.SignWithKeys(signer, anon.Keys)
  1882  		assert.Equal(t, nil, err)
  1883  
  1884  		_, err = tx.ValidateSender(signer, statedb, 0)
  1885  		assert.Equal(t, nil, err)
  1886  		assert.Equal(t, anon.Addr, tx.ValidatedSender())
  1887  	}
  1888  
  1889  	// TxTypeFeeDelegatedValueTransfer
  1890  	{
  1891  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransfer, map[types.TxValueKeyType]interface{}{
  1892  			types.TxValueKeyNonce:    nonce,
  1893  			types.TxValueKeyFrom:     decoupled.Addr,
  1894  			types.TxValueKeyFeePayer: anon.Addr,
  1895  			types.TxValueKeyTo:       decoupled.Addr,
  1896  			types.TxValueKeyAmount:   amount,
  1897  			types.TxValueKeyGasLimit: gasLimit,
  1898  			types.TxValueKeyGasPrice: gasPrice,
  1899  		})
  1900  		assert.Equal(t, nil, err)
  1901  
  1902  		err = tx.SignWithKeys(signer, decoupled.Keys)
  1903  		assert.Equal(t, nil, err)
  1904  
  1905  		err = tx.SignFeePayerWithKeys(signer, anon.Keys)
  1906  		assert.Equal(t, nil, err)
  1907  
  1908  		_, err = tx.ValidateSender(signer, statedb, 0)
  1909  		assert.Equal(t, nil, err)
  1910  		assert.Equal(t, decoupled.Addr, tx.ValidatedSender())
  1911  
  1912  		_, err = tx.ValidateFeePayer(signer, statedb, 0)
  1913  		assert.Equal(t, nil, err)
  1914  		assert.Equal(t, anon.Addr, tx.ValidatedFeePayer())
  1915  	}
  1916  
  1917  	// TxTypeFeeDelegatedValueTransferWithRatio
  1918  	{
  1919  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedValueTransferWithRatio, map[types.TxValueKeyType]interface{}{
  1920  			types.TxValueKeyNonce:              nonce,
  1921  			types.TxValueKeyFrom:               decoupled.Addr,
  1922  			types.TxValueKeyFeePayer:           anon.Addr,
  1923  			types.TxValueKeyTo:                 decoupled.Addr,
  1924  			types.TxValueKeyAmount:             amount,
  1925  			types.TxValueKeyGasLimit:           gasLimit,
  1926  			types.TxValueKeyGasPrice:           gasPrice,
  1927  			types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30),
  1928  		})
  1929  		assert.Equal(t, nil, err)
  1930  
  1931  		err = tx.SignWithKeys(signer, decoupled.Keys)
  1932  		assert.Equal(t, nil, err)
  1933  
  1934  		err = tx.SignFeePayerWithKeys(signer, anon.Keys)
  1935  		assert.Equal(t, nil, err)
  1936  
  1937  		_, err = tx.ValidateSender(signer, statedb, 0)
  1938  		assert.Equal(t, nil, err)
  1939  		assert.Equal(t, decoupled.Addr, tx.ValidatedSender())
  1940  
  1941  		_, err = tx.ValidateFeePayer(signer, statedb, 0)
  1942  		assert.Equal(t, nil, err)
  1943  		assert.Equal(t, anon.Addr, tx.ValidatedFeePayer())
  1944  	}
  1945  }
  1946  
  1947  func isCompilerAvailable() bool {
  1948  	solc, err := compiler.SolidityVersion("")
  1949  	if err != nil {
  1950  		fmt.Println("Solidity version check failed. Skipping this test", err)
  1951  		return false
  1952  	}
  1953  	if solc.Version != "0.4.24" && solc.Version != "0.4.25" {
  1954  		if testing.Verbose() {
  1955  			fmt.Println("solc version mismatch. Supported versions are 0.4.24 and 0.4.25.", "version", solc.Version)
  1956  		}
  1957  		return false
  1958  	}
  1959  
  1960  	return true
  1961  }
  1962  
  1963  func compileSolidity(filename string) (code []string, abiStr []string) {
  1964  	contracts, err := compiler.CompileSolidity("", filename)
  1965  	if err != nil {
  1966  		panic(err)
  1967  	}
  1968  
  1969  	code = make([]string, 0, len(contracts))
  1970  	abiStr = make([]string, 0, len(contracts))
  1971  
  1972  	for _, c := range contracts {
  1973  		abiBytes, err := json.Marshal(c.Info.AbiDefinition)
  1974  		if err != nil {
  1975  			panic(err)
  1976  		}
  1977  
  1978  		code = append(code, c.Code)
  1979  		abiStr = append(abiStr, string(abiBytes))
  1980  	}
  1981  
  1982  	return
  1983  }
  1984  
  1985  // applyTransaction setups variables to call block.ApplyTransaction() for tests.
  1986  // It directly returns values from block.ApplyTransaction().
  1987  func applyTransaction(t *testing.T, bcdata *BCData, tx *types.Transaction) (*types.Receipt, error) {
  1988  	state, err := bcdata.bc.State()
  1989  	assert.Equal(t, nil, err)
  1990  
  1991  	vmConfig := &vm.Config{
  1992  		JumpTable: vm.ConstantinopleInstructionSet,
  1993  	}
  1994  	parent := bcdata.bc.CurrentBlock()
  1995  	num := parent.Number()
  1996  	author := bcdata.addrs[0]
  1997  	header := &types.Header{
  1998  		ParentHash: parent.Hash(),
  1999  		Number:     num.Add(num, common.Big1),
  2000  		Extra:      parent.Extra(),
  2001  		Time:       new(big.Int).Add(parent.Time(), common.Big1),
  2002  		BlockScore: big.NewInt(0),
  2003  	}
  2004  	usedGas := uint64(0)
  2005  	receipt, _, err := bcdata.bc.ApplyTransaction(bcdata.bc.Config(), author, state, header, tx, &usedGas, vmConfig)
  2006  	return receipt, err
  2007  }