github.com/klaytn/klaytn@v1.10.2/tests/transaction_validation_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  	"math/big"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/klaytn/klaytn/blockchain"
    26  	"github.com/klaytn/klaytn/blockchain/types"
    27  	"github.com/klaytn/klaytn/blockchain/types/accountkey"
    28  	"github.com/klaytn/klaytn/common"
    29  	"github.com/klaytn/klaytn/common/profile"
    30  	"github.com/klaytn/klaytn/crypto"
    31  	"github.com/klaytn/klaytn/kerrors"
    32  	"github.com/klaytn/klaytn/log"
    33  	"github.com/klaytn/klaytn/params"
    34  	"github.com/stretchr/testify/assert"
    35  )
    36  
    37  // TestValidatingUnavailableContractExecution tests validation logic of invalid contract execution transaction.
    38  // TxPool will invalidate contract execution transactions sending to un-executable account even though the recipient is a contract account.
    39  func TestValidatingUnavailableContractExecution(t *testing.T) {
    40  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
    41  	prof := profile.NewProfiler()
    42  
    43  	// Initialize blockchain
    44  	start := time.Now()
    45  	bcdata, err := NewBCData(6, 4)
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
    50  	defer bcdata.Shutdown()
    51  
    52  	// Initialize address-balance map for verification
    53  	start = time.Now()
    54  	accountMap := NewAccountMap()
    55  	if err := accountMap.Initialize(bcdata); err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
    59  
    60  	signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID)
    61  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
    62  
    63  	// reservoir account
    64  	reservoir := &TestAccountType{
    65  		Addr:  *bcdata.addrs[0],
    66  		Keys:  []*ecdsa.PrivateKey{bcdata.privKeys[0]},
    67  		Nonce: uint64(0),
    68  	}
    69  
    70  	// various accounts preparation
    71  	contract, err := createAnonymousAccount("98275a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78991dab")
    72  	contract.Addr = common.Address{}
    73  
    74  	invalidContract, err := createAnonymousAccount("11115a145bc1726eb0445433088f5f882f8a4a9499135239cfb4040e78911111")
    75  	invalidContract.Addr = common.Address{}
    76  
    77  	EOA, err := createDefaultAccount(accountkey.AccountKeyTypeLegacy)
    78  	assert.Equal(t, nil, err)
    79  
    80  	code = "0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029"
    81  
    82  	// Prepare. creates various types of accounts tried to be executed
    83  	{
    84  		var txs types.Transactions
    85  
    86  		// tx to create a contract account
    87  		values := map[types.TxValueKeyType]interface{}{
    88  			types.TxValueKeyNonce:         reservoir.GetNonce(),
    89  			types.TxValueKeyAmount:        new(big.Int).SetUint64(0),
    90  			types.TxValueKeyGasLimit:      gasLimit,
    91  			types.TxValueKeyGasPrice:      gasPrice,
    92  			types.TxValueKeyHumanReadable: false,
    93  			types.TxValueKeyTo:            (*common.Address)(nil),
    94  			types.TxValueKeyFrom:          reservoir.GetAddr(),
    95  			types.TxValueKeyData:          common.FromHex(code),
    96  			types.TxValueKeyCodeFormat:    params.CodeFormatEVM,
    97  		}
    98  		tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values)
    99  		assert.Equal(t, nil, err)
   100  
   101  		err = tx.SignWithKeys(signer, reservoir.Keys)
   102  		assert.Equal(t, nil, err)
   103  
   104  		txs = append(txs, tx)
   105  
   106  		contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   107  
   108  		reservoir.Nonce += 1
   109  
   110  		// tx2 to create a invalid contract account
   111  		values = map[types.TxValueKeyType]interface{}{
   112  			types.TxValueKeyNonce:         reservoir.GetNonce(),
   113  			types.TxValueKeyAmount:        new(big.Int).SetUint64(0),
   114  			types.TxValueKeyGasLimit:      gasLimit,
   115  			types.TxValueKeyGasPrice:      gasPrice,
   116  			types.TxValueKeyHumanReadable: false,
   117  			types.TxValueKeyTo:            (*common.Address)(nil),
   118  			types.TxValueKeyFrom:          reservoir.GetAddr(),
   119  			types.TxValueKeyData:          []byte{}, // the invalid contract doesn't have contract code
   120  			types.TxValueKeyCodeFormat:    params.CodeFormatEVM,
   121  		}
   122  		tx2, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values)
   123  		assert.Equal(t, nil, err)
   124  
   125  		err = tx2.SignWithKeys(signer, reservoir.Keys)
   126  		assert.Equal(t, nil, err)
   127  
   128  		txs = append(txs, tx2)
   129  
   130  		invalidContract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce)
   131  
   132  		reservoir.Nonce += 1
   133  
   134  		// tx3 to create an EOA account
   135  		tx3, _, err := generateDefaultTx(reservoir, EOA, types.TxTypeValueTransfer, contract.Addr)
   136  		assert.Equal(t, nil, err)
   137  
   138  		err = tx3.SignWithKeys(signer, reservoir.Keys)
   139  		assert.Equal(t, nil, err)
   140  
   141  		txs = append(txs, tx3)
   142  		reservoir.Nonce += 1
   143  
   144  		if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil {
   145  			t.Fatal(err)
   146  		}
   147  	}
   148  
   149  	// make TxPool to test validation in 'TxPool add' process
   150  	txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc)
   151  
   152  	// 1. contract execution transaction to the contract account.
   153  	{
   154  		tx, _ := genSmartContractExecution(t, signer, reservoir, contract, nil, gasPrice)
   155  
   156  		err = txpool.AddRemote(tx)
   157  		assert.Equal(t, nil, err)
   158  	}
   159  
   160  	// 2. contract execution transaction to the invalid contract account.
   161  	{
   162  		tx, _ := genSmartContractExecution(t, signer, reservoir, invalidContract, nil, gasPrice)
   163  
   164  		err = txpool.AddRemote(tx)
   165  		assert.Equal(t, kerrors.ErrNotProgramAccount, err)
   166  	}
   167  
   168  	// 3. contract execution transaction to the EOA account.
   169  	{
   170  		tx, _ := genSmartContractExecution(t, signer, reservoir, EOA, nil, gasPrice)
   171  
   172  		err = txpool.AddRemote(tx)
   173  		assert.Equal(t, kerrors.ErrNotProgramAccount, err)
   174  	}
   175  
   176  	if testing.Verbose() {
   177  		prof.PrintProfileInfo()
   178  	}
   179  }