github.com/klaytn/klaytn@v1.12.1/tests/klay_test.go (about) 1 // Copyright 2018 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 "bytes" 21 "crypto/ecdsa" 22 "flag" 23 "fmt" 24 "math/big" 25 "math/rand" 26 "os" 27 "strconv" 28 "testing" 29 "time" 30 31 "github.com/klaytn/klaytn/blockchain" 32 "github.com/klaytn/klaytn/blockchain/types" 33 "github.com/klaytn/klaytn/common/profile" 34 "github.com/klaytn/klaytn/crypto" 35 "github.com/klaytn/klaytn/kerrors" 36 "github.com/klaytn/klaytn/log" 37 "github.com/klaytn/klaytn/params" 38 "github.com/klaytn/klaytn/rlp" 39 "github.com/stretchr/testify/assert" 40 "github.com/stretchr/testify/require" 41 ) 42 43 var txPerBlock int 44 45 func init() { 46 flag.IntVar(&txPerBlock, "txs-per-block", 1000, 47 "Specify the number of transactions per block") 48 } 49 50 //////////////////////////////////////////////////////////////////////////////// 51 // TestValueTransfer 52 //////////////////////////////////////////////////////////////////////////////// 53 type testOption struct { 54 numTransactions int 55 numMaxAccounts int 56 numValidators int 57 numGeneratedBlocks int 58 txdata []byte 59 makeTransactions func(*BCData, *AccountMap, types.Signer, int, *big.Int, []byte) (types.Transactions, error) 60 } 61 62 func makeTransactionsFrom(bcdata *BCData, accountMap *AccountMap, signer types.Signer, numTransactions int, 63 amount *big.Int, data []byte, 64 ) (types.Transactions, error) { 65 from := *bcdata.addrs[0] 66 privKey := bcdata.privKeys[0] 67 toAddrs := bcdata.addrs 68 numAddrs := len(toAddrs) 69 70 txs := make(types.Transactions, 0, numTransactions) 71 nonce := accountMap.GetNonce(from) 72 73 for i := 0; i < numTransactions; i++ { 74 a := toAddrs[i%numAddrs] 75 txamount := amount 76 if txamount == nil { 77 txamount = big.NewInt(rand.Int63n(10)) 78 txamount = txamount.Add(txamount, big.NewInt(1)) 79 } 80 var gasLimit uint64 = 1000000 81 gasPrice := new(big.Int).SetInt64(0) 82 83 tx := types.NewTransaction(nonce, *a, txamount, gasLimit, gasPrice, data) 84 signedTx, err := types.SignTx(tx, signer, privKey) 85 if err != nil { 86 return nil, err 87 } 88 89 txs = append(txs, signedTx) 90 91 nonce++ 92 } 93 94 return txs, nil 95 } 96 97 func makeIndependentTransactions(bcdata *BCData, accountMap *AccountMap, signer types.Signer, numTransactions int, 98 amount *big.Int, data []byte, 99 ) (types.Transactions, error) { 100 numAddrs := len(bcdata.addrs) / 2 101 fromAddrs := bcdata.addrs[:numAddrs] 102 toAddrs := bcdata.addrs[numAddrs:] 103 104 fromNonces := make([]uint64, numAddrs) 105 for i, addr := range fromAddrs { 106 fromNonces[i] = accountMap.GetNonce(*addr) 107 } 108 109 txs := make(types.Transactions, 0, numTransactions) 110 111 for i := 0; i < numTransactions; i++ { 112 idx := i % numAddrs 113 114 txamount := amount 115 if txamount == nil { 116 txamount = big.NewInt(rand.Int63n(10)) 117 txamount = txamount.Add(txamount, big.NewInt(1)) 118 } 119 var gasLimit uint64 = 1000000 120 gasPrice := new(big.Int).SetInt64(0) 121 122 tx := types.NewTransaction(fromNonces[idx], *toAddrs[idx], txamount, gasLimit, gasPrice, data) 123 signedTx, err := types.SignTx(tx, signer, bcdata.privKeys[idx]) 124 if err != nil { 125 return nil, err 126 } 127 128 txs = append(txs, signedTx) 129 130 fromNonces[idx]++ 131 } 132 133 return txs, nil 134 } 135 136 // makeTransactionsToRandom makes `numTransactions` transactions which transfers a random amount of tokens 137 // from accounts in `AccountMap` to a randomly generated account. 138 // It returns the generated transactions if successful, or it returns an error if failed. 139 func makeTransactionsToRandom(bcdata *BCData, accountMap *AccountMap, signer types.Signer, numTransactions int, 140 amount *big.Int, data []byte, 141 ) (types.Transactions, error) { 142 numAddrs := len(bcdata.addrs) 143 fromAddrs := bcdata.addrs 144 145 fromNonces := make([]uint64, numAddrs) 146 for i, addr := range fromAddrs { 147 fromNonces[i] = accountMap.GetNonce(*addr) 148 } 149 150 txs := make(types.Transactions, 0, numTransactions) 151 152 for i := 0; i < numTransactions; i++ { 153 idx := i % numAddrs 154 155 txamount := amount 156 if txamount == nil { 157 txamount = big.NewInt(rand.Int63n(10)) 158 txamount = txamount.Add(txamount, big.NewInt(1)) 159 } 160 var gasLimit uint64 = 1000000 161 gasPrice := new(big.Int).SetInt64(0) 162 163 // generate a new address 164 k, err := crypto.GenerateKey() 165 if err != nil { 166 return nil, err 167 } 168 to := crypto.PubkeyToAddress(k.PublicKey) 169 170 tx := types.NewTransaction(fromNonces[idx], to, txamount, gasLimit, gasPrice, data) 171 signedTx, err := types.SignTx(tx, signer, bcdata.privKeys[idx]) 172 if err != nil { 173 return nil, err 174 } 175 176 txs = append(txs, signedTx) 177 178 fromNonces[idx]++ 179 } 180 181 return txs, nil 182 } 183 184 // makeTransactionsToRandom makes `numTransactions` transactions which transfers a random amount of KLAY 185 // from accounts in `AccountMap` to a randomly generated account. 186 // It returns the generated transactions if successful, or it returns an error if failed. 187 func makeNewTransactionsToRandom(bcdata *BCData, accountMap *AccountMap, signer types.Signer, numTransactions int, 188 amount *big.Int, data []byte, 189 ) (types.Transactions, error) { 190 numAddrs := len(bcdata.addrs) 191 fromAddrs := bcdata.addrs 192 fromNonces := make([]uint64, numAddrs) 193 194 for i, addr := range fromAddrs { 195 fromNonces[i] = accountMap.GetNonce(*addr) 196 } 197 198 txs := make(types.Transactions, 0, numTransactions) 199 200 for i := 0; i < numTransactions; i++ { 201 idx := i % numAddrs 202 203 txamount := amount 204 if txamount == nil { 205 txamount = big.NewInt(rand.Int63n(10)) 206 txamount = txamount.Add(txamount, big.NewInt(1)) 207 } 208 var gasLimit uint64 = 1000000 209 gasPrice := new(big.Int).SetInt64(0) 210 211 // generate a new address 212 k, err := crypto.GenerateKey() 213 if err != nil { 214 return nil, err 215 } 216 to := crypto.PubkeyToAddress(k.PublicKey) 217 218 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, map[types.TxValueKeyType]interface{}{ 219 types.TxValueKeyNonce: fromNonces[idx], 220 types.TxValueKeyTo: to, 221 types.TxValueKeyAmount: txamount, 222 types.TxValueKeyGasLimit: gasLimit, 223 types.TxValueKeyGasPrice: gasPrice, 224 types.TxValueKeyFrom: *bcdata.addrs[idx], 225 }) 226 signedTx, err := types.SignTx(tx, signer, bcdata.privKeys[idx]) 227 if err != nil { 228 return nil, err 229 } 230 231 txs = append(txs, signedTx) 232 233 fromNonces[idx]++ 234 } 235 236 return txs, nil 237 } 238 239 // makeNewTransactionsToRing makes `numTransactions` transactions which transfers a fixed amount of KLAY 240 // from account with index i to account with index (i+1). To have same amount of balance before and after the test, 241 // total number of transactions should be the multiple of number of addresses. 242 // It returns the generated transactions if successful, or it returns an error if failed. 243 func makeNewTransactionsToRing(bcdata *BCData, accountMap *AccountMap, signer types.Signer, numTransactions int, 244 amount *big.Int, data []byte, 245 ) (types.Transactions, error) { 246 numAddrs := len(bcdata.addrs) 247 fromAddrs := bcdata.addrs 248 249 if numTransactions%numAddrs != 0 { 250 return nil, fmt.Errorf("numTranasctions should be divided by numAddrs! numTransactions: %v, numAddrs: %v", numTransactions, numAddrs) 251 } 252 253 fromNonces := make([]uint64, numAddrs) 254 for i, addr := range fromAddrs { 255 fromNonces[i] = accountMap.GetNonce(*addr) 256 } 257 258 txs := make(types.Transactions, 0, numTransactions) 259 txAmount := amount 260 if txAmount == nil { 261 txAmount = big.NewInt(rand.Int63n(10)) 262 txAmount = txAmount.Add(txAmount, big.NewInt(1)) 263 } 264 var gasLimit uint64 = 1000000 265 gasPrice := new(big.Int).SetInt64(0) 266 for i := 0; i < numTransactions; i++ { 267 fromIdx := i % numAddrs 268 269 toIdx := (fromIdx + 1) % numAddrs 270 toAddr := *bcdata.addrs[toIdx] 271 272 tx, err := types.NewTransactionWithMap(types.TxTypeValueTransfer, map[types.TxValueKeyType]interface{}{ 273 types.TxValueKeyNonce: fromNonces[fromIdx], 274 types.TxValueKeyTo: toAddr, 275 types.TxValueKeyAmount: txAmount, 276 types.TxValueKeyGasLimit: gasLimit, 277 types.TxValueKeyGasPrice: gasPrice, 278 types.TxValueKeyFrom: *bcdata.addrs[fromIdx], 279 }) 280 281 signedTx, err := types.SignTx(tx, signer, bcdata.privKeys[fromIdx]) 282 if err != nil { 283 return nil, err 284 } 285 286 txs = append(txs, signedTx) 287 fromNonces[fromIdx]++ 288 } 289 290 return txs, nil 291 } 292 293 func TestValueTransfer(t *testing.T) { 294 var nBlocks int = 3 295 var txPerBlock int = 10 296 297 if i, err := strconv.ParseInt(os.Getenv("NUM_BLOCKS"), 10, 32); err == nil { 298 nBlocks = int(i) 299 } 300 301 if i, err := strconv.ParseInt(os.Getenv("TXS_PER_BLOCK"), 10, 32); err == nil { 302 txPerBlock = int(i) 303 } 304 305 valueTransferTests := [...]struct { 306 name string 307 opt testOption 308 }{ 309 { 310 "SingleSenderMultipleRecipient", 311 testOption{txPerBlock, 1000, 4, nBlocks, []byte{}, makeTransactionsFrom}, 312 }, 313 { 314 "MultipleSenderMultipleRecipient", 315 testOption{txPerBlock, 2000, 4, nBlocks, []byte{}, makeIndependentTransactions}, 316 }, 317 { 318 "MultipleSenderRandomRecipient", 319 testOption{txPerBlock, 2000, 4, nBlocks, []byte{}, makeTransactionsToRandom}, 320 }, 321 322 // Below test cases execute one transaction per a block. 323 { 324 "SingleSenderMultipleRecipientSingleTxPerBlock", 325 testOption{1, 1000, 4, 10, []byte{}, makeTransactionsFrom}, 326 }, 327 { 328 "MultipleSenderMultipleRecipientSingleTxPerBlock", 329 testOption{1, 2000, 4, 10, []byte{}, makeIndependentTransactions}, 330 }, 331 { 332 "MultipleSenderRandomRecipientSingleTxPerBlock", 333 testOption{1, 2000, 4, 10, []byte{}, makeTransactionsToRandom}, 334 }, 335 } 336 337 for _, test := range valueTransferTests { 338 t.Run(test.name, func(t *testing.T) { 339 testValueTransfer(t, &test.opt) 340 }) 341 } 342 } 343 344 func testValueTransfer(t *testing.T, opt *testOption) { 345 prof := profile.NewProfiler() 346 347 // Initialize blockchain 348 start := time.Now() 349 bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators) 350 if err != nil { 351 t.Fatal(err) 352 } 353 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 354 defer bcdata.Shutdown() 355 356 // Initialize address-balance map for verification 357 start = time.Now() 358 accountMap := NewAccountMap() 359 if err := accountMap.Initialize(bcdata); err != nil { 360 t.Fatal(err) 361 } 362 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 363 364 for i := 0; i < opt.numGeneratedBlocks; i++ { 365 // fmt.Printf("iteration %d\n", i) 366 err := bcdata.GenABlock(accountMap, opt, opt.numTransactions, prof) 367 if err != nil { 368 t.Fatal(err) 369 } 370 } 371 372 if testing.Verbose() { 373 prof.PrintProfileInfo() 374 } 375 } 376 377 func TestValueTransferRing(t *testing.T) { 378 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 379 prof := profile.NewProfiler() 380 381 numTransactions := 20000 382 numAccounts := 2000 383 384 if numTransactions%numAccounts != 0 { 385 t.Fatalf("numTransactions should be divided by numAccounts! numTransactions: %v, numAccounts: %v", numTransactions, numAccounts) 386 } 387 388 opt := testOption{numTransactions, numAccounts, 4, 1, []byte{}, makeNewTransactionsToRing} 389 390 // Initialize blockchain 391 start := time.Now() 392 bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators) 393 if err != nil { 394 t.Fatal(err) 395 } 396 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 397 defer bcdata.Shutdown() 398 399 // Initialize address-balance map for verification 400 start = time.Now() 401 accountMap := NewAccountMap() 402 if err := accountMap.Initialize(bcdata); err != nil { 403 t.Fatal(err) 404 } 405 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 406 407 // make txpool 408 txpool := makeTxPool(bcdata, opt.numTransactions) 409 signer := types.MakeSigner(bcdata.bc.Config(), bcdata.bc.CurrentHeader().Number) 410 411 // make ring transactions 412 txs, err := makeNewTransactionsToRing(bcdata, accountMap, signer, opt.numTransactions, nil, []byte{}) 413 if err != nil { 414 t.Fatal(err) 415 } 416 417 txpool.AddRemotes(txs) 418 419 for { 420 if err := bcdata.GenABlockWithTxpool(accountMap, txpool, prof); err != nil { 421 if err == errEmptyPending { 422 break 423 } 424 t.Fatal(err) 425 } 426 } 427 428 if testing.Verbose() { 429 prof.PrintProfileInfo() 430 } 431 } 432 433 // TestWronglyEncodedAccountKey checks if accountKey field is encoded in a wrong way. 434 // case 1. AccountUpdate 435 // case 2. FeeDelegatedAccountUpdate 436 // case 3. FeeDelegatedAccountUpdateWithRatio 437 func TestWronglyEncodedAccountKey(t *testing.T) { 438 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 439 prof := profile.NewProfiler() 440 441 numTransactions := 20000 442 numAccounts := 2000 443 444 if numTransactions%numAccounts != 0 { 445 t.Fatalf("numTransactions should be divided by numAccounts! numTransactions: %v, numAccounts: %v", numTransactions, numAccounts) 446 } 447 448 opt := testOption{numTransactions, numAccounts, 4, 1, []byte{}, makeNewTransactionsToRing} 449 450 // Initialize blockchain 451 start := time.Now() 452 bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators) 453 if err != nil { 454 t.Fatal(err) 455 } 456 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 457 defer bcdata.Shutdown() 458 459 // Initialize address-balance map for verification 460 start = time.Now() 461 accountMap := NewAccountMap() 462 if err := accountMap.Initialize(bcdata); err != nil { 463 t.Fatal(err) 464 } 465 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 466 467 // make txpool 468 // var txs types.Transactions 469 signer := types.MakeSigner(bcdata.bc.Config(), bcdata.bc.CurrentHeader().Number) 470 471 // case 1. AccountUpdate 472 { 473 tx := types.NewTx(&types.TxInternalDataAccountUpdate{}) 474 txtype := types.TxTypeAccountUpdate 475 476 wrongEncodedKey := []byte{0x10} 477 serializedBytes, err := rlp.EncodeToBytes([]interface{}{ 478 txtype, 479 uint64(0), 480 new(big.Int).SetUint64(25 * params.Ston), 481 uint64(100000), 482 *bcdata.addrs[0], 483 wrongEncodedKey, 484 }) 485 require.Equal(t, nil, err) 486 487 h := rlpHash(struct { 488 Byte []byte 489 ChainId *big.Int 490 R uint 491 S uint 492 }{ 493 serializedBytes, 494 bcdata.bc.Config().ChainID, 495 uint(0), 496 uint(0), 497 }) 498 sig, err := types.NewTxSignaturesWithValues(signer, tx, h, []*ecdsa.PrivateKey{bcdata.privKeys[0]}) 499 if err != nil { 500 panic(err) 501 } 502 503 buffer := new(bytes.Buffer) 504 err = rlp.Encode(buffer, txtype) 505 assert.Equal(t, nil, err) 506 507 err = rlp.Encode(buffer, []interface{}{ 508 uint64(0), 509 new(big.Int).SetUint64(25 * params.Ston), 510 uint64(100000), 511 *bcdata.addrs[0], 512 wrongEncodedKey, 513 sig, 514 }) 515 require.Equal(t, nil, err) 516 517 err = rlp.DecodeBytes(buffer.Bytes(), tx) 518 require.Equal(t, kerrors.ErrUnserializableKey, err) 519 } 520 521 // case 2. FeeDelegatedAccountUpdate 522 { 523 tx := types.NewTx(&types.TxInternalDataFeeDelegatedAccountUpdate{}) 524 txtype := types.TxTypeFeeDelegatedAccountUpdate 525 526 wrongEncodedKey := []byte{0x10} 527 serializedBytes, err := rlp.EncodeToBytes([]interface{}{ 528 txtype, 529 uint64(0), 530 new(big.Int).SetUint64(25 * params.Ston), 531 uint64(100000), 532 *bcdata.addrs[0], 533 wrongEncodedKey, 534 }) 535 require.Equal(t, nil, err) 536 537 h := rlpHash(struct { 538 Byte []byte 539 ChainId *big.Int 540 R uint 541 S uint 542 }{ 543 serializedBytes, 544 bcdata.bc.Config().ChainID, 545 uint(0), 546 uint(0), 547 }) 548 sig, err := types.NewTxSignaturesWithValues(signer, tx, h, []*ecdsa.PrivateKey{bcdata.privKeys[0]}) 549 if err != nil { 550 panic(err) 551 } 552 553 buffer := new(bytes.Buffer) 554 err = rlp.Encode(buffer, txtype) 555 assert.Equal(t, nil, err) 556 557 err = rlp.Encode(buffer, []interface{}{ 558 uint64(0), 559 new(big.Int).SetUint64(25 * params.Ston), 560 uint64(100000), 561 *bcdata.addrs[0], 562 wrongEncodedKey, 563 sig, 564 *bcdata.addrs[0], 565 sig, 566 }) 567 require.Equal(t, nil, err) 568 569 err = rlp.DecodeBytes(buffer.Bytes(), tx) 570 require.Equal(t, kerrors.ErrUnserializableKey, err) 571 } 572 573 // case 3. FeeDelegatedAccountUpdateWithRatio 574 { 575 tx := types.NewTx(&types.TxInternalDataFeeDelegatedAccountUpdateWithRatio{}) 576 txtype := types.TxTypeFeeDelegatedAccountUpdateWithRatio 577 578 wrongEncodedKey := []byte{0x10} 579 serializedBytes, err := rlp.EncodeToBytes([]interface{}{ 580 txtype, 581 uint64(0), 582 new(big.Int).SetUint64(25 * params.Ston), 583 uint64(100000), 584 *bcdata.addrs[0], 585 types.FeeRatio(10), 586 wrongEncodedKey, 587 }) 588 require.Equal(t, nil, err) 589 590 h := rlpHash(struct { 591 Byte []byte 592 ChainId *big.Int 593 R uint 594 S uint 595 }{ 596 serializedBytes, 597 bcdata.bc.Config().ChainID, 598 uint(0), 599 uint(0), 600 }) 601 sig, err := types.NewTxSignaturesWithValues(signer, tx, h, []*ecdsa.PrivateKey{bcdata.privKeys[0]}) 602 if err != nil { 603 panic(err) 604 } 605 606 buffer := new(bytes.Buffer) 607 err = rlp.Encode(buffer, txtype) 608 assert.Equal(t, nil, err) 609 610 err = rlp.Encode(buffer, []interface{}{ 611 uint64(0), 612 new(big.Int).SetUint64(25 * params.Ston), 613 uint64(100000), 614 *bcdata.addrs[0], 615 wrongEncodedKey, 616 types.FeeRatio(10), 617 sig, 618 *bcdata.addrs[0], 619 sig, 620 }) 621 require.Equal(t, nil, err) 622 623 err = rlp.DecodeBytes(buffer.Bytes(), tx) 624 require.Equal(t, kerrors.ErrUnserializableKey, err) 625 } 626 627 // Below code is used to check the nil dereference case. 628 //txpool := makeTxPool(bcdata, opt.numTransactions) 629 //txpool.AddRemotes(txs) 630 // 631 //for { 632 // if err := bcdata.GenABlockWithTxpool(accountMap, txpool, prof); err != nil { 633 // if err == errEmptyPending { 634 // break 635 // } 636 // t.Fatal(err) 637 // } 638 //} 639 640 if testing.Verbose() { 641 prof.PrintProfileInfo() 642 } 643 } 644 645 // BenchmarkValueTransfer measures TPS without network traffics 646 // while creating a block. As a disclaimer, this function does not tell that Klaytn 647 // can perform this amount of TPS in real environment. 648 func BenchmarkValueTransfer(t *testing.B) { 649 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 650 prof := profile.NewProfiler() 651 opt := testOption{t.N, 2000, 4, 1, []byte{}, makeTransactionsToRandom} 652 653 // Initialize blockchain 654 start := time.Now() 655 bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators) 656 if err != nil { 657 t.Fatal(err) 658 } 659 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 660 defer bcdata.Shutdown() 661 662 // Initialize address-balance map for verification 663 start = time.Now() 664 accountMap := NewAccountMap() 665 if err := accountMap.Initialize(bcdata); err != nil { 666 t.Fatal(err) 667 } 668 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 669 670 // make txpool 671 txpool := makeTxPool(bcdata, t.N) 672 signer := types.MakeSigner(bcdata.bc.Config(), bcdata.bc.CurrentHeader().Number) 673 674 // make t.N transactions 675 txs, err := makeIndependentTransactions(bcdata, accountMap, signer, t.N, nil, []byte{}) 676 if err != nil { 677 t.Fatal(err) 678 } 679 680 t.ResetTimer() 681 682 txpool.AddRemotes(txs) 683 684 for { 685 if err := bcdata.GenABlockWithTxpool(accountMap, txpool, prof); err != nil { 686 if err == errEmptyPending { 687 break 688 } 689 t.Fatal(err) 690 } 691 } 692 t.StopTimer() 693 694 if testing.Verbose() { 695 prof.PrintProfileInfo() 696 } 697 } 698 699 // BenchmarkNewValueTransfer measures TPS without network traffics 700 // while creating a block. As a disclaimer, this function does not tell that Klaytn 701 // can perform this amount of TPS in real environment. 702 func BenchmarkNewValueTransfer(t *testing.B) { 703 log.EnableLogForTest(log.LvlCrit, log.LvlTrace) 704 prof := profile.NewProfiler() 705 opt := testOption{t.N, 2000, 4, 1, []byte{}, makeNewTransactionsToRandom} 706 707 // Initialize blockchain 708 start := time.Now() 709 bcdata, err := NewBCData(opt.numMaxAccounts, opt.numValidators) 710 if err != nil { 711 t.Fatal(err) 712 } 713 prof.Profile("main_init_blockchain", time.Now().Sub(start)) 714 defer bcdata.Shutdown() 715 716 // Initialize address-balance map for verification 717 start = time.Now() 718 accountMap := NewAccountMap() 719 if err := accountMap.Initialize(bcdata); err != nil { 720 t.Fatal(err) 721 } 722 prof.Profile("main_init_accountMap", time.Now().Sub(start)) 723 724 // make txpool 725 txpool := makeTxPool(bcdata, t.N) 726 signer := types.MakeSigner(bcdata.bc.Config(), bcdata.bc.CurrentHeader().Number) 727 728 // make t.N transactions 729 txs, err := makeIndependentTransactions(bcdata, accountMap, signer, t.N, nil, []byte{}) 730 if err != nil { 731 t.Fatal(err) 732 } 733 txpool.AddRemotes(txs) 734 735 t.ResetTimer() 736 for { 737 if err := bcdata.GenABlockWithTxpool(accountMap, txpool, prof); err != nil { 738 if err == errEmptyPending { 739 break 740 } 741 t.Fatal(err) 742 } 743 } 744 t.StopTimer() 745 746 if testing.Verbose() { 747 prof.PrintProfileInfo() 748 } 749 } 750 751 func makeTxPool(bcdata *BCData, txPoolSize int) *blockchain.TxPool { 752 txpoolconfig := blockchain.DefaultTxPoolConfig 753 txpoolconfig.Journal = "" 754 txpoolconfig.ExecSlotsAccount = uint64(txPoolSize) 755 txpoolconfig.NonExecSlotsAccount = uint64(txPoolSize) 756 txpoolconfig.ExecSlotsAll = 2 * uint64(txPoolSize) 757 txpoolconfig.NonExecSlotsAll = 2 * uint64(txPoolSize) 758 return blockchain.NewTxPool(txpoolconfig, bcdata.bc.Config(), bcdata.bc) 759 }