github.com/klaytn/klaytn@v1.10.2/tests/tx_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 "errors" 22 "fmt" 23 "math/big" 24 "testing" 25 "time" 26 27 "github.com/klaytn/klaytn/blockchain" 28 "github.com/klaytn/klaytn/blockchain/types" 29 "github.com/klaytn/klaytn/blockchain/types/accountkey" 30 "github.com/klaytn/klaytn/blockchain/vm" 31 "github.com/klaytn/klaytn/common" 32 "github.com/klaytn/klaytn/common/profile" 33 "github.com/klaytn/klaytn/crypto" 34 "github.com/klaytn/klaytn/kerrors" 35 "github.com/klaytn/klaytn/log" 36 "github.com/klaytn/klaytn/params" 37 "github.com/klaytn/klaytn/rlp" 38 "github.com/stretchr/testify/assert" 39 ) 40 41 type txValueMap map[types.TxValueKeyType]interface{} 42 43 type testTxType struct { 44 name string 45 txType types.TxType 46 } 47 48 func toBasicType(txType types.TxType) types.TxType { 49 return txType &^ ((1 << types.SubTxTypeBits) - 1) 50 } 51 52 func genMapForTxTypes(from TestAccount, to TestAccount, txType types.TxType) (txValueMap, uint64) { 53 var valueMap txValueMap 54 gas := uint64(0) 55 gasPrice := big.NewInt(25 * params.Ston) 56 newAccount, err := createDefaultAccount(accountkey.AccountKeyTypePublic) 57 if err != nil { 58 return nil, 0 59 } 60 61 // switch to basic tx type representation and generate a map 62 switch toBasicType(txType) { 63 case types.TxTypeLegacyTransaction: 64 valueMap, gas = genMapForLegacyTransaction(from, to, gasPrice, txType) 65 case types.TxTypeValueTransfer: 66 valueMap, gas = genMapForValueTransfer(from, to, gasPrice, txType) 67 case types.TxTypeValueTransferMemo: 68 valueMap, gas = genMapForValueTransferWithMemo(from, to, gasPrice, txType) 69 case types.TxTypeAccountUpdate: 70 valueMap, gas = genMapForUpdate(from, to, gasPrice, newAccount.AccKey, txType) 71 case types.TxTypeSmartContractDeploy: 72 valueMap, gas = genMapForDeploy(from, nil, gasPrice, txType) 73 case types.TxTypeSmartContractExecution: 74 valueMap, gas = genMapForExecution(from, to, gasPrice, txType) 75 case types.TxTypeCancel: 76 valueMap, gas = genMapForCancel(from, gasPrice, txType) 77 case types.TxTypeChainDataAnchoring: 78 valueMap, gas = genMapForChainDataAnchoring(from, gasPrice, txType) 79 } 80 81 if txType.IsFeeDelegatedTransaction() { 82 valueMap[types.TxValueKeyFeePayer] = from.GetAddr() 83 } 84 85 if txType.IsFeeDelegatedWithRatioTransaction() { 86 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(30) 87 } 88 89 if txType == types.TxTypeEthereumAccessList { 90 valueMap, gas = genMapForAccessListTransaction(from, to, gasPrice, txType) 91 } 92 93 if txType == types.TxTypeEthereumDynamicFee { 94 valueMap, gas = genMapForDynamicFeeTransaction(from, to, gasPrice, txType) 95 } 96 97 return valueMap, gas 98 } 99 100 // TestValidationPoolInsert generates invalid txs which will be invalidated during txPool insert process. 101 func TestValidationPoolInsert(t *testing.T) { 102 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 103 104 testTxTypes := []testTxType{} 105 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 106 if i == types.TxTypeKlaytnLast { 107 i = types.TxTypeEthereumAccessList 108 } 109 110 _, err := types.NewTxInternalData(i) 111 if err == nil { 112 testTxTypes = append(testTxTypes, testTxType{i.String(), i}) 113 } 114 } 115 116 invalidCases := []struct { 117 Name string 118 fn func(types.TxType, txValueMap, common.Address) (txValueMap, error) 119 }{ 120 {"invalidNonce", decreaseNonce}, 121 {"invalidGasPrice", decreaseGasPrice}, 122 {"invalidTxSize", exceedSizeLimit}, 123 {"invalidRecipientProgram", valueTransferToContract}, 124 {"invalidRecipientNotProgram", executeToEOA}, 125 {"invalidCodeFormat", invalidCodeFormat}, 126 } 127 128 prof := profile.NewProfiler() 129 130 // Initialize blockchain 131 bcdata, err := NewBCData(6, 4) 132 if err != nil { 133 t.Fatal(err) 134 } 135 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 136 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 137 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 138 defer bcdata.Shutdown() 139 140 // Initialize address-balance map for verification 141 accountMap := NewAccountMap() 142 if err := accountMap.Initialize(bcdata); err != nil { 143 t.Fatal(err) 144 } 145 146 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 147 148 // reservoir account 149 reservoir := &TestAccountType{ 150 Addr: *bcdata.addrs[0], 151 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 152 Nonce: uint64(0), 153 } 154 155 // for contract execution txs 156 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 157 assert.Equal(t, nil, err) 158 159 // deploy a contract for contract execution tx type 160 { 161 var txs types.Transactions 162 163 values := map[types.TxValueKeyType]interface{}{ 164 types.TxValueKeyNonce: reservoir.GetNonce(), 165 types.TxValueKeyFrom: reservoir.GetAddr(), 166 types.TxValueKeyTo: (*common.Address)(nil), 167 types.TxValueKeyAmount: big.NewInt(0), 168 types.TxValueKeyGasLimit: gasLimit, 169 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 170 types.TxValueKeyHumanReadable: false, 171 types.TxValueKeyData: common.FromHex(code), 172 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 173 } 174 175 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 176 assert.Equal(t, nil, err) 177 178 err = tx.SignWithKeys(signer, reservoir.Keys) 179 assert.Equal(t, nil, err) 180 181 txs = append(txs, tx) 182 183 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 184 t.Fatal(err) 185 } 186 187 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 188 189 reservoir.AddNonce() 190 } 191 192 // make TxPool to test validation in 'TxPool add' process 193 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 194 195 // test for all tx types 196 for _, testTxType := range testTxTypes { 197 txType := testTxType.txType 198 199 // generate invalid txs and check the return error 200 for _, invalidCase := range invalidCases { 201 to := reservoir 202 if toBasicType(testTxType.txType) == types.TxTypeSmartContractExecution { 203 to = contract 204 } 205 206 // generate a new tx and mutate it 207 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 208 invalidMap, expectedErr := invalidCase.fn(txType, valueMap, contract.Addr) 209 210 tx, err := types.NewTransactionWithMap(txType, invalidMap) 211 assert.Equal(t, nil, err) 212 213 err = tx.SignWithKeys(signer, reservoir.Keys) 214 assert.Equal(t, nil, err) 215 216 if txType.IsFeeDelegatedTransaction() { 217 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 218 assert.Equal(t, nil, err) 219 } 220 221 err = txpool.AddRemote(tx) 222 assert.Equal(t, expectedErr, err) 223 if expectedErr == nil { 224 reservoir.Nonce += 1 225 } 226 } 227 } 228 } 229 230 func TestValidationPoolInsertMagma(t *testing.T) { 231 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 232 233 testTxTypes := []testTxType{} 234 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 235 if i == types.TxTypeKlaytnLast { 236 i = types.TxTypeEthereumAccessList 237 } 238 239 _, err := types.NewTxInternalData(i) 240 if err == nil { 241 testTxTypes = append(testTxTypes, testTxType{i.String(), i}) 242 } 243 } 244 245 invalidCases := []struct { 246 Name string 247 fn func(types.TxType, txValueMap, common.Address) (txValueMap, error) 248 }{ 249 {"invalidGasPrice", decreaseGasPriceMagma}, 250 } 251 252 prof := profile.NewProfiler() 253 254 // Initialize blockchain 255 bcdata, err := NewBCData(6, 4) 256 if err != nil { 257 t.Fatal(err) 258 } 259 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 260 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 261 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 262 bcdata.bc.Config().MagmaCompatibleBlock = big.NewInt(0) 263 defer bcdata.Shutdown() 264 265 // Initialize address-balance map for verification 266 accountMap := NewAccountMap() 267 if err := accountMap.Initialize(bcdata); err != nil { 268 t.Fatal(err) 269 } 270 271 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 272 273 // reservoir account 274 reservoir := &TestAccountType{ 275 Addr: *bcdata.addrs[0], 276 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 277 Nonce: uint64(0), 278 } 279 280 // for contract execution txs 281 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 282 assert.Equal(t, nil, err) 283 284 // deploy a contract for contract execution tx type 285 { 286 var txs types.Transactions 287 288 values := map[types.TxValueKeyType]interface{}{ 289 types.TxValueKeyNonce: reservoir.GetNonce(), 290 types.TxValueKeyFrom: reservoir.GetAddr(), 291 types.TxValueKeyTo: (*common.Address)(nil), 292 types.TxValueKeyAmount: big.NewInt(0), 293 types.TxValueKeyGasLimit: gasLimit, 294 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 295 types.TxValueKeyHumanReadable: false, 296 types.TxValueKeyData: common.FromHex(code), 297 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 298 } 299 300 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 301 assert.Equal(t, nil, err) 302 303 err = tx.SignWithKeys(signer, reservoir.Keys) 304 assert.Equal(t, nil, err) 305 306 txs = append(txs, tx) 307 308 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 309 t.Fatal(err) 310 } 311 312 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 313 314 reservoir.AddNonce() 315 } 316 317 // make TxPool to test validation in 'TxPool add' process 318 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 319 320 // test for all tx types 321 for _, testTxType := range testTxTypes { 322 txType := testTxType.txType 323 324 // generate invalid txs and check the return error 325 for _, invalidCase := range invalidCases { 326 to := reservoir 327 if toBasicType(testTxType.txType) == types.TxTypeSmartContractExecution { 328 to = contract 329 } 330 331 // generate a new tx and mutate it 332 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 333 invalidMap, expectedErr := invalidCase.fn(txType, valueMap, contract.Addr) 334 335 tx, err := types.NewTransactionWithMap(txType, invalidMap) 336 assert.Equal(t, nil, err) 337 338 err = tx.SignWithKeys(signer, reservoir.Keys) 339 assert.Equal(t, nil, err) 340 341 if txType.IsFeeDelegatedTransaction() { 342 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 343 assert.Equal(t, nil, err) 344 } 345 346 err = txpool.AddRemote(tx) 347 assert.Equal(t, expectedErr, err) 348 if expectedErr == nil { 349 reservoir.Nonce += 1 350 } 351 } 352 } 353 } 354 355 // TestValidationBlockTx generates invalid txs which will be invalidated during block insert process. 356 func TestValidationBlockTx(t *testing.T) { 357 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 358 359 testTxTypes := []testTxType{} 360 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 361 if i == types.TxTypeKlaytnLast { 362 i = types.TxTypeEthereumAccessList 363 } 364 365 _, err := types.NewTxInternalData(i) 366 if err == nil { 367 testTxTypes = append(testTxTypes, testTxType{i.String(), i}) 368 } 369 } 370 371 invalidCases := []struct { 372 Name string 373 fn func(types.TxType, txValueMap, common.Address) (txValueMap, error) 374 }{ 375 {"invalidNonce", decreaseNonce}, 376 {"invalidRecipientProgram", valueTransferToContract}, 377 {"invalidRecipientNotProgram", executeToEOA}, 378 {"invalidCodeFormat", invalidCodeFormat}, 379 } 380 381 prof := profile.NewProfiler() 382 383 // Initialize blockchain 384 bcdata, err := NewBCData(6, 4) 385 if err != nil { 386 t.Fatal(err) 387 } 388 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 389 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 390 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 391 defer bcdata.Shutdown() 392 393 // Initialize address-balance map for verification 394 accountMap := NewAccountMap() 395 if err := accountMap.Initialize(bcdata); err != nil { 396 t.Fatal(err) 397 } 398 399 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 400 401 // reservoir account 402 reservoir := &TestAccountType{ 403 Addr: *bcdata.addrs[0], 404 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 405 Nonce: uint64(0), 406 } 407 408 // for contract execution txs 409 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 410 assert.Equal(t, nil, err) 411 412 // deploy a contract for contract execution tx type 413 { 414 var txs types.Transactions 415 416 values := map[types.TxValueKeyType]interface{}{ 417 types.TxValueKeyNonce: reservoir.GetNonce(), 418 types.TxValueKeyFrom: reservoir.GetAddr(), 419 types.TxValueKeyTo: (*common.Address)(nil), 420 types.TxValueKeyAmount: big.NewInt(0), 421 types.TxValueKeyGasLimit: gasLimit, 422 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 423 types.TxValueKeyHumanReadable: false, 424 types.TxValueKeyData: common.FromHex(code), 425 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 426 } 427 428 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 429 assert.Equal(t, nil, err) 430 431 err = tx.SignWithKeys(signer, reservoir.Keys) 432 assert.Equal(t, nil, err) 433 434 txs = append(txs, tx) 435 436 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 437 t.Fatal(err) 438 } 439 440 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 441 442 reservoir.AddNonce() 443 } 444 445 // test for all tx types 446 for _, testTxType := range testTxTypes { 447 txType := testTxType.txType 448 449 // generate invalid txs and check the return error 450 for _, invalidCase := range invalidCases { 451 to := reservoir 452 if toBasicType(testTxType.txType) == types.TxTypeSmartContractExecution { 453 to = contract 454 } 455 // generate a new tx and mutate it 456 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 457 invalidMap, expectedErr := invalidCase.fn(txType, valueMap, contract.Addr) 458 459 tx, err := types.NewTransactionWithMap(txType, invalidMap) 460 assert.Equal(t, nil, err) 461 462 err = tx.SignWithKeys(signer, reservoir.Keys) 463 assert.Equal(t, nil, err) 464 465 if txType.IsFeeDelegatedTransaction() { 466 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 467 assert.Equal(t, nil, err) 468 } 469 470 receipt, err := applyTransaction(t, bcdata, tx) 471 assert.Equal(t, expectedErr, err) 472 if expectedErr == nil { 473 assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 474 } 475 } 476 } 477 } 478 479 // decreaseNonce changes nonce to zero. 480 func decreaseNonce(txType types.TxType, values txValueMap, contract common.Address) (txValueMap, error) { 481 values[types.TxValueKeyNonce] = uint64(0) 482 483 return values, blockchain.ErrNonceTooLow 484 } 485 486 // decreaseGasPrice changes gasPrice to 12345678 487 func decreaseGasPrice(txType types.TxType, values txValueMap, contract common.Address) (txValueMap, error) { 488 var err error 489 if txType == types.TxTypeEthereumDynamicFee { 490 (*big.Int).SetUint64(values[types.TxValueKeyGasFeeCap].(*big.Int), 12345678) 491 (*big.Int).SetUint64(values[types.TxValueKeyGasTipCap].(*big.Int), 12345678) 492 err = blockchain.ErrInvalidGasTipCap 493 } else { 494 (*big.Int).SetUint64(values[types.TxValueKeyGasPrice].(*big.Int), 12345678) 495 err = blockchain.ErrInvalidUnitPrice 496 497 } 498 499 return values, err 500 } 501 502 // decreaseGasPrice changes gasPrice to 12345678 and return an error with magma policy 503 func decreaseGasPriceMagma(txType types.TxType, values txValueMap, contract common.Address) (txValueMap, error) { 504 var err error 505 if txType == types.TxTypeEthereumDynamicFee { 506 (*big.Int).SetUint64(values[types.TxValueKeyGasFeeCap].(*big.Int), 12345678) 507 (*big.Int).SetUint64(values[types.TxValueKeyGasTipCap].(*big.Int), 12345678) 508 err = blockchain.ErrFeeCapBelowBaseFee 509 } else { 510 (*big.Int).SetUint64(values[types.TxValueKeyGasPrice].(*big.Int), 12345678) 511 err = blockchain.ErrGasPriceBelowBaseFee 512 } 513 514 return values, err 515 } 516 517 // exceedSizeLimit assigns tx data bigger than MaxTxDataSize. 518 func exceedSizeLimit(txType types.TxType, values txValueMap, contract common.Address) (txValueMap, error) { 519 invalidData := make([]byte, blockchain.MaxTxDataSize+1) 520 521 if values[types.TxValueKeyData] != nil { 522 values[types.TxValueKeyData] = invalidData 523 return values, blockchain.ErrOversizedData 524 } 525 526 if values[types.TxValueKeyAnchoredData] != nil { 527 values[types.TxValueKeyAnchoredData] = invalidData 528 return values, blockchain.ErrOversizedData 529 } 530 531 return values, nil 532 } 533 534 // valueTransferToContract changes recipient address of value transfer txs to the contract address. 535 func valueTransferToContract(txType types.TxType, values txValueMap, contract common.Address) (txValueMap, error) { 536 txType = toBasicType(txType) 537 if txType == types.TxTypeValueTransfer || txType == types.TxTypeValueTransferMemo { 538 values[types.TxValueKeyTo] = contract 539 return values, kerrors.ErrNotForProgramAccount 540 } 541 542 return values, nil 543 } 544 545 // executeToEOA changes the recipient of contract execution txs to an EOA address (the same with the sender). 546 func executeToEOA(txType types.TxType, values txValueMap, contract common.Address) (txValueMap, error) { 547 if toBasicType(txType) == types.TxTypeSmartContractExecution { 548 values[types.TxValueKeyTo] = values[types.TxValueKeyFrom].(common.Address) 549 return values, kerrors.ErrNotProgramAccount 550 } 551 552 return values, nil 553 } 554 555 func invalidCodeFormat(txType types.TxType, values txValueMap, contract common.Address) (txValueMap, error) { 556 if txType.IsContractDeploy() { 557 values[types.TxValueKeyCodeFormat] = params.CodeFormatLast 558 return values, kerrors.ErrInvalidCodeFormat 559 } 560 return values, nil 561 } 562 563 // TestValidationInvalidSig generates txs signed by an invalid sender or a fee payer. 564 func TestValidationInvalidSig(t *testing.T) { 565 testTxTypes := []testTxType{} 566 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 567 if i == types.TxTypeKlaytnLast { 568 i = types.TxTypeEthereumAccessList 569 } 570 571 _, err := types.NewTxInternalData(i) 572 if err == nil { 573 testTxTypes = append(testTxTypes, testTxType{i.String(), i}) 574 } 575 } 576 577 invalidCases := []struct { 578 Name string 579 fn func(*testing.T, types.TxType, *TestAccountType, *TestAccountType, types.Signer) (*types.Transaction, error) 580 }{ 581 {"invalidSender", testInvalidSenderSig}, 582 {"invalidFeePayer", testInvalidFeePayerSig}, 583 } 584 585 prof := profile.NewProfiler() 586 587 // Initialize blockchain 588 bcdata, err := NewBCData(6, 4) 589 if err != nil { 590 t.Fatal(err) 591 } 592 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 593 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 594 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 595 defer bcdata.Shutdown() 596 597 // Initialize address-balance map for verification 598 accountMap := NewAccountMap() 599 if err := accountMap.Initialize(bcdata); err != nil { 600 t.Fatal(err) 601 } 602 603 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 604 605 // reservoir account 606 reservoir := &TestAccountType{ 607 Addr: *bcdata.addrs[0], 608 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 609 Nonce: uint64(0), 610 } 611 612 // for contract execution txs 613 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 614 assert.Equal(t, nil, err) 615 616 // deploy a contract for contract execution tx type 617 { 618 var txs types.Transactions 619 620 values := map[types.TxValueKeyType]interface{}{ 621 types.TxValueKeyNonce: reservoir.GetNonce(), 622 types.TxValueKeyFrom: reservoir.GetAddr(), 623 types.TxValueKeyTo: (*common.Address)(nil), 624 types.TxValueKeyAmount: big.NewInt(0), 625 types.TxValueKeyGasLimit: gasLimit, 626 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 627 types.TxValueKeyHumanReadable: false, 628 types.TxValueKeyData: common.FromHex(code), 629 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 630 } 631 632 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 633 assert.Equal(t, nil, err) 634 635 err = tx.SignWithKeys(signer, reservoir.Keys) 636 assert.Equal(t, nil, err) 637 638 txs = append(txs, tx) 639 640 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 641 t.Fatal(err) 642 } 643 644 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 645 646 reservoir.AddNonce() 647 } 648 649 // make TxPool to test validation in 'TxPool add' process 650 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 651 652 // test for all tx types 653 for _, testTxType := range testTxTypes { 654 txType := testTxType.txType 655 656 for _, invalidCase := range invalidCases { 657 tx, expectedErr := invalidCase.fn(t, txType, reservoir, contract, signer) 658 659 if tx != nil { 660 // For tx pool validation test 661 err = txpool.AddRemote(tx) 662 assert.Equal(t, expectedErr, err) 663 664 // For block tx validation test 665 if expectedErr == blockchain.ErrInvalidFeePayer { 666 expectedErr = types.ErrInvalidSigFeePayer 667 } 668 receipt, err := applyTransaction(t, bcdata, tx) 669 assert.Equal(t, expectedErr, err) 670 assert.Equal(t, (*types.Receipt)(nil), receipt) 671 } 672 } 673 } 674 } 675 676 // testInvalidSenderSig generates invalid txs signed by an invalid sender. 677 func testInvalidSenderSig(t *testing.T, txType types.TxType, reservoir *TestAccountType, contract *TestAccountType, signer types.Signer) (*types.Transaction, error) { 678 if !txType.IsLegacyTransaction() && !txType.IsEthTypedTransaction() { 679 newAcc, err := createDefaultAccount(accountkey.AccountKeyTypePublic) 680 assert.Equal(t, nil, err) 681 682 to := reservoir 683 if toBasicType(txType) == types.TxTypeSmartContractExecution { 684 to = contract 685 } 686 687 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 688 tx, err := types.NewTransactionWithMap(txType, valueMap) 689 assert.Equal(t, nil, err) 690 691 err = tx.SignWithKeys(signer, newAcc.Keys) 692 assert.Equal(t, nil, err) 693 694 if txType.IsFeeDelegatedTransaction() { 695 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 696 assert.Equal(t, nil, err) 697 } 698 return tx, types.ErrInvalidSigSender 699 } 700 return nil, nil 701 } 702 703 // testInvalidFeePayerSig generates invalid txs signed by an invalid fee payer. 704 func testInvalidFeePayerSig(t *testing.T, txType types.TxType, reservoir *TestAccountType, contract *TestAccountType, signer types.Signer) (*types.Transaction, error) { 705 if txType.IsFeeDelegatedTransaction() { 706 newAcc, err := createDefaultAccount(accountkey.AccountKeyTypePublic) 707 assert.Equal(t, nil, err) 708 709 to := reservoir 710 if toBasicType(txType) == types.TxTypeSmartContractExecution { 711 to = contract 712 } 713 714 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 715 tx, err := types.NewTransactionWithMap(txType, valueMap) 716 assert.Equal(t, nil, err) 717 718 err = tx.SignWithKeys(signer, reservoir.Keys) 719 assert.Equal(t, nil, err) 720 721 tx.SignFeePayerWithKeys(signer, newAcc.Keys) 722 assert.Equal(t, nil, err) 723 724 return tx, blockchain.ErrInvalidFeePayer 725 } 726 return nil, nil 727 } 728 729 // TestLegacyTxFromNonLegacyAcc generates legacy tx from non-legacy account, and it will be invalidated during txPool insert process. 730 func TestLegacyTxFromNonLegacyAcc(t *testing.T) { 731 prof := profile.NewProfiler() 732 733 // Initialize blockchain 734 bcdata, err := NewBCData(6, 4) 735 if err != nil { 736 t.Fatal(err) 737 } 738 defer bcdata.Shutdown() 739 740 // Initialize address-balance map for verification 741 accountMap := NewAccountMap() 742 if err := accountMap.Initialize(bcdata); err != nil { 743 t.Fatal(err) 744 } 745 746 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 747 748 // reservoir account 749 reservoir := &TestAccountType{ 750 Addr: *bcdata.addrs[0], 751 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 752 Nonce: uint64(0), 753 } 754 755 var txs types.Transactions 756 acc1, err := createDefaultAccount(accountkey.AccountKeyTypePublic) 757 758 valueMap, _ := genMapForTxTypes(reservoir, reservoir, types.TxTypeAccountUpdate) 759 valueMap[types.TxValueKeyAccountKey] = acc1.AccKey 760 761 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, valueMap) 762 assert.Equal(t, nil, err) 763 764 err = tx.SignWithKeys(signer, reservoir.Keys) 765 assert.Equal(t, nil, err) 766 767 txs = append(txs, tx) 768 769 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 770 t.Fatal(err) 771 } 772 reservoir.AddNonce() 773 774 // make TxPool to test validation in 'TxPool add' process 775 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 776 777 valueMap, _ = genMapForTxTypes(reservoir, reservoir, types.TxTypeLegacyTransaction) 778 tx, err = types.NewTransactionWithMap(types.TxTypeLegacyTransaction, valueMap) 779 assert.Equal(t, nil, err) 780 781 err = tx.SignWithKeys(signer, reservoir.Keys) 782 assert.Equal(t, nil, err) 783 784 err = txpool.AddRemote(tx) 785 assert.Equal(t, kerrors.ErrLegacyTransactionMustBeWithLegacyKey, err) 786 } 787 788 // TestInvalidBalance generates invalid txs which don't have enough KLAY, and will be invalidated during txPool insert process. 789 func TestInvalidBalance(t *testing.T) { 790 testTxTypes := []testTxType{} 791 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 792 if i == types.TxTypeKlaytnLast { 793 i = types.TxTypeEthereumAccessList 794 } 795 796 _, err := types.NewTxInternalData(i) 797 if err == nil { 798 testTxTypes = append(testTxTypes, testTxType{i.String(), i}) 799 } 800 } 801 802 prof := profile.NewProfiler() 803 804 // Initialize blockchain 805 bcdata, err := NewBCData(6, 4) 806 if err != nil { 807 t.Fatal(err) 808 } 809 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 810 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 811 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 812 defer bcdata.Shutdown() 813 814 // Initialize address-balance map for verification 815 accountMap := NewAccountMap() 816 if err := accountMap.Initialize(bcdata); err != nil { 817 t.Fatal(err) 818 } 819 820 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 821 822 // reservoir account 823 reservoir := &TestAccountType{ 824 Addr: *bcdata.addrs[0], 825 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 826 Nonce: uint64(0), 827 } 828 829 // for contract execution txs 830 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 831 assert.Equal(t, nil, err) 832 833 // test account will be lack of KLAY 834 testAcc, err := createDefaultAccount(accountkey.AccountKeyTypeLegacy) 835 assert.Equal(t, nil, err) 836 837 gasLimit := uint64(100000000000) 838 gasPrice := big.NewInt(25 * params.Ston) 839 amount := uint64(25 * params.Ston) 840 cost := new(big.Int).Mul(new(big.Int).SetUint64(gasLimit), gasPrice) 841 cost.Add(cost, new(big.Int).SetUint64(amount)) 842 843 // deploy a contract for contract execution tx type 844 { 845 var txs types.Transactions 846 847 values := map[types.TxValueKeyType]interface{}{ 848 types.TxValueKeyNonce: reservoir.GetNonce(), 849 types.TxValueKeyFrom: reservoir.GetAddr(), 850 types.TxValueKeyTo: (*common.Address)(nil), 851 types.TxValueKeyAmount: big.NewInt(0), 852 types.TxValueKeyGasLimit: gasLimit, 853 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 854 types.TxValueKeyHumanReadable: false, 855 types.TxValueKeyData: common.FromHex(code), 856 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 857 } 858 859 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 860 assert.Equal(t, nil, err) 861 862 err = tx.SignWithKeys(signer, reservoir.Keys) 863 assert.Equal(t, nil, err) 864 865 txs = append(txs, tx) 866 867 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 868 t.Fatal(err) 869 } 870 871 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 872 873 reservoir.AddNonce() 874 } 875 876 // generate a test account with a specific amount of KLAY 877 { 878 var txs types.Transactions 879 880 valueMapForCreation, _ := genMapForTxTypes(reservoir, testAcc, types.TxTypeValueTransfer) 881 valueMapForCreation[types.TxValueKeyAmount] = cost 882 883 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, valueMapForCreation) 884 assert.Equal(t, nil, err) 885 886 err = tx.SignWithKeys(signer, reservoir.Keys) 887 assert.Equal(t, nil, err) 888 889 txs = append(txs, tx) 890 891 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 892 t.Fatal(err) 893 } 894 reservoir.AddNonce() 895 } 896 897 // make TxPool to test validation in 'TxPool add' process 898 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 899 900 // test for all tx types 901 for _, testTxType := range testTxTypes { 902 txType := testTxType.txType 903 904 if !txType.IsFeeDelegatedTransaction() { 905 // tx with a specific amount or a gasLimit requiring more KLAY than the sender has. 906 { 907 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 908 if toBasicType(txType) == types.TxTypeSmartContractExecution { 909 valueMap[types.TxValueKeyTo] = contract.Addr 910 } 911 if valueMap[types.TxValueKeyAmount] != nil { 912 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 913 valueMap[types.TxValueKeyGasLimit] = gasLimit + 1 // requires 1 more gas 914 } else { 915 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) + 1 // requires 1 more gas 916 } 917 918 tx, err := types.NewTransactionWithMap(txType, valueMap) 919 assert.Equal(t, nil, err) 920 921 err = tx.SignWithKeys(signer, testAcc.Keys) 922 assert.Equal(t, nil, err) 923 924 err = txpool.AddRemote(tx) 925 assert.Equal(t, blockchain.ErrInsufficientFundsFrom, err) 926 } 927 928 // tx with a specific amount or a gasLimit requiring the exact KLAY the sender has. 929 { 930 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 931 if toBasicType(txType) == types.TxTypeSmartContractExecution { 932 valueMap[types.TxValueKeyTo] = contract.Addr 933 } 934 if valueMap[types.TxValueKeyAmount] != nil { 935 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 936 valueMap[types.TxValueKeyGasLimit] = gasLimit 937 } else { 938 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) 939 } 940 941 tx, err := types.NewTransactionWithMap(txType, valueMap) 942 assert.Equal(t, nil, err) 943 944 err = tx.SignWithKeys(signer, testAcc.Keys) 945 assert.Equal(t, nil, err) 946 947 // Since `txpool.AddRemote` does not make a block, 948 // the sender can send txs to txpool in multiple times (by the for loop) with limited KLAY. 949 err = txpool.AddRemote(tx) 950 assert.Equal(t, nil, err) 951 testAcc.AddNonce() 952 } 953 } 954 955 if txType.IsFeeDelegatedTransaction() && !txType.IsFeeDelegatedWithRatioTransaction() { 956 // tx with a specific amount requiring more KLAY than the sender has. 957 { 958 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 959 if toBasicType(txType) == types.TxTypeSmartContractExecution { 960 valueMap[types.TxValueKeyTo] = contract.Addr 961 } 962 if valueMap[types.TxValueKeyAmount] != nil { 963 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 964 valueMap[types.TxValueKeyAmount] = new(big.Int).Add(cost, new(big.Int).SetUint64(1)) // requires 1 more amount 965 966 tx, err := types.NewTransactionWithMap(txType, valueMap) 967 assert.Equal(t, nil, err) 968 969 err = tx.SignWithKeys(signer, testAcc.Keys) 970 assert.Equal(t, nil, err) 971 972 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 973 assert.Equal(t, nil, err) 974 975 err = txpool.AddRemote(tx) 976 assert.Equal(t, blockchain.ErrInsufficientFundsFrom, err) 977 } 978 } 979 980 // tx with a specific gasLimit (or amount) requiring more KLAY than the feePayer has. 981 { 982 valueMap, _ := genMapForTxTypes(reservoir, testAcc, txType) 983 if toBasicType(txType) == types.TxTypeSmartContractExecution { 984 valueMap[types.TxValueKeyTo] = contract.Addr 985 } 986 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 987 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) + 1 // requires 1 more gas 988 989 tx, err := types.NewTransactionWithMap(txType, valueMap) 990 assert.Equal(t, nil, err) 991 992 err = tx.SignWithKeys(signer, reservoir.Keys) 993 assert.Equal(t, nil, err) 994 995 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 996 assert.Equal(t, nil, err) 997 998 err = txpool.AddRemote(tx) 999 assert.Equal(t, blockchain.ErrInsufficientFundsFeePayer, err) 1000 } 1001 1002 // tx with a specific amount requiring the exact KLAY the sender has. 1003 { 1004 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1005 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1006 valueMap[types.TxValueKeyTo] = contract.Addr 1007 } 1008 if valueMap[types.TxValueKeyAmount] != nil { 1009 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 1010 valueMap[types.TxValueKeyAmount] = cost 1011 1012 tx, err := types.NewTransactionWithMap(txType, valueMap) 1013 assert.Equal(t, nil, err) 1014 1015 err = tx.SignWithKeys(signer, testAcc.Keys) 1016 assert.Equal(t, nil, err) 1017 1018 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1019 assert.Equal(t, nil, err) 1020 1021 // Since `txpool.AddRemote` does not make a block, 1022 // the sender can send txs to txpool in multiple times (by the for loop) with limited KLAY. 1023 err = txpool.AddRemote(tx) 1024 assert.Equal(t, nil, err) 1025 testAcc.AddNonce() 1026 } 1027 } 1028 1029 // tx with a specific gasLimit (or amount) requiring the exact KLAY the feePayer has. 1030 { 1031 valueMap, _ := genMapForTxTypes(reservoir, testAcc, txType) 1032 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1033 valueMap[types.TxValueKeyTo] = contract.Addr 1034 } 1035 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 1036 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) 1037 1038 tx, err := types.NewTransactionWithMap(txType, valueMap) 1039 assert.Equal(t, nil, err) 1040 1041 err = tx.SignWithKeys(signer, reservoir.Keys) 1042 assert.Equal(t, nil, err) 1043 1044 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 1045 assert.Equal(t, nil, err) 1046 1047 // Since `txpool.AddRemote` does not make a block, 1048 // the sender can send txs to txpool in multiple times (by the for loop) with limited KLAY. 1049 err = txpool.AddRemote(tx) 1050 assert.Equal(t, nil, err) 1051 reservoir.AddNonce() 1052 } 1053 } 1054 1055 if txType.IsFeeDelegatedWithRatioTransaction() { 1056 // tx with a specific amount and a gasLimit requiring more KLAY than the sender has. 1057 { 1058 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1059 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1060 valueMap[types.TxValueKeyTo] = contract.Addr 1061 } 1062 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 1063 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(90) 1064 if valueMap[types.TxValueKeyAmount] != nil { 1065 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 1066 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1067 // = (gasLimit + 1) * 10 * (100 - 90) * 0.01 = gasLimit + 1 1068 valueMap[types.TxValueKeyGasLimit] = (gasLimit + 1) * 10 // requires 1 more gas 1069 } else { 1070 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1071 // = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 * (100 - 90) * 0.01 = gasLimit + (amount / gasPrice.Uint64()) + 1 1072 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 // requires 1 more gas 1073 } 1074 1075 tx, err := types.NewTransactionWithMap(txType, valueMap) 1076 assert.Equal(t, nil, err) 1077 1078 err = tx.SignWithKeys(signer, testAcc.Keys) 1079 assert.Equal(t, nil, err) 1080 1081 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1082 assert.Equal(t, nil, err) 1083 1084 err = txpool.AddRemote(tx) 1085 assert.Equal(t, blockchain.ErrInsufficientFundsFrom, err) 1086 } 1087 1088 // tx with a specific amount and a gasLimit requiring more KLAY than the feePayer has. 1089 { 1090 valueMap, _ := genMapForTxTypes(reservoir, testAcc, txType) 1091 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1092 valueMap[types.TxValueKeyTo] = contract.Addr 1093 } 1094 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 1095 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(10) 1096 // Gas testAcc will charge = tx gasLimit * fee-payer's feeRatio 1097 // = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 * 10 * 0.01 = gasLimit + (amount / gasPrice.Uint64()) + 1 1098 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 // requires 1 more gas 1099 1100 tx, err := types.NewTransactionWithMap(txType, valueMap) 1101 assert.Equal(t, nil, err) 1102 1103 err = tx.SignWithKeys(signer, reservoir.Keys) 1104 assert.Equal(t, nil, err) 1105 1106 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 1107 assert.Equal(t, nil, err) 1108 1109 err = txpool.AddRemote(tx) 1110 assert.Equal(t, blockchain.ErrInsufficientFundsFeePayer, err) 1111 } 1112 1113 // tx with a specific amount and a gasLimit requiring the exact KLAY the sender has. 1114 { 1115 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1116 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1117 valueMap[types.TxValueKeyTo] = contract.Addr 1118 } 1119 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 1120 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(90) 1121 if valueMap[types.TxValueKeyAmount] != nil { 1122 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 1123 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1124 // = gasLimit * 10 * (100 - 90) * 0.01 = gasLimit 1125 valueMap[types.TxValueKeyGasLimit] = gasLimit * 10 1126 } else { 1127 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1128 // = (gasLimit + (amount / gasPrice.Uint64())) * 10 * (100 - 90) * 0.01 = gasLimit + (amount / gasPrice.Uint64()) 1129 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64())) * 10 1130 } 1131 1132 tx, err := types.NewTransactionWithMap(txType, valueMap) 1133 assert.Equal(t, nil, err) 1134 1135 err = tx.SignWithKeys(signer, testAcc.Keys) 1136 assert.Equal(t, nil, err) 1137 1138 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1139 assert.Equal(t, nil, err) 1140 1141 // Since `txpool.AddRemote` does not make a block, 1142 // the sender can send txs to txpool in multiple times (by the for loop) with limited KLAY. 1143 err = txpool.AddRemote(tx) 1144 assert.Equal(t, nil, err) 1145 testAcc.AddNonce() 1146 } 1147 1148 // tx with a specific amount and a gasLimit requiring the exact KLAY the feePayer has. 1149 { 1150 valueMap, _ := genMapForTxTypes(reservoir, testAcc, txType) 1151 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1152 valueMap[types.TxValueKeyTo] = contract.Addr 1153 } 1154 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 1155 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(10) 1156 // Gas testAcc will charge = tx gasLimit * fee-payer's feeRatio 1157 // = (gasLimit + (amount / gasPrice.Uint64())) * 10 * 10 * 0.01 = gasLimit + (amount / gasPrice.Uint64()) 1158 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64())) * 10 1159 1160 tx, err := types.NewTransactionWithMap(txType, valueMap) 1161 assert.Equal(t, nil, err) 1162 1163 err = tx.SignWithKeys(signer, reservoir.Keys) 1164 assert.Equal(t, nil, err) 1165 1166 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 1167 assert.Equal(t, nil, err) 1168 1169 // Since `txpool.AddRemote` does not make a block, 1170 // the sender can send txs to txpool in multiple times (by the for loop) with limited KLAY. 1171 err = txpool.AddRemote(tx) 1172 assert.Equal(t, nil, err) 1173 reservoir.AddNonce() 1174 } 1175 } 1176 } 1177 } 1178 1179 // TestInvalidBalanceBlockTx generates invalid txs which don't have enough KLAY, and will be invalidated during block insert process. 1180 func TestInvalidBalanceBlockTx(t *testing.T) { 1181 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 1182 1183 testTxTypes := []testTxType{} 1184 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 1185 if i == types.TxTypeKlaytnLast { 1186 i = types.TxTypeEthereumAccessList 1187 } 1188 1189 _, err := types.NewTxInternalData(i) 1190 if err == nil { 1191 testTxTypes = append(testTxTypes, testTxType{i.String(), i}) 1192 } 1193 } 1194 1195 // re-declare errors since those errors are private variables in 'blockchain' package. 1196 errInsufficientBalanceForGas := errors.New("insufficient balance of the sender to pay for gas") 1197 errInsufficientBalanceForGasFeePayer := errors.New("insufficient balance of the fee payer to pay for gas") 1198 1199 prof := profile.NewProfiler() 1200 1201 // Initialize blockchain 1202 bcdata, err := NewBCData(6, 4) 1203 if err != nil { 1204 t.Fatal(err) 1205 } 1206 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 1207 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 1208 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 1209 defer bcdata.Shutdown() 1210 1211 // Initialize address-balance map for verification 1212 accountMap := NewAccountMap() 1213 if err := accountMap.Initialize(bcdata); err != nil { 1214 t.Fatal(err) 1215 } 1216 1217 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1218 1219 // reservoir account 1220 reservoir := &TestAccountType{ 1221 Addr: *bcdata.addrs[0], 1222 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1223 Nonce: uint64(0), 1224 } 1225 1226 // for contract execution txs 1227 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 1228 assert.Equal(t, nil, err) 1229 1230 // test account will be lack of KLAY 1231 testAcc, err := createDefaultAccount(accountkey.AccountKeyTypeLegacy) 1232 assert.Equal(t, nil, err) 1233 1234 gasLimit := uint64(100000000000) 1235 gasPrice := big.NewInt(25 * params.Ston) 1236 amount := uint64(25 * params.Ston) 1237 cost := new(big.Int).Mul(new(big.Int).SetUint64(gasLimit), gasPrice) 1238 cost.Add(cost, new(big.Int).SetUint64(amount)) 1239 1240 // deploy a contract for contract execution tx type 1241 { 1242 var txs types.Transactions 1243 1244 values := map[types.TxValueKeyType]interface{}{ 1245 types.TxValueKeyNonce: reservoir.GetNonce(), 1246 types.TxValueKeyFrom: reservoir.GetAddr(), 1247 types.TxValueKeyTo: (*common.Address)(nil), 1248 types.TxValueKeyAmount: big.NewInt(0), 1249 types.TxValueKeyGasLimit: gasLimit, 1250 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 1251 types.TxValueKeyHumanReadable: false, 1252 types.TxValueKeyData: common.FromHex(code), 1253 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 1254 } 1255 1256 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 1257 assert.Equal(t, nil, err) 1258 1259 err = tx.SignWithKeys(signer, reservoir.Keys) 1260 assert.Equal(t, nil, err) 1261 1262 txs = append(txs, tx) 1263 1264 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1265 t.Fatal(err) 1266 } 1267 1268 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 1269 1270 reservoir.AddNonce() 1271 } 1272 1273 // generate a test account with a specific amount of KLAY 1274 { 1275 var txs types.Transactions 1276 1277 valueMapForCreation, _ := genMapForTxTypes(reservoir, testAcc, types.TxTypeValueTransfer) 1278 valueMapForCreation[types.TxValueKeyAmount] = cost 1279 1280 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, valueMapForCreation) 1281 assert.Equal(t, nil, err) 1282 1283 err = tx.SignWithKeys(signer, reservoir.Keys) 1284 assert.Equal(t, nil, err) 1285 1286 txs = append(txs, tx) 1287 1288 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1289 t.Fatal(err) 1290 } 1291 reservoir.AddNonce() 1292 } 1293 1294 // test for all tx types 1295 for _, testTxType := range testTxTypes { 1296 txType := testTxType.txType 1297 1298 if !txType.IsFeeDelegatedTransaction() { 1299 // tx with a specific amount or a gasLimit requiring more KLAY than the sender has. 1300 { 1301 var expectedErr error 1302 1303 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1304 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1305 valueMap[types.TxValueKeyTo] = contract.Addr 1306 } 1307 if valueMap[types.TxValueKeyAmount] != nil { 1308 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 1309 valueMap[types.TxValueKeyGasLimit] = gasLimit + 1 // requires 1 more gas 1310 // The tx will be failed in vm since it can buy gas but cannot send enough value 1311 expectedErr = vm.ErrInsufficientBalance 1312 } else { 1313 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) + 1 // requires 1 more gas 1314 // The tx will be failed in buyGas() since it cannot buy enough gas 1315 expectedErr = errInsufficientBalanceForGasFeePayer 1316 } 1317 1318 tx, err := types.NewTransactionWithMap(txType, valueMap) 1319 assert.Equal(t, nil, err) 1320 1321 err = tx.SignWithKeys(signer, testAcc.Keys) 1322 assert.Equal(t, nil, err) 1323 1324 receipt, err := applyTransaction(t, bcdata, tx) 1325 assert.Equal(t, expectedErr, err) 1326 assert.Equal(t, (*types.Receipt)(nil), receipt) 1327 } 1328 1329 // tx with a specific amount or a gasLimit requiring the exact KLAY the sender has. 1330 { 1331 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1332 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1333 valueMap[types.TxValueKeyTo] = contract.Addr 1334 } 1335 if valueMap[types.TxValueKeyAmount] != nil { 1336 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 1337 valueMap[types.TxValueKeyGasLimit] = gasLimit 1338 } else { 1339 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) 1340 } 1341 1342 tx, err := types.NewTransactionWithMap(txType, valueMap) 1343 assert.Equal(t, nil, err) 1344 1345 err = tx.SignWithKeys(signer, testAcc.Keys) 1346 assert.Equal(t, nil, err) 1347 1348 receipt, err := applyTransaction(t, bcdata, tx) 1349 assert.Equal(t, nil, err) 1350 // contract deploy tx with non-zero value will be failed in vm because test functions do not support it. 1351 if txType.IsContractDeploy() { 1352 assert.Equal(t, types.ReceiptStatusErrExecutionReverted, receipt.Status) 1353 } else { 1354 assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 1355 } 1356 } 1357 } 1358 1359 if txType.IsFeeDelegatedTransaction() && !txType.IsFeeDelegatedWithRatioTransaction() { 1360 // tx with a specific amount requiring more KLAY than the sender has. 1361 { 1362 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1363 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1364 valueMap[types.TxValueKeyTo] = contract.Addr 1365 } 1366 if valueMap[types.TxValueKeyAmount] != nil { 1367 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 1368 valueMap[types.TxValueKeyAmount] = new(big.Int).Add(cost, new(big.Int).SetUint64(1)) // requires 1 more amount 1369 1370 tx, err := types.NewTransactionWithMap(txType, valueMap) 1371 assert.Equal(t, nil, err) 1372 1373 err = tx.SignWithKeys(signer, testAcc.Keys) 1374 assert.Equal(t, nil, err) 1375 1376 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1377 assert.Equal(t, nil, err) 1378 1379 receipt, err := applyTransaction(t, bcdata, tx) 1380 assert.Equal(t, vm.ErrInsufficientBalance, err) 1381 assert.Equal(t, (*types.Receipt)(nil), receipt) 1382 } 1383 } 1384 1385 // tx with a specific gasLimit (or amount) requiring more KLAY than the feePayer has. 1386 { 1387 valueMap, _ := genMapForTxTypes(reservoir, reservoir, txType) 1388 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1389 valueMap[types.TxValueKeyTo] = contract.Addr 1390 } 1391 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 1392 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) + 1 // requires 1 more gas 1393 1394 tx, err := types.NewTransactionWithMap(txType, valueMap) 1395 assert.Equal(t, nil, err) 1396 1397 err = tx.SignWithKeys(signer, reservoir.Keys) 1398 assert.Equal(t, nil, err) 1399 1400 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 1401 assert.Equal(t, nil, err) 1402 1403 receipt, err := applyTransaction(t, bcdata, tx) 1404 assert.Equal(t, errInsufficientBalanceForGasFeePayer, err) 1405 assert.Equal(t, (*types.Receipt)(nil), receipt) 1406 } 1407 1408 // tx with a specific amount requiring the exact KLAY the sender has. 1409 { 1410 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1411 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1412 valueMap[types.TxValueKeyTo] = contract.Addr 1413 } 1414 if valueMap[types.TxValueKeyAmount] != nil { 1415 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 1416 valueMap[types.TxValueKeyAmount] = cost 1417 1418 tx, err := types.NewTransactionWithMap(txType, valueMap) 1419 assert.Equal(t, nil, err) 1420 1421 err = tx.SignWithKeys(signer, testAcc.Keys) 1422 assert.Equal(t, nil, err) 1423 1424 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1425 assert.Equal(t, nil, err) 1426 1427 receipt, err := applyTransaction(t, bcdata, tx) 1428 assert.Equal(t, nil, err) 1429 // contract deploy tx with non-zero value will be failed in vm because test functions do not support it. 1430 if txType.IsContractDeploy() { 1431 assert.Equal(t, types.ReceiptStatusErrExecutionReverted, receipt.Status) 1432 } else { 1433 assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 1434 } 1435 } 1436 } 1437 1438 // tx with a specific gasLimit (or amount) requiring the exact KLAY the feePayer has. 1439 { 1440 valueMap, _ := genMapForTxTypes(reservoir, reservoir, txType) 1441 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1442 valueMap[types.TxValueKeyTo] = contract.Addr 1443 } 1444 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 1445 valueMap[types.TxValueKeyGasLimit] = gasLimit + (amount / gasPrice.Uint64()) 1446 1447 tx, err := types.NewTransactionWithMap(txType, valueMap) 1448 assert.Equal(t, nil, err) 1449 1450 err = tx.SignWithKeys(signer, reservoir.Keys) 1451 assert.Equal(t, nil, err) 1452 1453 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 1454 assert.Equal(t, nil, err) 1455 1456 receipt, err := applyTransaction(t, bcdata, tx) 1457 assert.Equal(t, nil, err) 1458 assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 1459 } 1460 } 1461 1462 if txType.IsFeeDelegatedWithRatioTransaction() { 1463 // tx with a specific amount and a gasLimit requiring more KLAY than the sender has. 1464 { 1465 var expectedErr error 1466 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1467 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1468 valueMap[types.TxValueKeyTo] = contract.Addr 1469 } 1470 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 1471 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(90) 1472 if valueMap[types.TxValueKeyAmount] != nil { 1473 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 1474 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1475 // = (gasLimit + 1) * 10 * (100 - 90) * 0.01 = gasLimit + 1 1476 valueMap[types.TxValueKeyGasLimit] = (gasLimit + 1) * 10 // requires 1 more gas 1477 // The tx will be failed in vm since it can buy gas but cannot send enough value 1478 expectedErr = vm.ErrInsufficientBalance 1479 } else { 1480 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1481 // = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 * (100 - 90) * 0.01 = gasLimit + (amount / gasPrice.Uint64()) + 1 1482 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 // requires 1 more gas 1483 // The tx will be failed in buyGas() since it cannot buy enough gas 1484 expectedErr = errInsufficientBalanceForGas 1485 } 1486 1487 tx, err := types.NewTransactionWithMap(txType, valueMap) 1488 assert.Equal(t, nil, err) 1489 1490 err = tx.SignWithKeys(signer, testAcc.Keys) 1491 assert.Equal(t, nil, err) 1492 1493 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1494 assert.Equal(t, nil, err) 1495 1496 receipt, err := applyTransaction(t, bcdata, tx) 1497 assert.Equal(t, expectedErr, err) 1498 assert.Equal(t, (*types.Receipt)(nil), receipt) 1499 } 1500 1501 // tx with a specific amount and a gasLimit requiring more KLAY than the feePayer has. 1502 { 1503 valueMap, _ := genMapForTxTypes(reservoir, reservoir, txType) 1504 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1505 valueMap[types.TxValueKeyTo] = contract.Addr 1506 } 1507 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 1508 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(10) 1509 // Gas testAcc will charge = tx gasLimit * fee-payer's feeRatio 1510 // = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 * 10 * 0.01 = gasLimit + (amount / gasPrice.Uint64()) + 1 1511 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64()) + 1) * 10 // requires 1 more gas 1512 1513 tx, err := types.NewTransactionWithMap(txType, valueMap) 1514 assert.Equal(t, nil, err) 1515 1516 err = tx.SignWithKeys(signer, reservoir.Keys) 1517 assert.Equal(t, nil, err) 1518 1519 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 1520 assert.Equal(t, nil, err) 1521 1522 receipt, err := applyTransaction(t, bcdata, tx) 1523 assert.Equal(t, errInsufficientBalanceForGasFeePayer, err) 1524 assert.Equal(t, (*types.Receipt)(nil), receipt) 1525 } 1526 1527 // tx with a specific amount and a gasLimit requiring the exact KLAY the sender has. 1528 { 1529 valueMap, _ := genMapForTxTypes(testAcc, reservoir, txType) 1530 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1531 valueMap[types.TxValueKeyTo] = contract.Addr 1532 } 1533 valueMap[types.TxValueKeyFeePayer] = reservoir.Addr 1534 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(90) 1535 if valueMap[types.TxValueKeyAmount] != nil { 1536 valueMap[types.TxValueKeyAmount] = new(big.Int).SetUint64(amount) 1537 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1538 // = gasLimit * 10 * (100 - 90) * 0.01 = gasLimit 1539 valueMap[types.TxValueKeyGasLimit] = gasLimit * 10 1540 } else { 1541 // Gas testAcc will charge = tx gasLimit * sender's feeRatio 1542 // = (gasLimit + (amount / gasPrice.Uint64())) * 10 * (100 - 90) * 0.01 = gasLimit + (amount / gasPrice.Uint64()) 1543 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64())) * 10 1544 } 1545 1546 tx, err := types.NewTransactionWithMap(txType, valueMap) 1547 assert.Equal(t, nil, err) 1548 1549 err = tx.SignWithKeys(signer, testAcc.Keys) 1550 assert.Equal(t, nil, err) 1551 1552 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1553 assert.Equal(t, nil, err) 1554 1555 receipt, err := applyTransaction(t, bcdata, tx) 1556 assert.Equal(t, nil, err) 1557 // contract deploy tx with non-zero value will be failed in vm because test functions do not support it. 1558 if txType.IsContractDeploy() { 1559 assert.Equal(t, types.ReceiptStatusErrExecutionReverted, receipt.Status) 1560 } else { 1561 assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 1562 } 1563 } 1564 1565 // tx with a specific amount and a gasLimit requiring the exact KLAY the feePayer has. 1566 { 1567 valueMap, _ := genMapForTxTypes(reservoir, reservoir, txType) 1568 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1569 valueMap[types.TxValueKeyTo] = contract.Addr 1570 } 1571 valueMap[types.TxValueKeyFeePayer] = testAcc.Addr 1572 valueMap[types.TxValueKeyFeeRatioOfFeePayer] = types.FeeRatio(10) 1573 // Gas testAcc will charge = tx gasLimit * fee-payer's feeRatio 1574 // = (gasLimit + (amount / gasPrice.Uint64())) * 10 * 10 * 0.01 = gasLimit + (amount / gasPrice.Uint64()) 1575 valueMap[types.TxValueKeyGasLimit] = (gasLimit + (amount / gasPrice.Uint64())) * 10 1576 1577 tx, err := types.NewTransactionWithMap(txType, valueMap) 1578 assert.Equal(t, nil, err) 1579 1580 err = tx.SignWithKeys(signer, reservoir.Keys) 1581 assert.Equal(t, nil, err) 1582 1583 tx.SignFeePayerWithKeys(signer, testAcc.Keys) 1584 assert.Equal(t, nil, err) 1585 1586 receipt, err := applyTransaction(t, bcdata, tx) 1587 assert.Equal(t, nil, err) 1588 assert.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) 1589 } 1590 } 1591 } 1592 } 1593 1594 // TestValidationTxSizeAfterRLP tests tx size validation during txPool insert process. 1595 // Since the size is RLP encoded tx size, the test also includes RLP encoding/decoding process which may raise an issue. 1596 func TestValidationTxSizeAfterRLP(t *testing.T) { 1597 testTxTypes := []types.TxType{} 1598 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 1599 if i == types.TxTypeKlaytnLast { 1600 i = types.TxTypeEthereumAccessList 1601 } 1602 1603 tx, err := types.NewTxInternalData(i) 1604 if err == nil { 1605 // Since this test is for payload size, tx types without payload field will not be tested. 1606 if _, ok := tx.(types.TxInternalDataPayload); ok { 1607 testTxTypes = append(testTxTypes, i) 1608 } 1609 } 1610 } 1611 1612 prof := profile.NewProfiler() 1613 1614 // Initialize blockchain 1615 bcdata, err := NewBCData(6, 4) 1616 if err != nil { 1617 t.Fatal(err) 1618 } 1619 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 1620 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 1621 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 1622 defer bcdata.Shutdown() 1623 1624 // Initialize address-balance map for verification 1625 accountMap := NewAccountMap() 1626 if err := accountMap.Initialize(bcdata); err != nil { 1627 t.Fatal(err) 1628 } 1629 1630 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1631 1632 // reservoir account 1633 reservoir := &TestAccountType{ 1634 Addr: *bcdata.addrs[0], 1635 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1636 Nonce: uint64(0), 1637 } 1638 1639 // for contract execution txs 1640 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 1641 assert.Equal(t, nil, err) 1642 1643 // deploy a contract for contract execution tx type 1644 { 1645 var txs types.Transactions 1646 1647 values := map[types.TxValueKeyType]interface{}{ 1648 types.TxValueKeyNonce: reservoir.GetNonce(), 1649 types.TxValueKeyFrom: reservoir.GetAddr(), 1650 types.TxValueKeyTo: (*common.Address)(nil), 1651 types.TxValueKeyAmount: big.NewInt(0), 1652 types.TxValueKeyGasLimit: gasLimit, 1653 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 1654 types.TxValueKeyHumanReadable: false, 1655 types.TxValueKeyData: common.FromHex(code), 1656 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 1657 } 1658 1659 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 1660 assert.Equal(t, nil, err) 1661 1662 err = tx.SignWithKeys(signer, reservoir.Keys) 1663 assert.Equal(t, nil, err) 1664 1665 txs = append(txs, tx) 1666 1667 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1668 t.Fatal(err) 1669 } 1670 1671 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 1672 1673 reservoir.AddNonce() 1674 } 1675 1676 // make TxPool to test validation in 'TxPool add' process 1677 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 1678 1679 // test for all tx types 1680 for _, txType := range testTxTypes { 1681 // test for invalid tx size 1682 { 1683 // generate invalid txs which size is around (32 * 1024) ~ (33 * 1024) 1684 valueMap, _ := genMapForTxTypes(reservoir, reservoir, txType) 1685 valueMap, _ = exceedSizeLimit(txType, valueMap, contract.Addr) 1686 1687 tx, err := types.NewTransactionWithMap(txType, valueMap) 1688 assert.Equal(t, nil, err) 1689 1690 err = tx.SignWithKeys(signer, reservoir.Keys) 1691 assert.Equal(t, nil, err) 1692 1693 if txType.IsFeeDelegatedTransaction() { 1694 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1695 assert.Equal(t, nil, err) 1696 } 1697 1698 // check the rlp encoded tx size 1699 encodedTx, err := rlp.EncodeToBytes(tx) 1700 if len(encodedTx) < blockchain.MaxTxDataSize { 1701 t.Fatalf("test data size is smaller than MaxTxDataSize") 1702 } 1703 1704 // RLP decode and re-generate the tx 1705 newTx := &types.Transaction{} 1706 err = rlp.DecodeBytes(encodedTx, newTx) 1707 1708 // test for tx pool insert validation 1709 err = txpool.AddRemote(newTx) 1710 assert.Equal(t, blockchain.ErrOversizedData, err) 1711 } 1712 1713 // test for valid tx size 1714 { 1715 // generate valid txs which size is around (31 * 1024) ~ (32 * 1024) 1716 to := reservoir 1717 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1718 to = contract 1719 } 1720 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 1721 validData := make([]byte, blockchain.MaxTxDataSize-1024) 1722 1723 if valueMap[types.TxValueKeyData] != nil { 1724 valueMap[types.TxValueKeyData] = validData 1725 } 1726 1727 if valueMap[types.TxValueKeyAnchoredData] != nil { 1728 valueMap[types.TxValueKeyAnchoredData] = validData 1729 } 1730 1731 tx, err := types.NewTransactionWithMap(txType, valueMap) 1732 assert.Equal(t, nil, err) 1733 1734 err = tx.SignWithKeys(signer, reservoir.Keys) 1735 assert.Equal(t, nil, err) 1736 1737 if txType.IsFeeDelegatedTransaction() { 1738 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1739 assert.Equal(t, nil, err) 1740 } 1741 1742 // check the rlp encoded tx size 1743 encodedTx, err := rlp.EncodeToBytes(tx) 1744 if len(encodedTx) > blockchain.MaxTxDataSize { 1745 t.Fatalf("test data size is bigger than MaxTxDataSize") 1746 } 1747 1748 // RLP decode and re-generate the tx 1749 newTx := &types.Transaction{} 1750 err = rlp.DecodeBytes(encodedTx, newTx) 1751 1752 // test for tx pool insert validation 1753 err = txpool.AddRemote(newTx) 1754 assert.Equal(t, nil, err) 1755 reservoir.AddNonce() 1756 } 1757 } 1758 } 1759 1760 // TestValidationPoolResetAfterSenderKeyChange puts txs in the pending pool and generates a block only with the first tx. 1761 // Since the tx changes the sender's account key, all rest txs should drop from the pending pool. 1762 func TestValidationPoolResetAfterSenderKeyChange(t *testing.T) { 1763 txTypes := []types.TxType{} 1764 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 1765 if i == types.TxTypeKlaytnLast { 1766 i = types.TxTypeEthereumAccessList 1767 } 1768 1769 _, err := types.NewTxInternalData(i) 1770 if err == nil { 1771 txTypes = append(txTypes, i) 1772 } 1773 } 1774 1775 prof := profile.NewProfiler() 1776 1777 // Initialize blockchain 1778 bcdata, err := NewBCData(6, 4) 1779 if err != nil { 1780 t.Fatal(err) 1781 } 1782 bcdata.bc.Config().IstanbulCompatibleBlock = big.NewInt(0) 1783 bcdata.bc.Config().LondonCompatibleBlock = big.NewInt(0) 1784 bcdata.bc.Config().EthTxTypeCompatibleBlock = big.NewInt(0) 1785 defer bcdata.Shutdown() 1786 1787 // Initialize address-balance map for verification 1788 accountMap := NewAccountMap() 1789 if err := accountMap.Initialize(bcdata); err != nil { 1790 t.Fatal(err) 1791 } 1792 1793 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1794 1795 // reservoir account 1796 reservoir := &TestAccountType{ 1797 Addr: *bcdata.addrs[0], 1798 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1799 Nonce: uint64(0), 1800 } 1801 1802 // for contract execution txs 1803 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 1804 assert.Equal(t, nil, err) 1805 1806 // deploy a contract for contract execution tx type 1807 { 1808 var txs types.Transactions 1809 1810 values := map[types.TxValueKeyType]interface{}{ 1811 types.TxValueKeyNonce: reservoir.GetNonce(), 1812 types.TxValueKeyFrom: reservoir.GetAddr(), 1813 types.TxValueKeyTo: (*common.Address)(nil), 1814 types.TxValueKeyAmount: big.NewInt(0), 1815 types.TxValueKeyGasLimit: gasLimit, 1816 types.TxValueKeyGasPrice: big.NewInt(0), 1817 types.TxValueKeyHumanReadable: false, 1818 types.TxValueKeyData: common.FromHex(code), 1819 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 1820 } 1821 1822 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 1823 assert.Equal(t, nil, err) 1824 1825 err = tx.SignWithKeys(signer, reservoir.Keys) 1826 assert.Equal(t, nil, err) 1827 1828 txs = append(txs, tx) 1829 1830 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1831 t.Fatal(err) 1832 } 1833 1834 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 1835 1836 reservoir.AddNonce() 1837 } 1838 1839 // make TxPool to test validation in 'TxPool add' process 1840 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 1841 1842 // state changing tx which will invalidate other txs when it is contained in a block. 1843 var txs types.Transactions 1844 { 1845 valueMap, _ := genMapForTxTypes(reservoir, reservoir, types.TxTypeAccountUpdate) 1846 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, valueMap) 1847 1848 assert.Equal(t, nil, err) 1849 1850 err = tx.SignWithKeys(signer, reservoir.Keys) 1851 assert.Equal(t, nil, err) 1852 1853 txs = append(txs, tx) 1854 1855 err = txpool.AddRemote(tx) 1856 assert.Equal(t, nil, err) 1857 reservoir.AddNonce() 1858 } 1859 1860 // generate valid txs with all tx types. 1861 for _, txType := range txTypes { 1862 to := reservoir 1863 if toBasicType(txType) == types.TxTypeSmartContractExecution { 1864 to = contract 1865 } 1866 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 1867 tx, err := types.NewTransactionWithMap(txType, valueMap) 1868 assert.Equal(t, nil, err) 1869 1870 err = tx.SignWithKeys(signer, reservoir.Keys) 1871 assert.Equal(t, nil, err) 1872 1873 if txType.IsFeeDelegatedTransaction() { 1874 tx.SignFeePayerWithKeys(signer, reservoir.Keys) 1875 assert.Equal(t, nil, err) 1876 } 1877 1878 err = txpool.AddRemote(tx) 1879 if err != nil { 1880 fmt.Println(tx) 1881 statedb, _ := bcdata.bc.State() 1882 fmt.Println(statedb.GetCode(tx.ValidatedSender())) 1883 } 1884 assert.Equal(t, nil, err) 1885 reservoir.AddNonce() 1886 } 1887 1888 // check pending whether it contains all txs 1889 pendingLen, _ := txpool.Stats() 1890 assert.Equal(t, len(txTypes)+1, pendingLen) 1891 1892 // generate a block with a state changing tx 1893 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1894 t.Fatal(err) 1895 } 1896 1897 // Wait 1 second until txpool.reset() is called. 1898 time.Sleep(1 * time.Second) 1899 1900 // check pending whether it contains zero tx 1901 pendingLen, _ = txpool.Stats() 1902 assert.Equal(t, 0, pendingLen) 1903 } 1904 1905 // TestValidationPoolResetAfterFeePayerKeyChange puts txs in the pending pool and generates a block only with the first tx. 1906 // Since the tx changes the fee payer's account key, all rest txs should drop from the pending pool. 1907 func TestValidationPoolResetAfterFeePayerKeyChange(t *testing.T) { 1908 txTypes := []types.TxType{} 1909 for i := types.TxTypeLegacyTransaction; i < types.TxTypeEthereumLast; i++ { 1910 if i == types.TxTypeKlaytnLast { 1911 i = types.TxTypeEthereumAccessList 1912 } 1913 1914 _, err := types.NewTxInternalData(i) 1915 if err == nil { 1916 // This test is only for fee-delegated tx types 1917 if i.IsFeeDelegatedTransaction() { 1918 txTypes = append(txTypes, i) 1919 } 1920 } 1921 } 1922 1923 prof := profile.NewProfiler() 1924 1925 // Initialize blockchain 1926 bcdata, err := NewBCData(6, 4) 1927 if err != nil { 1928 t.Fatal(err) 1929 } 1930 defer bcdata.Shutdown() 1931 1932 // Initialize address-balance map for verification 1933 accountMap := NewAccountMap() 1934 if err := accountMap.Initialize(bcdata); err != nil { 1935 t.Fatal(err) 1936 } 1937 1938 signer := types.LatestSignerForChainID(bcdata.bc.Config().ChainID) 1939 1940 // reservoir account 1941 reservoir := &TestAccountType{ 1942 Addr: *bcdata.addrs[0], 1943 Keys: []*ecdsa.PrivateKey{bcdata.privKeys[0]}, 1944 Nonce: uint64(0), 1945 } 1946 1947 // for contract execution txs 1948 contract, err := createAnonymousAccount("a5c9a50938a089618167c9d67dbebc0deaffc3c76ddc6b40c2777ae59438e989") 1949 assert.Equal(t, nil, err) 1950 1951 // fee payer account 1952 feePayer, err := createDefaultAccount(accountkey.AccountKeyTypeLegacy) 1953 assert.Equal(t, nil, err) 1954 1955 // deploy a contract for contract execution tx type 1956 { 1957 var txs types.Transactions 1958 1959 values := map[types.TxValueKeyType]interface{}{ 1960 types.TxValueKeyNonce: reservoir.GetNonce(), 1961 types.TxValueKeyFrom: reservoir.GetAddr(), 1962 types.TxValueKeyTo: (*common.Address)(nil), 1963 types.TxValueKeyAmount: big.NewInt(0), 1964 types.TxValueKeyGasLimit: gasLimit, 1965 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 1966 types.TxValueKeyHumanReadable: false, 1967 types.TxValueKeyData: common.FromHex(code), 1968 types.TxValueKeyCodeFormat: params.CodeFormatEVM, 1969 } 1970 1971 tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values) 1972 assert.Equal(t, nil, err) 1973 1974 err = tx.SignWithKeys(signer, reservoir.Keys) 1975 assert.Equal(t, nil, err) 1976 1977 txs = append(txs, tx) 1978 1979 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 1980 t.Fatal(err) 1981 } 1982 1983 contract.Addr = crypto.CreateAddress(reservoir.Addr, reservoir.Nonce) 1984 1985 reservoir.AddNonce() 1986 } 1987 1988 // transfer KLAY to fee payer 1989 { 1990 var txs types.Transactions 1991 1992 values := map[types.TxValueKeyType]interface{}{ 1993 types.TxValueKeyNonce: reservoir.GetNonce(), 1994 types.TxValueKeyFrom: reservoir.GetAddr(), 1995 types.TxValueKeyTo: feePayer.Addr, 1996 types.TxValueKeyAmount: new(big.Int).Mul(big.NewInt(params.KLAY), big.NewInt(100000)), 1997 types.TxValueKeyGasLimit: gasLimit, 1998 types.TxValueKeyGasPrice: big.NewInt(25 * params.Ston), 1999 } 2000 2001 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, values) 2002 assert.Equal(t, nil, err) 2003 2004 err = tx.SignWithKeys(signer, reservoir.Keys) 2005 assert.Equal(t, nil, err) 2006 2007 txs = append(txs, tx) 2008 2009 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 2010 t.Fatal(err) 2011 } 2012 reservoir.AddNonce() 2013 } 2014 2015 // make TxPool to test validation in 'TxPool add' process 2016 txpool := blockchain.NewTxPool(blockchain.DefaultTxPoolConfig, bcdata.bc.Config(), bcdata.bc) 2017 2018 // state changing tx which will invalidate other txs when it is contained in a block. 2019 var txs types.Transactions 2020 { 2021 valueMap, _ := genMapForTxTypes(feePayer, feePayer, types.TxTypeAccountUpdate) 2022 tx, err := types.NewTransactionWithMap(types.TxTypeAccountUpdate, valueMap) 2023 2024 assert.Equal(t, nil, err) 2025 2026 err = tx.SignWithKeys(signer, feePayer.Keys) 2027 assert.Equal(t, nil, err) 2028 2029 txs = append(txs, tx) 2030 2031 err = txpool.AddRemote(tx) 2032 assert.Equal(t, nil, err) 2033 feePayer.AddNonce() 2034 } 2035 2036 // generate valid txs with all tx fee delegation types. 2037 for _, txType := range txTypes { 2038 to := reservoir 2039 if toBasicType(txType) == types.TxTypeSmartContractExecution { 2040 to = contract 2041 } 2042 2043 valueMap, _ := genMapForTxTypes(reservoir, to, txType) 2044 valueMap[types.TxValueKeyFeePayer] = feePayer.Addr 2045 2046 tx, err := types.NewTransactionWithMap(txType, valueMap) 2047 assert.Equal(t, nil, err) 2048 2049 err = tx.SignWithKeys(signer, reservoir.Keys) 2050 assert.Equal(t, nil, err) 2051 2052 tx.SignFeePayerWithKeys(signer, feePayer.Keys) 2053 assert.Equal(t, nil, err) 2054 2055 err = txpool.AddRemote(tx) 2056 assert.Equal(t, nil, err) 2057 reservoir.AddNonce() 2058 } 2059 2060 // check pending whether it contains all txs 2061 pendingLen, _ := txpool.Stats() 2062 assert.Equal(t, len(txTypes)+1, pendingLen) 2063 2064 // generate a block with a state changing tx 2065 if err := bcdata.GenABlockWithTransactions(accountMap, txs, prof); err != nil { 2066 t.Fatal(err) 2067 } 2068 2069 // Wait 1 second until txpool.reset() is called. 2070 time.Sleep(1 * time.Second) 2071 2072 // check pending whether it contains zero tx 2073 pendingLen, _ = txpool.Stats() 2074 assert.Equal(t, 0, pendingLen) 2075 }