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 }