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