github.com/klaytn/klaytn@v1.12.1/tests/tx_cancel_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/common/profile"
    28  	"github.com/klaytn/klaytn/log"
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  // TestTxCancel tests TxCancel transaction types:
    33  // 1. Insert a value transfer transaction with nonce 0.
    34  // 2. Insert a value transfer transaction with nonce 0. This should not be replaced.
    35  // 3. Insert a TxCancel transaction with nonce 0. This should replace the tx with the same nonce.
    36  // 4. Insert a TxCancel transaction with nonce 0 and different gas limit. This should replace the tx with the same nonce.
    37  func TestTxCancel(t *testing.T) {
    38  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
    39  	prof := profile.NewProfiler()
    40  	opt := testOption{1000, 2000, 4, 1, []byte{}, makeNewTransactionsToRandom}
    41  
    42  	// Initialize blockchain
    43  	start := time.Now()
    44  	bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators)
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
    49  	defer bcdata.Shutdown()
    50  
    51  	// Initialize address-balance map for verification
    52  	start = time.Now()
    53  	accountMap := NewAccountMap()
    54  	if err := accountMap.Initialize(bcdata); err != nil {
    55  		t.Fatal(err)
    56  	}
    57  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
    58  
    59  	// make TxPool to test validation in 'TxPool add' process
    60  	txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc)
    61  
    62  	signer := types.MakeSigner(bcdata.bc.Config(), bcdata.bc.CurrentHeader().Number)
    63  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
    64  
    65  	// 1. Insert a value transfer transaction with nonce 0.
    66  	{
    67  		var txs types.Transactions
    68  
    69  		amount := new(big.Int).SetUint64(1000)
    70  		values := map[types.TxValueKeyType]interface{}{
    71  			types.TxValueKeyNonce:    uint64(0),
    72  			types.TxValueKeyFrom:     *bcdata.addrs[0],
    73  			types.TxValueKeyTo:       *bcdata.addrs[0],
    74  			types.TxValueKeyAmount:   amount,
    75  			types.TxValueKeyGasLimit: gasLimit,
    76  			types.TxValueKeyGasPrice: gasPrice,
    77  		}
    78  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
    79  		assert.Equal(t, nil, err)
    80  
    81  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
    82  		assert.Equal(t, nil, err)
    83  
    84  		txs = append(txs, tx)
    85  
    86  		txpool.AddRemotes(txs)
    87  
    88  		pending, queued := txpool.Content()
    89  		assert.Equal(t, 0, len(queued))
    90  		assert.Equal(t, 1, len(pending))
    91  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
    92  	}
    93  
    94  	// 2. Insert a value transfer transaction with nonce 0. This should not be replaced.
    95  	{
    96  		var txs types.Transactions
    97  
    98  		pending, queued := txpool.Content()
    99  		oldtx := pending[*bcdata.addrs[0]][0]
   100  
   101  		amount := new(big.Int).SetUint64(1000)
   102  		values := map[types.TxValueKeyType]interface{}{
   103  			types.TxValueKeyNonce:    uint64(0),
   104  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   105  			types.TxValueKeyTo:       *bcdata.addrs[1],
   106  			types.TxValueKeyAmount:   amount,
   107  			types.TxValueKeyGasLimit: gasLimit,
   108  			types.TxValueKeyGasPrice: gasPrice,
   109  		}
   110  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
   111  		assert.Equal(t, nil, err)
   112  
   113  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   114  		assert.Equal(t, nil, err)
   115  
   116  		txs = append(txs, tx)
   117  
   118  		txpool.AddRemotes(txs)
   119  
   120  		pending, queued = txpool.Content()
   121  		assert.Equal(t, 0, len(queued))
   122  		assert.Equal(t, 1, len(pending))
   123  		assert.True(t, oldtx.Equal(pending[*bcdata.addrs[0]][0]))
   124  	}
   125  
   126  	// 3. Insert a TxCancel transaction with nonce 0. This should replace the tx with the same nonce.
   127  	{
   128  		var txs types.Transactions
   129  
   130  		values := map[types.TxValueKeyType]interface{}{
   131  			types.TxValueKeyNonce:    uint64(0),
   132  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   133  			types.TxValueKeyGasLimit: gasLimit,
   134  			types.TxValueKeyGasPrice: gasPrice,
   135  		}
   136  		tx, err := types.NewTransactionWithMap(types.TxTypeCancel, values)
   137  		assert.Equal(t, nil, err)
   138  
   139  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   140  		assert.Equal(t, nil, err)
   141  
   142  		txs = append(txs, tx)
   143  
   144  		txpool.AddRemotes(txs)
   145  
   146  		pending, queued := txpool.Content()
   147  		assert.Equal(t, 0, len(queued))
   148  		assert.Equal(t, 1, len(pending))
   149  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   150  	}
   151  
   152  	// 4. Insert a TxCancel transaction with nonce 0 and different gas limit. This should replace the tx with the same nonce.
   153  	{
   154  		var txs types.Transactions
   155  
   156  		values := map[types.TxValueKeyType]interface{}{
   157  			types.TxValueKeyNonce:    uint64(0),
   158  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   159  			types.TxValueKeyGasLimit: gasLimit + 10,
   160  			types.TxValueKeyGasPrice: gasPrice,
   161  		}
   162  		tx, err := types.NewTransactionWithMap(types.TxTypeCancel, values)
   163  		assert.Equal(t, nil, err)
   164  
   165  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   166  		assert.Equal(t, nil, err)
   167  
   168  		txs = append(txs, tx)
   169  
   170  		txpool.AddRemotes(txs)
   171  
   172  		pending, queued := txpool.Content()
   173  		assert.Equal(t, 0, len(queued))
   174  		assert.Equal(t, 1, len(pending))
   175  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   176  	}
   177  
   178  	if testing.Verbose() {
   179  		prof.PrintProfileInfo()
   180  	}
   181  }
   182  
   183  // TestTxFeeDelegatedCancel tests TxCancel transaction types:
   184  // 1. Insert a value transfer transaction with nonce 0.
   185  // 2. Insert a value transfer transaction with nonce 0. This should not be replaced.
   186  // 3. Insert a TxCancel transaction with nonce 0. This should replace the tx with the same nonce.
   187  // 4. Insert a TxCancel transaction with nonce 0 and different gas limit. This should replace the tx with the same nonce.
   188  func TestTxFeeDelegatedCancel(t *testing.T) {
   189  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   190  	prof := profile.NewProfiler()
   191  	opt := testOption{1000, 2000, 4, 1, []byte{}, makeNewTransactionsToRandom}
   192  
   193  	// Initialize blockchain
   194  	start := time.Now()
   195  	bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators)
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   200  	defer bcdata.Shutdown()
   201  
   202  	// Initialize address-balance map for verification
   203  	start = time.Now()
   204  	accountMap := NewAccountMap()
   205  	if err := accountMap.Initialize(bcdata); err != nil {
   206  		t.Fatal(err)
   207  	}
   208  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   209  
   210  	// make TxPool to test validation in 'TxPool add' process
   211  	txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc)
   212  
   213  	signer := types.MakeSigner(bcdata.bc.Config(), bcdata.bc.CurrentHeader().Number)
   214  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
   215  
   216  	// 1. Insert a value transfer transaction with nonce 0.
   217  	{
   218  		var txs types.Transactions
   219  
   220  		amount := new(big.Int).SetUint64(1000)
   221  		values := map[types.TxValueKeyType]interface{}{
   222  			types.TxValueKeyNonce:    uint64(0),
   223  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   224  			types.TxValueKeyTo:       *bcdata.addrs[0],
   225  			types.TxValueKeyAmount:   amount,
   226  			types.TxValueKeyGasLimit: gasLimit,
   227  			types.TxValueKeyGasPrice: gasPrice,
   228  		}
   229  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
   230  		assert.Equal(t, nil, err)
   231  
   232  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   233  		assert.Equal(t, nil, err)
   234  
   235  		txs = append(txs, tx)
   236  
   237  		txpool.AddRemotes(txs)
   238  
   239  		pending, queued := txpool.Content()
   240  		assert.Equal(t, 0, len(queued))
   241  		assert.Equal(t, 1, len(pending))
   242  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   243  	}
   244  
   245  	// 2. Insert a value transfer transaction with nonce 0. This should not be replaced.
   246  	{
   247  		var txs types.Transactions
   248  
   249  		pending, queued := txpool.Content()
   250  		oldtx := pending[*bcdata.addrs[0]][0]
   251  
   252  		amount := new(big.Int).SetUint64(1000)
   253  		values := map[types.TxValueKeyType]interface{}{
   254  			types.TxValueKeyNonce:    uint64(0),
   255  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   256  			types.TxValueKeyTo:       *bcdata.addrs[1],
   257  			types.TxValueKeyAmount:   amount,
   258  			types.TxValueKeyGasLimit: gasLimit,
   259  			types.TxValueKeyGasPrice: gasPrice,
   260  		}
   261  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
   262  		assert.Equal(t, nil, err)
   263  
   264  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   265  		assert.Equal(t, nil, err)
   266  
   267  		txs = append(txs, tx)
   268  
   269  		txpool.AddRemotes(txs)
   270  
   271  		pending, queued = txpool.Content()
   272  		assert.Equal(t, 0, len(queued))
   273  		assert.Equal(t, 1, len(pending))
   274  		assert.True(t, oldtx.Equal(pending[*bcdata.addrs[0]][0]))
   275  	}
   276  
   277  	// 3. Insert a TxCancel transaction with nonce 0. This should replace the tx with the same nonce.
   278  	{
   279  		var txs types.Transactions
   280  
   281  		values := map[types.TxValueKeyType]interface{}{
   282  			types.TxValueKeyNonce:    uint64(0),
   283  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   284  			types.TxValueKeyGasLimit: gasLimit,
   285  			types.TxValueKeyGasPrice: gasPrice,
   286  			types.TxValueKeyFeePayer: *bcdata.addrs[1],
   287  		}
   288  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedCancel, values)
   289  		assert.Equal(t, nil, err)
   290  
   291  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   292  		assert.Equal(t, nil, err)
   293  
   294  		err = tx.SignFeePayerWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[1]})
   295  		assert.Equal(t, nil, err)
   296  
   297  		txs = append(txs, tx)
   298  
   299  		txpool.AddRemotes(txs)
   300  
   301  		pending, queued := txpool.Content()
   302  		assert.Equal(t, 0, len(queued))
   303  		assert.Equal(t, 1, len(pending))
   304  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   305  	}
   306  
   307  	// 4. Insert a TxCancel transaction with nonce 0 and different gas limit. This should replace the tx with the same nonce.
   308  	{
   309  		var txs types.Transactions
   310  
   311  		values := map[types.TxValueKeyType]interface{}{
   312  			types.TxValueKeyNonce:    uint64(0),
   313  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   314  			types.TxValueKeyGasLimit: gasLimit + 10,
   315  			types.TxValueKeyGasPrice: gasPrice,
   316  			types.TxValueKeyFeePayer: *bcdata.addrs[1],
   317  		}
   318  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedCancel, values)
   319  		assert.Equal(t, nil, err)
   320  
   321  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   322  		assert.Equal(t, nil, err)
   323  
   324  		err = tx.SignFeePayerWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[1]})
   325  		assert.Equal(t, nil, err)
   326  
   327  		txs = append(txs, tx)
   328  
   329  		txpool.AddRemotes(txs)
   330  
   331  		pending, queued := txpool.Content()
   332  		assert.Equal(t, 0, len(queued))
   333  		assert.Equal(t, 1, len(pending))
   334  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   335  	}
   336  
   337  	if testing.Verbose() {
   338  		prof.PrintProfileInfo()
   339  	}
   340  }
   341  
   342  // TestTxFeeDelegatedCancelWithRatio tests TxCancel transaction types:
   343  // 1. Insert a value transfer transaction with nonce 0.
   344  // 2. Insert a value transfer transaction with nonce 0. This should not be replaced.
   345  // 3. Insert a TxCancel transaction with nonce 0. This should replace the tx with the same nonce.
   346  // 4. Insert a TxCancel transaction with nonce 0 and different gas limit. This should replace the tx with the same nonce.
   347  func TestTxFeeDelegatedCancelWithRatio(t *testing.T) {
   348  	log.EnableLogForTest(log.LvlCrit, log.LvlTrace)
   349  	prof := profile.NewProfiler()
   350  	opt := testOption{1000, 2000, 4, 1, []byte{}, makeNewTransactionsToRandom}
   351  
   352  	// Initialize blockchain
   353  	start := time.Now()
   354  	bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators)
   355  	if err != nil {
   356  		t.Fatal(err)
   357  	}
   358  	prof.Profile("main_init_blockchain", time.Now().Sub(start))
   359  	defer bcdata.Shutdown()
   360  
   361  	// Initialize address-balance map for verification
   362  	start = time.Now()
   363  	accountMap := NewAccountMap()
   364  	if err := accountMap.Initialize(bcdata); err != nil {
   365  		t.Fatal(err)
   366  	}
   367  	prof.Profile("main_init_accountMap", time.Now().Sub(start))
   368  
   369  	// make TxPool to test validation in 'TxPool add' process
   370  	txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc)
   371  
   372  	signer := types.MakeSigner(bcdata.bc.Config(), bcdata.bc.CurrentHeader().Number)
   373  	gasPrice := new(big.Int).SetUint64(bcdata.bc.Config().UnitPrice)
   374  
   375  	// 1. Insert a value transfer transaction with nonce 0.
   376  	{
   377  		var txs types.Transactions
   378  
   379  		amount := new(big.Int).SetUint64(1000)
   380  		values := map[types.TxValueKeyType]interface{}{
   381  			types.TxValueKeyNonce:    uint64(0),
   382  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   383  			types.TxValueKeyTo:       *bcdata.addrs[0],
   384  			types.TxValueKeyAmount:   amount,
   385  			types.TxValueKeyGasLimit: gasLimit,
   386  			types.TxValueKeyGasPrice: gasPrice,
   387  		}
   388  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
   389  		assert.Equal(t, nil, err)
   390  
   391  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   392  		assert.Equal(t, nil, err)
   393  
   394  		txs = append(txs, tx)
   395  
   396  		txpool.AddRemotes(txs)
   397  
   398  		pending, queued := txpool.Content()
   399  		assert.Equal(t, 0, len(queued))
   400  		assert.Equal(t, 1, len(pending))
   401  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   402  	}
   403  
   404  	// 2. Insert a value transfer transaction with nonce 0. This should not be replaced.
   405  	{
   406  		var txs types.Transactions
   407  
   408  		pending, queued := txpool.Content()
   409  		oldtx := pending[*bcdata.addrs[0]][0]
   410  
   411  		amount := new(big.Int).SetUint64(1000)
   412  		values := map[types.TxValueKeyType]interface{}{
   413  			types.TxValueKeyNonce:    uint64(0),
   414  			types.TxValueKeyFrom:     *bcdata.addrs[0],
   415  			types.TxValueKeyTo:       *bcdata.addrs[1],
   416  			types.TxValueKeyAmount:   amount,
   417  			types.TxValueKeyGasLimit: gasLimit,
   418  			types.TxValueKeyGasPrice: gasPrice,
   419  		}
   420  		tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values)
   421  		assert.Equal(t, nil, err)
   422  
   423  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   424  		assert.Equal(t, nil, err)
   425  
   426  		txs = append(txs, tx)
   427  
   428  		txpool.AddRemotes(txs)
   429  
   430  		pending, queued = txpool.Content()
   431  		assert.Equal(t, 0, len(queued))
   432  		assert.Equal(t, 1, len(pending))
   433  		assert.True(t, oldtx.Equal(pending[*bcdata.addrs[0]][0]))
   434  	}
   435  
   436  	// 3. Insert a TxCancel transaction with nonce 0. This should replace the tx with the same nonce.
   437  	{
   438  		var txs types.Transactions
   439  
   440  		values := map[types.TxValueKeyType]interface{}{
   441  			types.TxValueKeyNonce:              uint64(0),
   442  			types.TxValueKeyFrom:               *bcdata.addrs[0],
   443  			types.TxValueKeyGasLimit:           gasLimit,
   444  			types.TxValueKeyGasPrice:           gasPrice,
   445  			types.TxValueKeyFeePayer:           *bcdata.addrs[1],
   446  			types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(30),
   447  		}
   448  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedCancelWithRatio, values)
   449  		assert.Equal(t, nil, err)
   450  
   451  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   452  		assert.Equal(t, nil, err)
   453  
   454  		err = tx.SignFeePayerWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[1]})
   455  		assert.Equal(t, nil, err)
   456  
   457  		txs = append(txs, tx)
   458  
   459  		txpool.AddRemotes(txs)
   460  
   461  		pending, queued := txpool.Content()
   462  		assert.Equal(t, 0, len(queued))
   463  		assert.Equal(t, 1, len(pending))
   464  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   465  	}
   466  
   467  	// 4. Insert a TxCancel transaction with nonce 0 and different gas limit. This should replace the tx with the same nonce.
   468  	{
   469  		var txs types.Transactions
   470  
   471  		values := map[types.TxValueKeyType]interface{}{
   472  			types.TxValueKeyNonce:              uint64(0),
   473  			types.TxValueKeyFrom:               *bcdata.addrs[0],
   474  			types.TxValueKeyGasLimit:           gasLimit + 10,
   475  			types.TxValueKeyGasPrice:           gasPrice,
   476  			types.TxValueKeyFeePayer:           *bcdata.addrs[1],
   477  			types.TxValueKeyFeeRatioOfFeePayer: types.FeeRatio(20),
   478  		}
   479  		tx, err := types.NewTransactionWithMap(types.TxTypeFeeDelegatedCancelWithRatio, values)
   480  		assert.Equal(t, nil, err)
   481  
   482  		err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[0]})
   483  		assert.Equal(t, nil, err)
   484  
   485  		err = tx.SignFeePayerWithKeys(signer, []*ecdsa.PrivateKey{bcdata.privKeys[1]})
   486  		assert.Equal(t, nil, err)
   487  
   488  		txs = append(txs, tx)
   489  
   490  		txpool.AddRemotes(txs)
   491  
   492  		pending, queued := txpool.Content()
   493  		assert.Equal(t, 0, len(queued))
   494  		assert.Equal(t, 1, len(pending))
   495  		assert.True(t, tx.Equal(pending[*bcdata.addrs[0]][0]))
   496  	}
   497  
   498  	if testing.Verbose() {
   499  		prof.PrintProfileInfo()
   500  	}
   501  }