github.com/klaytn/klaytn@v1.10.2/blockchain/tx_pool_test.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/tx_pool_test.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package blockchain 22 23 import ( 24 "crypto/ecdsa" 25 "fmt" 26 "io" 27 "io/ioutil" 28 "math/big" 29 "math/rand" 30 "os" 31 "reflect" 32 "testing" 33 "time" 34 35 "github.com/klaytn/klaytn/blockchain/state" 36 "github.com/klaytn/klaytn/blockchain/types" 37 "github.com/klaytn/klaytn/common" 38 "github.com/klaytn/klaytn/crypto" 39 "github.com/klaytn/klaytn/event" 40 "github.com/klaytn/klaytn/fork" 41 "github.com/klaytn/klaytn/params" 42 "github.com/klaytn/klaytn/rlp" 43 "github.com/klaytn/klaytn/storage/database" 44 "github.com/stretchr/testify/assert" 45 ) 46 47 var ( 48 // testTxPoolConfig is a transaction pool configuration without stateful disk 49 // sideeffects used during testing. 50 testTxPoolConfig TxPoolConfig 51 52 // eip1559Config is a chain config with EIP-1559 enabled at block 0. 53 eip1559Config *params.ChainConfig 54 55 // kip71Config is a chain config with Magma enabled at block 0. 56 kip71Config *params.ChainConfig 57 ) 58 59 func init() { 60 testTxPoolConfig = DefaultTxPoolConfig 61 testTxPoolConfig.Journal = "" 62 63 eip1559Config = params.TestChainConfig.Copy() 64 eip1559Config.IstanbulCompatibleBlock = common.Big0 65 eip1559Config.LondonCompatibleBlock = common.Big0 66 eip1559Config.EthTxTypeCompatibleBlock = common.Big0 67 fork.SetHardForkBlockNumberConfig(eip1559Config) 68 69 kip71Config = params.TestChainConfig.Copy() 70 kip71Config.MagmaCompatibleBlock = common.Big0 71 kip71Config.IstanbulCompatibleBlock = common.Big0 72 kip71Config.LondonCompatibleBlock = common.Big0 73 kip71Config.EthTxTypeCompatibleBlock = common.Big0 74 kip71Config.Governance = ¶ms.GovernanceConfig{KIP71: params.GetDefaultKIP71Config()} 75 76 InitDeriveSha(params.TestChainConfig) 77 } 78 79 type testBlockChain struct { 80 statedb *state.StateDB 81 gasLimit uint64 82 chainHeadFeed *event.Feed 83 } 84 85 func (pool *TxPool) SetBaseFee(baseFee *big.Int) { 86 pool.gasPrice = baseFee 87 } 88 89 func (bc *testBlockChain) CurrentBlock() *types.Block { 90 return types.NewBlock(&types.Header{Number: big.NewInt(0)}, nil, nil) 91 } 92 93 func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 94 return bc.CurrentBlock() 95 } 96 97 func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { 98 return bc.statedb, nil 99 } 100 101 func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 102 return bc.chainHeadFeed.Subscribe(ch) 103 } 104 105 func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction { 106 return pricedTransaction(nonce, gaslimit, big.NewInt(1), key) 107 } 108 109 func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 110 tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xAAAA"), big.NewInt(100), gaslimit, gasprice, nil), 111 types.LatestSignerForChainID(params.TestChainConfig.ChainID), key) 112 return tx 113 } 114 115 func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, bytes uint64) *types.Transaction { 116 data := make([]byte, bytes) 117 rand.Read(data) 118 119 tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xAAAA"), big.NewInt(0), gaslimit, gasprice, data), 120 types.LatestSignerForChainID(params.TestChainConfig.ChainID), key) 121 return tx 122 } 123 124 func dynamicFeeTx(nonce uint64, gaslimit uint64, gasFee *big.Int, tip *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 125 dynamicTx := types.NewTx(&types.TxInternalDataEthereumDynamicFee{ 126 ChainID: params.TestChainConfig.ChainID, 127 AccountNonce: nonce, 128 GasTipCap: tip, 129 GasFeeCap: gasFee, 130 GasLimit: gaslimit, 131 Recipient: &common.Address{}, 132 Amount: big.NewInt(100), 133 Payload: nil, 134 AccessList: nil, 135 }) 136 137 signedTx, _ := types.SignTx(dynamicTx, types.LatestSignerForChainID(params.TestChainConfig.ChainID), key) 138 return signedTx 139 } 140 141 func cancelTx(nonce uint64, gasLimit uint64, gasPrice *big.Int, from common.Address, key *ecdsa.PrivateKey) *types.Transaction { 142 d, err := types.NewTxInternalDataWithMap(types.TxTypeCancel, map[types.TxValueKeyType]interface{}{ 143 types.TxValueKeyNonce: nonce, 144 types.TxValueKeyGasLimit: gasLimit, 145 types.TxValueKeyGasPrice: gasPrice, 146 types.TxValueKeyFrom: from, 147 }) 148 if err != nil { 149 // Since we do not have testing.T here, call panic() instead of t.Fatal(). 150 panic(err) 151 } 152 cancelTx := types.NewTx(d) 153 signedTx, _ := types.SignTx(cancelTx, types.LatestSignerForChainID(params.TestChainConfig.ChainID), key) 154 return signedTx 155 } 156 157 func feeDelegatedTx(nonce uint64, gaslimit uint64, gasPrice *big.Int, amount *big.Int, senderPrvKey *ecdsa.PrivateKey, feePayerPrvKey *ecdsa.PrivateKey) *types.Transaction { 158 delegatedTx := types.NewTx(&types.TxInternalDataFeeDelegatedValueTransfer{ 159 AccountNonce: nonce, 160 Price: gasPrice, 161 GasLimit: gaslimit, 162 Recipient: common.Address{}, 163 Amount: amount, 164 From: crypto.PubkeyToAddress(senderPrvKey.PublicKey), 165 FeePayer: crypto.PubkeyToAddress(feePayerPrvKey.PublicKey), 166 }) 167 168 types.SignTxAsFeePayer(delegatedTx, types.LatestSignerForChainID(params.TestChainConfig.ChainID), feePayerPrvKey) 169 signedTx, _ := types.SignTx(delegatedTx, types.LatestSignerForChainID(params.TestChainConfig.ChainID), senderPrvKey) 170 return signedTx 171 } 172 173 func feeDelegatedWithRatioTx(nonce uint64, gaslimit uint64, gasPrice *big.Int, amount *big.Int, senderPrvKey *ecdsa.PrivateKey, feePayerPrvKey *ecdsa.PrivateKey, ratio types.FeeRatio) *types.Transaction { 174 delegatedTx := types.NewTx(&types.TxInternalDataFeeDelegatedValueTransferWithRatio{ 175 AccountNonce: nonce, 176 Price: gasPrice, 177 GasLimit: gaslimit, 178 Recipient: common.Address{}, 179 Amount: amount, 180 From: crypto.PubkeyToAddress(senderPrvKey.PublicKey), 181 FeePayer: crypto.PubkeyToAddress(feePayerPrvKey.PublicKey), 182 FeeRatio: ratio, 183 }) 184 185 types.SignTxAsFeePayer(delegatedTx, types.LatestSignerForChainID(params.TestChainConfig.ChainID), feePayerPrvKey) 186 signedTx, _ := types.SignTx(delegatedTx, types.LatestSignerForChainID(params.TestChainConfig.ChainID), senderPrvKey) 187 return signedTx 188 } 189 190 func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { 191 return setupTxPoolWithConfig(params.TestChainConfig) 192 } 193 194 func setupTxPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) { 195 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 196 blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)} 197 198 key, _ := crypto.GenerateKey() 199 pool := NewTxPool(testTxPoolConfig, config, blockchain) 200 201 return pool, key 202 } 203 204 // validateTxPoolInternals checks various consistency invariants within the pool. 205 func validateTxPoolInternals(pool *TxPool) error { 206 pool.mu.RLock() 207 defer pool.mu.RUnlock() 208 209 // Ensure the total transaction set is consistent with pending + queued 210 pending, queued := pool.stats() 211 if total := pool.all.Count(); total != pending+queued { 212 return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued) 213 } 214 if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued { 215 return fmt.Errorf("total priced transaction count %d != %d pending + %d queued", priced, pending, queued) 216 } 217 // Ensure the next nonce to assign is the correct one 218 for addr, txs := range pool.pending { 219 // Find the last transaction 220 var last uint64 221 for nonce := range txs.txs.items { 222 if last < nonce { 223 last = nonce 224 } 225 } 226 if nonce := pool.getPendingNonce(addr); nonce != last+1 { 227 return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1) 228 } 229 } 230 return nil 231 } 232 233 // validateEvents checks that the correct number of transaction addition events 234 // were fired on the pool's event feed. 235 func validateEvents(events chan NewTxsEvent, count int) error { 236 var received []*types.Transaction 237 238 for len(received) < count { 239 select { 240 case ev := <-events: 241 received = append(received, ev.Txs...) 242 case <-time.After(time.Second): 243 return fmt.Errorf("event #%d not fired", len(received)) 244 } 245 } 246 if len(received) > count { 247 return fmt.Errorf("more than %d events fired: %v", count, received[count:]) 248 } 249 select { 250 case ev := <-events: 251 return fmt.Errorf("more than %d events fired: %v", count, ev.Txs) 252 253 case <-time.After(50 * time.Millisecond): 254 // This branch should be "default", but it's a data race between goroutines, 255 // reading the event channel and pushing into it, so better wait a bit ensuring 256 // really nothing gets injected. 257 } 258 return nil 259 } 260 261 func deriveSender(tx *types.Transaction) (common.Address, error) { 262 signer := types.LatestSignerForChainID(params.TestChainConfig.ChainID) 263 return types.Sender(signer, tx) 264 } 265 266 type testChain struct { 267 *testBlockChain 268 address common.Address 269 trigger *bool 270 } 271 272 // testChain.State() is used multiple times to reset the pending state. 273 // when simulate is true it will create a state that indicates 274 // that tx0 and tx1 are included in the chain. 275 func (c *testChain) State() (*state.StateDB, error) { 276 // delay "state change" by one. The tx pool fetches the 277 // state multiple times and by delaying it a bit we simulate 278 // a state change between those fetches. 279 stdb := c.statedb 280 if *c.trigger { 281 c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 282 // simulate that the new head block included tx0 and tx1 283 c.statedb.SetNonce(c.address, 2) 284 c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.KLAY)) 285 *c.trigger = false 286 } 287 return stdb, nil 288 } 289 290 // This test simulates a scenario where a new block is imported during a 291 // state reset and tests whether the pending state is in sync with the 292 // block head event that initiated the resetState(). 293 func TestStateChangeDuringTransactionPoolReset(t *testing.T) { 294 t.Parallel() 295 296 var ( 297 key, _ = crypto.GenerateKey() 298 address = crypto.PubkeyToAddress(key.PublicKey) 299 statedb, _ = state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 300 trigger = false 301 ) 302 303 // setup pool with 2 transaction in it 304 statedb.SetBalance(address, new(big.Int).SetUint64(params.KLAY)) 305 blockchain := &testChain{&testBlockChain{statedb, 1000000000, new(event.Feed)}, address, &trigger} 306 307 tx0 := transaction(0, 100000, key) 308 tx1 := transaction(1, 100000, key) 309 310 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 311 defer pool.Stop() 312 313 nonce := pool.GetPendingNonce(address) 314 if nonce != 0 { 315 t.Fatalf("Invalid nonce, want 0, got %d", nonce) 316 } 317 318 pool.AddRemotes(types.Transactions{tx0, tx1}) 319 320 nonce = pool.GetPendingNonce(address) 321 if nonce != 2 { 322 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 323 } 324 325 // trigger state change in the background 326 trigger = true 327 328 pool.lockedReset(nil, nil) 329 330 _, err := pool.Pending() 331 if err != nil { 332 t.Fatalf("Could not fetch pending transactions: %v", err) 333 } 334 nonce = pool.GetPendingNonce(address) 335 if nonce != 2 { 336 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 337 } 338 } 339 340 func testAddBalance(pool *TxPool, addr common.Address, amount *big.Int) { 341 pool.mu.Lock() 342 pool.currentState.AddBalance(addr, amount) 343 pool.mu.Unlock() 344 } 345 346 func testSetNonce(pool *TxPool, addr common.Address, nonce uint64) { 347 pool.mu.Lock() 348 pool.currentState.SetNonce(addr, nonce) 349 pool.mu.Unlock() 350 } 351 352 func TestHomesteadTransaction(t *testing.T) { 353 t.Parallel() 354 baseFee := big.NewInt(30) 355 356 pool, _ := setupTxPoolWithConfig(kip71Config) 357 defer pool.Stop() 358 pool.SetBaseFee(baseFee) 359 360 rlpTx := common.Hex2Bytes("f87e8085174876e800830186a08080ad601f80600e600039806000f350fe60003681823780368234f58015156014578182fd5b80825250506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222") 361 tx := new(types.Transaction) 362 363 err := rlp.DecodeBytes(rlpTx, tx) 364 assert.NoError(t, err) 365 366 from, err := types.EIP155Signer{}.Sender(tx) 367 assert.NoError(t, err) 368 assert.Equal(t, "0x4c8D290a1B368ac4728d83a9e8321fC3af2b39b1", from.String()) 369 370 testAddBalance(pool, from, new(big.Int).Mul(big.NewInt(10), big.NewInt(params.KLAY))) 371 err = pool.AddRemote(tx) 372 assert.NoError(t, err) 373 } 374 375 func TestInvalidTransactions(t *testing.T) { 376 t.Parallel() 377 378 pool, key := setupTxPool() 379 defer pool.Stop() 380 381 tx := transaction(0, 100, key) 382 from, _ := deriveSender(tx) 383 384 testAddBalance(pool, from, big.NewInt(1)) 385 if err := pool.AddRemote(tx); err != ErrInsufficientFundsFrom { 386 t.Error("expected", ErrInsufficientFundsFrom, "got", err) 387 } 388 389 balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) 390 testAddBalance(pool, from, balance) 391 if err := pool.AddRemote(tx); err != ErrIntrinsicGas { 392 t.Error("expected", ErrIntrinsicGas, "got", err) 393 } 394 395 testSetNonce(pool, from, 1) 396 testAddBalance(pool, from, big.NewInt(0xffffffffffffff)) 397 tx = transaction(0, 100000, key) 398 if err := pool.AddRemote(tx); err != ErrNonceTooLow { 399 t.Error("expected", ErrNonceTooLow) 400 } 401 402 tx = transaction(1, 100000, key) 403 pool.SetBaseFee(big.NewInt(1000)) 404 405 // NOTE-Klaytn We only accept txs with an expected gas price only 406 // regardless of local or remote. 407 if err := pool.AddRemote(tx); err != ErrInvalidUnitPrice { 408 t.Error("expected", ErrInvalidUnitPrice, "got", err) 409 } 410 if err := pool.AddLocal(tx); err != ErrInvalidUnitPrice { 411 t.Error("expected", ErrInvalidUnitPrice, "got", err) 412 } 413 } 414 415 func TestInvalidTransactionsMagma(t *testing.T) { 416 t.Parallel() 417 418 pool, key := setupTxPoolWithConfig(kip71Config) 419 pool.SetBaseFee(big.NewInt(1)) 420 defer pool.Stop() 421 422 tx := transaction(0, 100, key) 423 from, _ := deriveSender(tx) 424 425 testAddBalance(pool, from, big.NewInt(1)) 426 if err := pool.AddRemote(tx); err != ErrInsufficientFundsFrom { 427 t.Error("expected", ErrInsufficientFundsFrom, "got", err) 428 } 429 430 balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) 431 testAddBalance(pool, from, balance) 432 if err := pool.AddRemote(tx); err != ErrIntrinsicGas { 433 t.Error("expected", ErrIntrinsicGas, "got", err) 434 } 435 436 testSetNonce(pool, from, 1) 437 testAddBalance(pool, from, big.NewInt(0xffffffffffffff)) 438 tx = transaction(0, 100000, key) 439 if err := pool.AddRemote(tx); err != ErrNonceTooLow { 440 t.Error("expected", ErrNonceTooLow) 441 } 442 443 tx = transaction(1, 100000, key) 444 pool.SetBaseFee(big.NewInt(1000)) 445 446 // NOTE-Klaytn if the gasPrice in tx is lower than txPool's 447 // It should return ErrGasPriceBelowBaseFee error after magma hardfork 448 if err := pool.AddRemote(tx); err != ErrGasPriceBelowBaseFee { 449 t.Error("expected", ErrGasPriceBelowBaseFee, "got", err) 450 } 451 if err := pool.AddLocal(tx); err != ErrGasPriceBelowBaseFee { 452 t.Error("expected", ErrGasPriceBelowBaseFee, "got", err) 453 } 454 } 455 456 func genAnchorTx(nonce uint64) *types.Transaction { 457 key, _ := crypto.HexToECDSA("45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") 458 from := crypto.PubkeyToAddress(key.PublicKey) 459 460 gasLimit := uint64(1000000) 461 gasPrice := big.NewInt(1) 462 463 data := []byte{0x11, 0x22} 464 values := map[types.TxValueKeyType]interface{}{ 465 types.TxValueKeyNonce: nonce, 466 types.TxValueKeyFrom: from, 467 types.TxValueKeyGasLimit: gasLimit, 468 types.TxValueKeyGasPrice: gasPrice, 469 types.TxValueKeyAnchoredData: data, 470 } 471 472 tx, _ := types.NewTransactionWithMap(types.TxTypeChainDataAnchoring, values) 473 474 signer := types.MakeSigner(params.BFTTestChainConfig, big.NewInt(2)) 475 tx.Sign(signer, key) 476 477 return tx 478 } 479 480 func TestAnchorTransactions(t *testing.T) { 481 t.Parallel() 482 483 pool, _ := setupTxPool() 484 defer pool.Stop() 485 486 poolAllow, _ := setupTxPool() 487 poolAllow.config.AllowLocalAnchorTx = true 488 defer poolAllow.Stop() 489 490 tx1 := genAnchorTx(1) 491 tx2 := genAnchorTx(2) 492 493 from, _ := tx1.From() 494 testAddBalance(pool, from, big.NewInt(10000000)) 495 testAddBalance(poolAllow, from, big.NewInt(10000000)) 496 497 // default txPool 498 { 499 err := pool.AddRemote(tx1) 500 assert.NoError(t, err) 501 502 err = pool.AddLocal(tx2) 503 assert.Error(t, errNotAllowedAnchoringTx, err) 504 } 505 506 // txPool which allow locally submitted anchor txs 507 { 508 err := poolAllow.AddRemote(tx1) 509 assert.NoError(t, err) 510 511 err = poolAllow.AddLocal(tx2) 512 assert.NoError(t, err) 513 } 514 } 515 516 func TestTransactionQueue(t *testing.T) { 517 t.Parallel() 518 519 pool, key := setupTxPool() 520 defer pool.Stop() 521 522 tx := transaction(0, 100, key) 523 from, _ := deriveSender(tx) 524 testAddBalance(pool, from, big.NewInt(1000)) 525 pool.lockedReset(nil, nil) 526 pool.enqueueTx(tx.Hash(), tx) 527 528 pool.promoteExecutables([]common.Address{from}) 529 if len(pool.pending) != 1 { 530 t.Error("expected valid txs to be 1 is", len(pool.pending)) 531 } 532 533 tx = transaction(1, 100, key) 534 from, _ = deriveSender(tx) 535 testSetNonce(pool, from, 2) 536 pool.enqueueTx(tx.Hash(), tx) 537 pool.promoteExecutables([]common.Address{from}) 538 if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok { 539 t.Error("expected transaction to be in tx pool") 540 } 541 542 if len(pool.queue) > 0 { 543 t.Error("expected transaction queue to be empty. is", len(pool.queue)) 544 } 545 546 pool, key = setupTxPool() 547 defer pool.Stop() 548 549 tx1 := transaction(0, 100, key) 550 tx2 := transaction(10, 100, key) 551 tx3 := transaction(11, 100, key) 552 from, _ = deriveSender(tx1) 553 pool.currentState.AddBalance(from, big.NewInt(1000)) 554 pool.lockedReset(nil, nil) 555 556 pool.enqueueTx(tx1.Hash(), tx1) 557 pool.enqueueTx(tx2.Hash(), tx2) 558 pool.enqueueTx(tx3.Hash(), tx3) 559 560 pool.promoteExecutables([]common.Address{from}) 561 562 if len(pool.pending) != 1 { 563 t.Error("expected tx pool to be 1, got", len(pool.pending)) 564 } 565 if pool.queue[from].Len() != 2 { 566 t.Error("expected len(queue) == 2, got", pool.queue[from].Len()) 567 } 568 } 569 570 func TestTransactionNegativeValue(t *testing.T) { 571 t.Parallel() 572 573 pool, key := setupTxPool() 574 defer pool.Stop() 575 576 signer := types.LatestSignerForChainID(params.TestChainConfig.ChainID) 577 tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), signer, key) 578 from, _ := deriveSender(tx) 579 pool.currentState.AddBalance(from, big.NewInt(1)) 580 if err := pool.AddRemote(tx); err != ErrNegativeValue { 581 t.Error("expected", ErrNegativeValue, "got", err) 582 } 583 } 584 585 func TestTransactionChainFork(t *testing.T) { 586 t.Parallel() 587 588 pool, key := setupTxPool() 589 defer pool.Stop() 590 591 addr := crypto.PubkeyToAddress(key.PublicKey) 592 resetState := func() { 593 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 594 statedb.AddBalance(addr, big.NewInt(100000000000000)) 595 596 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 597 pool.lockedReset(nil, nil) 598 } 599 resetState() 600 601 tx := transaction(0, 100000, key) 602 if _, err := pool.add(tx, false); err != nil { 603 t.Error("didn't expect error", err) 604 } 605 pool.removeTx(tx.Hash(), true) 606 607 // reset the pool's internal state 608 resetState() 609 if _, err := pool.add(tx, false); err != nil { 610 t.Error("didn't expect error", err) 611 } 612 } 613 614 func TestTransactionDoubleNonce(t *testing.T) { 615 t.Parallel() 616 617 pool, key := setupTxPool() 618 defer pool.Stop() 619 620 addr := crypto.PubkeyToAddress(key.PublicKey) 621 resetState := func() { 622 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 623 statedb.AddBalance(addr, big.NewInt(100000000000000)) 624 625 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 626 pool.lockedReset(nil, nil) 627 } 628 resetState() 629 630 signer := types.LatestSignerForChainID(params.TestChainConfig.ChainID) 631 tx1, _ := types.SignTx(types.NewTransaction(0, common.HexToAddress("0xAAAA"), big.NewInt(100), 100000, big.NewInt(1), nil), signer, key) 632 tx2, _ := types.SignTx(types.NewTransaction(0, common.HexToAddress("0xAAAA"), big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key) 633 tx3, _ := types.SignTx(types.NewTransaction(0, common.HexToAddress("0xAAAA"), big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key) 634 635 // NOTE-Klaytn Add the first two transaction, ensure the first one stays only 636 if replace, err := pool.add(tx1, false); err != nil || replace { 637 t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace) 638 } 639 if replace, err := pool.add(tx2, false); err == nil || replace { 640 t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace) 641 } 642 pool.promoteExecutables([]common.Address{addr}) 643 if pool.pending[addr].Len() != 1 { 644 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 645 } 646 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx1.Hash() { 647 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 648 } 649 // NOTE-Klaytn Add the third transaction and ensure it's not saved 650 pool.add(tx3, false) 651 pool.promoteExecutables([]common.Address{addr}) 652 if pool.pending[addr].Len() != 1 { 653 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 654 } 655 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx1.Hash() { 656 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 657 } 658 // Ensure the total transaction count is correct 659 if pool.all.Count() != 1 { 660 t.Error("expected 1 total transactions, got", pool.all.Count()) 661 } 662 } 663 664 func TestTransactionMissingNonce(t *testing.T) { 665 t.Parallel() 666 667 pool, key := setupTxPool() 668 defer pool.Stop() 669 670 addr := crypto.PubkeyToAddress(key.PublicKey) 671 testAddBalance(pool, addr, big.NewInt(100000000000000)) 672 tx := transaction(1, 100000, key) 673 if _, err := pool.add(tx, false); err != nil { 674 t.Error("didn't expect error", err) 675 } 676 if len(pool.pending) != 0 { 677 t.Error("expected 0 pending transactions, got", len(pool.pending)) 678 } 679 if pool.queue[addr].Len() != 1 { 680 t.Error("expected 1 queued transaction, got", pool.queue[addr].Len()) 681 } 682 if pool.all.Count() != 1 { 683 t.Error("expected 1 total transactions, got", pool.all.Count()) 684 } 685 } 686 687 func TestTransactionNonceRecovery(t *testing.T) { 688 t.Parallel() 689 690 const n = 10 691 pool, key := setupTxPool() 692 defer pool.Stop() 693 694 addr := crypto.PubkeyToAddress(key.PublicKey) 695 testSetNonce(pool, addr, n) 696 testAddBalance(pool, addr, big.NewInt(100000000000000)) 697 pool.lockedReset(nil, nil) 698 699 tx := transaction(n, 100000, key) 700 if err := pool.AddRemote(tx); err != nil { 701 t.Error(err) 702 } 703 // simulate some weird re-order of transactions and missing nonce(s) 704 testSetNonce(pool, addr, n-1) 705 pool.lockedReset(nil, nil) 706 if fn := pool.GetPendingNonce(addr); fn != n-1 { 707 t.Errorf("expected nonce to be %d, got %d", n-1, fn) 708 } 709 } 710 711 // Tests that if an account runs out of funds, any pending and queued transactions 712 // are dropped. 713 func TestTransactionDropping(t *testing.T) { 714 t.Parallel() 715 716 // Create a test account and fund it 717 pool, key := setupTxPool() 718 defer pool.Stop() 719 720 account := crypto.PubkeyToAddress(key.PublicKey) 721 testAddBalance(pool, account, big.NewInt(1000)) 722 723 // Add some pending and some queued transactions 724 var ( 725 tx0 = transaction(0, 100, key) 726 tx1 = transaction(1, 200, key) 727 tx2 = transaction(2, 300, key) 728 tx10 = transaction(10, 100, key) 729 tx11 = transaction(11, 200, key) 730 tx12 = transaction(12, 300, key) 731 ) 732 pool.promoteTx(account, tx0.Hash(), tx0) 733 pool.promoteTx(account, tx1.Hash(), tx1) 734 pool.promoteTx(account, tx2.Hash(), tx2) 735 pool.enqueueTx(tx10.Hash(), tx10) 736 pool.enqueueTx(tx11.Hash(), tx11) 737 pool.enqueueTx(tx12.Hash(), tx12) 738 739 // Check that pre and post validations leave the pool as is 740 if pool.pending[account].Len() != 3 { 741 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 742 } 743 if pool.queue[account].Len() != 3 { 744 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 745 } 746 if pool.all.Count() != 6 { 747 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) 748 } 749 pool.lockedReset(nil, nil) 750 if pool.pending[account].Len() != 3 { 751 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 752 } 753 if pool.queue[account].Len() != 3 { 754 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 755 } 756 if pool.all.Count() != 6 { 757 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) 758 } 759 // Reduce the balance of the account, and check that invalidated transactions are dropped 760 testAddBalance(pool, account, big.NewInt(-650)) 761 pool.lockedReset(nil, nil) 762 763 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 764 t.Errorf("funded pending transaction missing: %v", tx0) 765 } 766 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok { 767 t.Errorf("funded pending transaction missing: %v", tx0) 768 } 769 if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok { 770 t.Errorf("out-of-fund pending transaction present: %v", tx1) 771 } 772 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 773 t.Errorf("funded queued transaction missing: %v", tx10) 774 } 775 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok { 776 t.Errorf("funded queued transaction missing: %v", tx10) 777 } 778 if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok { 779 t.Errorf("out-of-fund queued transaction present: %v", tx11) 780 } 781 if pool.all.Count() != 4 { 782 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 4) 783 } 784 } 785 786 // Tests that if a transaction is dropped from the current pending pool (e.g. out 787 // of fund), all consecutive (still valid, but not executable) transactions are 788 // postponed back into the future queue to prevent broadcasting them. 789 func TestTransactionPostponing(t *testing.T) { 790 t.Parallel() 791 792 // Create the pool to test the postponing with 793 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 794 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 795 796 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 797 defer pool.Stop() 798 799 // Create two test accounts to produce different gap profiles with 800 keys := make([]*ecdsa.PrivateKey, 2) 801 accs := make([]common.Address, len(keys)) 802 803 for i := 0; i < len(keys); i++ { 804 keys[i], _ = crypto.GenerateKey() 805 accs[i] = crypto.PubkeyToAddress(keys[i].PublicKey) 806 807 testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(50100)) 808 } 809 // Add a batch consecutive pending transactions for validation 810 txs := []*types.Transaction{} 811 for i, key := range keys { 812 for j := 0; j < 100; j++ { 813 var tx *types.Transaction 814 if (i+j)%2 == 0 { 815 tx = transaction(uint64(j), 25000, key) 816 } else { 817 tx = transaction(uint64(j), 50000, key) 818 } 819 txs = append(txs, tx) 820 } 821 } 822 for i, err := range pool.AddRemotes(txs) { 823 if err != nil { 824 t.Fatalf("tx %d: failed to add transactions: %v", i, err) 825 } 826 } 827 // Check that pre and post validations leave the pool as is 828 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 829 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 830 } 831 if len(pool.queue) != 0 { 832 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 833 } 834 if pool.all.Count() != len(txs) { 835 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) 836 } 837 pool.lockedReset(nil, nil) 838 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 839 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 840 } 841 if len(pool.queue) != 0 { 842 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 843 } 844 if pool.all.Count() != len(txs) { 845 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) 846 } 847 // Reduce the balance of the account, and check that transactions are reorganised 848 for _, addr := range accs { 849 testAddBalance(pool, addr, big.NewInt(-1)) 850 } 851 pool.lockedReset(nil, nil) 852 853 // The first account's first transaction remains valid, check that subsequent 854 // ones are either filtered out, or queued up for later. 855 if _, ok := pool.pending[accs[0]].txs.items[txs[0].Nonce()]; !ok { 856 t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txs[0]) 857 } 858 if _, ok := pool.queue[accs[0]].txs.items[txs[0].Nonce()]; ok { 859 t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txs[0]) 860 } 861 for i, tx := range txs[1:100] { 862 if i%2 == 1 { 863 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 864 t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) 865 } 866 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; !ok { 867 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) 868 } 869 } else { 870 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 871 t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) 872 } 873 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; ok { 874 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) 875 } 876 } 877 } 878 // The second account's first transaction got invalid, check that all transactions 879 // are either filtered out, or queued up for later. 880 if pool.pending[accs[1]] != nil { 881 t.Errorf("invalidated account still has pending transactions") 882 } 883 for i, tx := range txs[100:] { 884 if i%2 == 1 { 885 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; !ok { 886 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", 100+i, tx) 887 } 888 } else { 889 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; ok { 890 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", 100+i, tx) 891 } 892 } 893 } 894 if pool.all.Count() != len(txs)/2 { 895 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)/2) 896 } 897 } 898 899 // Tests that if the transaction pool has both executable and non-executable 900 // transactions from an origin account, filling the nonce gap moves all queued 901 // ones into the pending pool. 902 func TestTransactionGapFilling(t *testing.T) { 903 t.Parallel() 904 905 // Create a test account and fund it 906 pool, key := setupTxPool() 907 defer pool.Stop() 908 909 account := crypto.PubkeyToAddress(key.PublicKey) 910 testAddBalance(pool, account, big.NewInt(1000000)) 911 912 // Keep track of transaction events to ensure all executables get announced 913 events := make(chan NewTxsEvent, testTxPoolConfig.NonExecSlotsAccount+5) 914 sub := pool.txFeed.Subscribe(events) 915 defer sub.Unsubscribe() 916 917 // Create a pending and a queued transaction with a nonce-gap in between 918 if err := pool.AddRemote(transaction(0, 100000, key)); err != nil { 919 t.Fatalf("failed to add pending transaction: %v", err) 920 } 921 if err := pool.AddRemote(transaction(2, 100000, key)); err != nil { 922 t.Fatalf("failed to add queued transaction: %v", err) 923 } 924 pending, queued := pool.Stats() 925 if pending != 1 { 926 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1) 927 } 928 if queued != 1 { 929 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 930 } 931 if err := validateEvents(events, 1); err != nil { 932 t.Fatalf("original event firing failed: %v", err) 933 } 934 if err := validateTxPoolInternals(pool); err != nil { 935 t.Fatalf("pool internal state corrupted: %v", err) 936 } 937 // Fill the nonce gap and ensure all transactions become pending 938 if err := pool.AddRemote(transaction(1, 100000, key)); err != nil { 939 t.Fatalf("failed to add gapped transaction: %v", err) 940 } 941 pending, queued = pool.Stats() 942 if pending != 3 { 943 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 944 } 945 if queued != 0 { 946 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 947 } 948 if err := validateEvents(events, 2); err != nil { 949 t.Fatalf("gap-filling event firing failed: %v", err) 950 } 951 if err := validateTxPoolInternals(pool); err != nil { 952 t.Fatalf("pool internal state corrupted: %v", err) 953 } 954 } 955 956 // Tests that if the transaction count belonging to a single account goes above 957 // some threshold, the higher transactions are dropped to prevent DOS attacks. 958 func TestTransactionQueueAccountLimiting(t *testing.T) { 959 t.Parallel() 960 961 // Create a test account and fund it 962 pool, key := setupTxPool() 963 defer pool.Stop() 964 965 account := crypto.PubkeyToAddress(key.PublicKey) 966 testAddBalance(pool, account, big.NewInt(1000000)) 967 968 // Keep queuing up transactions and make sure all above a limit are dropped 969 for i := uint64(1); i <= testTxPoolConfig.NonExecSlotsAccount+5; i++ { 970 if err := pool.AddRemote(transaction(i, 100000, key)); err != nil { 971 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 972 } 973 if len(pool.pending) != 0 { 974 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0) 975 } 976 if i <= testTxPoolConfig.NonExecSlotsAccount { 977 if pool.queue[account].Len() != int(i) { 978 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i) 979 } 980 } else { 981 if pool.queue[account].Len() != int(testTxPoolConfig.NonExecSlotsAccount) { 982 t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.NonExecSlotsAccount) 983 } 984 } 985 } 986 if pool.all.Count() != int(testTxPoolConfig.NonExecSlotsAccount) { 987 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.NonExecSlotsAccount) 988 } 989 } 990 991 // Tests that if the transaction count belonging to multiple accounts go above 992 // some threshold, the higher transactions are dropped to prevent DOS attacks. 993 // 994 // This logic should not hold for local transactions, unless the local tracking 995 // mechanism is disabled. 996 func TestTransactionQueueGlobalLimiting(t *testing.T) { 997 testTransactionQueueGlobalLimiting(t, false) 998 } 999 1000 func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { 1001 testTransactionQueueGlobalLimiting(t, true) 1002 } 1003 1004 func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { 1005 t.Parallel() 1006 1007 // Create the pool to test the limit enforcement with 1008 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 1009 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1010 1011 config := testTxPoolConfig 1012 config.NoLocals = nolocals 1013 config.NonExecSlotsAll = config.NonExecSlotsAccount*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) 1014 1015 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1016 defer pool.Stop() 1017 1018 // Create a number of test accounts and fund them (last one will be the local) 1019 keys := make([]*ecdsa.PrivateKey, 5) 1020 for i := 0; i < len(keys); i++ { 1021 keys[i], _ = crypto.GenerateKey() 1022 testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1023 } 1024 local := keys[len(keys)-1] 1025 1026 // Generate and queue a batch of transactions 1027 nonces := make(map[common.Address]uint64) 1028 1029 txs := make(types.Transactions, 0, 3*config.NonExecSlotsAll) 1030 for len(txs) < cap(txs) { 1031 key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account 1032 addr := crypto.PubkeyToAddress(key.PublicKey) 1033 1034 txs = append(txs, transaction(nonces[addr]+1, 100000, key)) 1035 nonces[addr]++ 1036 } 1037 // Import the batch and verify that limits have been enforced 1038 pool.AddRemotes(txs) 1039 1040 queued := 0 1041 for addr, list := range pool.queue { 1042 if list.Len() > int(config.NonExecSlotsAccount) { 1043 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.NonExecSlotsAccount) 1044 } 1045 queued += list.Len() 1046 } 1047 if queued > int(config.NonExecSlotsAll) { 1048 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.NonExecSlotsAll) 1049 } 1050 // Generate a batch of transactions from the local account and import them 1051 txs = txs[:0] 1052 for i := uint64(0); i < 3*config.NonExecSlotsAll; i++ { 1053 txs = append(txs, transaction(i+1, 100000, local)) 1054 } 1055 pool.AddLocals(txs) 1056 1057 // If locals are disabled, the previous eviction algorithm should apply here too 1058 if nolocals { 1059 queued := 0 1060 for addr, list := range pool.queue { 1061 if list.Len() > int(config.NonExecSlotsAccount) { 1062 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.NonExecSlotsAccount) 1063 } 1064 queued += list.Len() 1065 } 1066 if queued > int(config.NonExecSlotsAll) { 1067 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.NonExecSlotsAll) 1068 } 1069 } else { 1070 // Local exemptions are enabled, make sure the local account owned the queue 1071 if len(pool.queue) != 1 { 1072 t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1) 1073 } 1074 // Also ensure no local transactions are ever dropped, even if above global limits 1075 if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.NonExecSlotsAll { 1076 t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.NonExecSlotsAll) 1077 } 1078 } 1079 } 1080 1081 // Tests that if an account remains idle for a prolonged amount of time, any 1082 // non-executable transactions queued up are dropped to prevent wasting resources 1083 // on shuffling them around. 1084 // 1085 // This logic should not hold for local transactions, unless the local tracking 1086 // mechanism is disabled. 1087 func TestTransactionQueueTimeLimitingKeepLocals(t *testing.T) { 1088 testTransactionQueueTimeLimiting(t, false, true) 1089 } 1090 1091 func TestTransactionQueueTimeLimitingNotKeepLocals(t *testing.T) { 1092 testTransactionQueueTimeLimiting(t, false, false) 1093 } 1094 1095 func TestTransactionQueueTimeLimitingNoLocalsKeepLocals(t *testing.T) { 1096 testTransactionQueueTimeLimiting(t, true, true) 1097 } 1098 1099 func TestTransactionQueueTimeLimitingNoLocalsNoKeepLocals(t *testing.T) { 1100 testTransactionQueueTimeLimiting(t, true, false) 1101 } 1102 1103 func testTransactionQueueTimeLimiting(t *testing.T, nolocals, keepLocals bool) { 1104 // Reduce the eviction interval to a testable amount 1105 defer func(old time.Duration) { evictionInterval = old }(evictionInterval) 1106 evictionInterval = time.Second 1107 1108 // Create the pool to test the non-expiration enforcement 1109 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 1110 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1111 1112 config := testTxPoolConfig 1113 config.Lifetime = 5 * time.Second 1114 config.NoLocals = nolocals 1115 config.KeepLocals = keepLocals 1116 1117 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1118 defer pool.Stop() 1119 1120 // Create two test accounts to ensure remotes expire but locals do not 1121 local, _ := crypto.GenerateKey() 1122 remote, _ := crypto.GenerateKey() 1123 1124 testAddBalance(pool, crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 1125 testAddBalance(pool, crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 1126 1127 // Add the two transactions and ensure they both are queued up 1128 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 1129 t.Fatalf("failed to add local transaction: %v", err) 1130 } 1131 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil { 1132 t.Fatalf("failed to add remote transaction: %v", err) 1133 } 1134 pending, queued := pool.Stats() 1135 if pending != 0 { 1136 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1137 } 1138 if queued != 2 { 1139 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1140 } 1141 if err := validateTxPoolInternals(pool); err != nil { 1142 t.Fatalf("pool internal state corrupted: %v", err) 1143 } 1144 1145 time.Sleep(2 * evictionInterval) 1146 1147 // Wait a bit for eviction, but queued transactions must remain. 1148 pending, queued = pool.Stats() 1149 assert.Equal(t, pending, 0) 1150 assert.Equal(t, queued, 2) 1151 1152 // Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains 1153 time.Sleep(2 * config.Lifetime) 1154 1155 pending, queued = pool.Stats() 1156 assert.Equal(t, pending, 0) 1157 1158 if nolocals { 1159 assert.Equal(t, queued, 0) 1160 } else { 1161 if keepLocals { 1162 assert.Equal(t, queued, 1) 1163 } else { 1164 assert.Equal(t, queued, 0) 1165 } 1166 } 1167 if err := validateTxPoolInternals(pool); err != nil { 1168 t.Fatalf("pool internal state corrupted: %v", err) 1169 } 1170 } 1171 1172 // Tests that even if the transaction count belonging to a single account goes 1173 // above some threshold, as long as the transactions are executable, they are 1174 // accepted. 1175 func TestTransactionPendingLimiting(t *testing.T) { 1176 t.Parallel() 1177 1178 // Create a test account and fund it 1179 pool, key := setupTxPool() 1180 defer pool.Stop() 1181 1182 account := crypto.PubkeyToAddress(key.PublicKey) 1183 testAddBalance(pool, account, big.NewInt(1000000)) 1184 1185 // Keep track of transaction events to ensure all executables get announced 1186 events := make(chan NewTxsEvent, testTxPoolConfig.NonExecSlotsAccount+5) 1187 sub := pool.txFeed.Subscribe(events) 1188 defer sub.Unsubscribe() 1189 1190 // Keep queuing up transactions and make sure all above a limit are dropped 1191 for i := uint64(0); i < testTxPoolConfig.NonExecSlotsAccount+5; i++ { 1192 if err := pool.AddRemote(transaction(i, 100000, key)); err != nil { 1193 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 1194 } 1195 if pool.pending[account].Len() != int(i)+1 { 1196 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1) 1197 } 1198 if len(pool.queue) != 0 { 1199 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0) 1200 } 1201 } 1202 if pool.all.Count() != int(testTxPoolConfig.NonExecSlotsAccount+5) { 1203 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.NonExecSlotsAccount+5) 1204 } 1205 if err := validateEvents(events, int(testTxPoolConfig.NonExecSlotsAccount+5)); err != nil { 1206 t.Fatalf("event firing failed: %v", err) 1207 } 1208 if err := validateTxPoolInternals(pool); err != nil { 1209 t.Fatalf("pool internal state corrupted: %v", err) 1210 } 1211 } 1212 1213 // Tests that the transaction limits are enforced the same way irrelevant whether 1214 // the transactions are added one by one or in batches. 1215 func TestTransactionQueueLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 1) } 1216 1217 func TestTransactionPendingLimitingEquivalency(t *testing.T) { 1218 testTransactionLimitingEquivalency(t, 0) 1219 } 1220 1221 func testTransactionLimitingEquivalency(t *testing.T, origin uint64) { 1222 t.Parallel() 1223 1224 // Add a batch of transactions to a pool one by one 1225 pool1, key1 := setupTxPool() 1226 defer pool1.Stop() 1227 1228 account1 := crypto.PubkeyToAddress(key1.PublicKey) 1229 testAddBalance(pool1, account1, big.NewInt(1000000)) 1230 1231 for i := uint64(0); i < testTxPoolConfig.NonExecSlotsAccount+5; i++ { 1232 if err := pool1.AddRemote(transaction(origin+i, 100000, key1)); err != nil { 1233 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 1234 } 1235 } 1236 // Add a batch of transactions to a pool in one big batch 1237 pool2, key2 := setupTxPool() 1238 defer pool2.Stop() 1239 1240 account2 := crypto.PubkeyToAddress(key2.PublicKey) 1241 testAddBalance(pool2, account2, big.NewInt(1000000)) 1242 1243 txs := []*types.Transaction{} 1244 for i := uint64(0); i < testTxPoolConfig.NonExecSlotsAccount+5; i++ { 1245 txs = append(txs, transaction(origin+i, 100000, key2)) 1246 } 1247 pool2.AddRemotes(txs) 1248 1249 // Ensure the batch optimization honors the same pool mechanics 1250 if len(pool1.pending) != len(pool2.pending) { 1251 t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending)) 1252 } 1253 if len(pool1.queue) != len(pool2.queue) { 1254 t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue), len(pool2.queue)) 1255 } 1256 if pool1.all.Count() != pool2.all.Count() { 1257 t.Errorf("total transaction count mismatch: one-by-one algo %d, batch algo %d", pool1.all.Count(), pool2.all.Count()) 1258 } 1259 if err := validateTxPoolInternals(pool1); err != nil { 1260 t.Errorf("pool 1 internal state corrupted: %v", err) 1261 } 1262 if err := validateTxPoolInternals(pool2); err != nil { 1263 t.Errorf("pool 2 internal state corrupted: %v", err) 1264 } 1265 } 1266 1267 // Tests that if the transaction count belonging to multiple accounts go above 1268 // some hard threshold, the higher transactions are dropped to prevent DOS 1269 // attacks. 1270 func TestTransactionPendingGlobalLimiting(t *testing.T) { 1271 t.Parallel() 1272 1273 // Create the pool to test the limit enforcement with 1274 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 1275 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1276 1277 config := testTxPoolConfig 1278 config.ExecSlotsAll = config.ExecSlotsAccount * 10 1279 1280 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1281 defer pool.Stop() 1282 1283 // Create a number of test accounts and fund them 1284 keys := make([]*ecdsa.PrivateKey, 5) 1285 for i := 0; i < len(keys); i++ { 1286 keys[i], _ = crypto.GenerateKey() 1287 testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1288 } 1289 // Generate and queue a batch of transactions 1290 nonces := make(map[common.Address]uint64) 1291 1292 txs := types.Transactions{} 1293 for _, key := range keys { 1294 addr := crypto.PubkeyToAddress(key.PublicKey) 1295 for j := 0; j < int(config.ExecSlotsAll)/len(keys)*2; j++ { 1296 txs = append(txs, transaction(nonces[addr], 100000, key)) 1297 nonces[addr]++ 1298 } 1299 } 1300 // Import the batch and verify that limits have been enforced 1301 pool.AddRemotes(txs) 1302 1303 pending := 0 1304 for _, list := range pool.pending { 1305 pending += list.Len() 1306 } 1307 if pending > int(config.ExecSlotsAll) { 1308 t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.ExecSlotsAll) 1309 } 1310 if err := validateTxPoolInternals(pool); err != nil { 1311 t.Fatalf("pool internal state corrupted: %v", err) 1312 } 1313 } 1314 1315 // Test the limit on transaction size is enforced correctly. 1316 // This test verifies every transaction having allowed size 1317 // is added to the pool, and longer transactions are rejected. 1318 func TestTransactionAllowedTxSize(t *testing.T) { 1319 t.Parallel() 1320 1321 // Create a test account and fund it 1322 pool, key := setupTxPool() 1323 defer pool.Stop() 1324 1325 account := crypto.PubkeyToAddress(key.PublicKey) 1326 pool.currentState.AddBalance(account, big.NewInt(1000000000)) 1327 1328 // Compute maximal data size for transactions (lower bound). 1329 // 1330 // It is assumed the fields in the transaction (except of the data) are: 1331 // - nonce <= 32 bytes 1332 // - gasPrice <= 32 bytes 1333 // - gasLimit <= 32 bytes 1334 // - recipient == 20 bytes 1335 // - value <= 32 bytes 1336 // - signature == 65 bytes 1337 // All those fields are summed up to at most 213 bytes. 1338 baseSize := uint64(213) 1339 dataSize := MaxTxDataSize - baseSize 1340 1341 testcases := []struct { 1342 sizeOfTxData uint64 // data size of the transaction to be added 1343 nonce uint64 // nonce of the transaction 1344 success bool // the expected result whether the addition is succeeded or failed 1345 errStr string 1346 }{ 1347 // Try adding a transaction with close to the maximum allowed size 1348 {dataSize, 0, true, "failed to add the transaction which size is close to the maximal"}, 1349 // Try adding a transaction with random allowed size 1350 {uint64(rand.Intn(int(dataSize))), 1, true, "failed to add the transaction of random allowed size"}, 1351 // Try adding a slightly oversize transaction 1352 {MaxTxDataSize, 2, false, "expected rejection on slightly oversize transaction"}, 1353 // Try adding a transaction of random not allowed size 1354 {dataSize + 1 + uint64(rand.Intn(int(10*MaxTxDataSize))), 2, false, "expected rejection on oversize transaction"}, 1355 } 1356 for _, tc := range testcases { 1357 tx := pricedDataTransaction(tc.nonce, 100000000, big.NewInt(1), key, tc.sizeOfTxData) 1358 err := pool.AddRemote(tx) 1359 1360 // test failed 1361 if tc.success && err != nil || !tc.success && err == nil { 1362 t.Fatalf("%s. tx Size: %d. error: %v.", tc.errStr, int(tx.Size()), err) 1363 } 1364 } 1365 1366 // Run some sanity checks on the pool internals 1367 pending, queued := pool.Stats() 1368 if pending != 2 { 1369 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1370 } 1371 if queued != 0 { 1372 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1373 } 1374 if err := validateTxPoolInternals(pool); err != nil { 1375 t.Fatalf("pool internal state corrupted: %v", err) 1376 } 1377 } 1378 1379 // Tests that if transactions start being capped, transactions are also removed from 'all' 1380 func TestTransactionCapClearsFromAll(t *testing.T) { 1381 t.Parallel() 1382 1383 // Create the pool to test the limit enforcement with 1384 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 1385 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1386 1387 config := testTxPoolConfig 1388 config.ExecSlotsAccount = 2 1389 config.NonExecSlotsAccount = 2 1390 config.ExecSlotsAll = 8 1391 1392 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1393 defer pool.Stop() 1394 1395 // Create a number of test accounts and fund them 1396 key, _ := crypto.GenerateKey() 1397 addr := crypto.PubkeyToAddress(key.PublicKey) 1398 pool.currentState.AddBalance(addr, big.NewInt(1000000)) 1399 1400 txs := types.Transactions{} 1401 for j := 0; j < int(config.ExecSlotsAll)*2; j++ { 1402 txs = append(txs, transaction(uint64(j), 100000, key)) 1403 } 1404 // Import the batch and verify that limits have been enforced 1405 pool.AddRemotes(txs) 1406 if err := validateTxPoolInternals(pool); err != nil { 1407 t.Fatalf("pool internal state corrupted: %v", err) 1408 } 1409 } 1410 1411 // Tests that if the transaction count belonging to multiple accounts go above 1412 // some hard threshold, if they are under the minimum guaranteed slot count then 1413 // the transactions are still kept. 1414 func TestTransactionPendingMinimumAllowance(t *testing.T) { 1415 t.Parallel() 1416 1417 // Create the pool to test the limit enforcement with 1418 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 1419 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1420 1421 config := testTxPoolConfig 1422 config.ExecSlotsAll = 0 1423 1424 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1425 defer pool.Stop() 1426 1427 // Create a number of test accounts and fund them 1428 keys := make([]*ecdsa.PrivateKey, 5) 1429 for i := 0; i < len(keys); i++ { 1430 keys[i], _ = crypto.GenerateKey() 1431 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1432 } 1433 // Generate and queue a batch of transactions 1434 nonces := make(map[common.Address]uint64) 1435 1436 txs := types.Transactions{} 1437 for _, key := range keys { 1438 addr := crypto.PubkeyToAddress(key.PublicKey) 1439 for j := 0; j < int(config.ExecSlotsAccount)*2; j++ { 1440 txs = append(txs, transaction(nonces[addr], 100000, key)) 1441 nonces[addr]++ 1442 } 1443 } 1444 // Import the batch and verify that limits have been enforced 1445 pool.AddRemotes(txs) 1446 1447 for addr, list := range pool.pending { 1448 if list.Len() != int(config.ExecSlotsAccount) { 1449 t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.ExecSlotsAccount) 1450 } 1451 } 1452 if err := validateTxPoolInternals(pool); err != nil { 1453 t.Fatalf("pool internal state corrupted: %v", err) 1454 } 1455 } 1456 1457 // NOTE-Klaytn Disable test, because we don't have a pool repricing feature anymore. 1458 // Tests that setting the transaction pool gas price to a higher value correctly 1459 // discards everything cheaper than that and moves any gapped transactions back 1460 // from the pending pool to the queue. 1461 // 1462 // Note, local transactions are never allowed to be dropped. 1463 /* 1464 func TestTransactionPoolRepricing(t *testing.T) { 1465 t.Parallel() 1466 1467 // Create the pool to test the pricing enforcement with 1468 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemDB())) 1469 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1470 1471 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1472 defer pool.Stop() 1473 1474 // Keep track of transaction events to ensure all executables get announced 1475 events := make(chan NewTxsEvent, 32) 1476 sub := pool.txFeed.Subscribe(events) 1477 defer sub.Unsubscribe() 1478 1479 // Create a number of test accounts and fund them 1480 keys := make([]*ecdsa.PrivateKey, 4) 1481 for i := 0; i < len(keys); i++ { 1482 keys[i], _ = crypto.GenerateKey() 1483 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1484 } 1485 // Generate and queue a batch of transactions, both pending and queued 1486 txs := types.Transactions{} 1487 1488 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0])) 1489 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0])) 1490 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0])) 1491 1492 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) 1493 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1])) 1494 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[1])) 1495 1496 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[2])) 1497 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) 1498 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2])) 1499 1500 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[3]) 1501 1502 // Import the batch and that both pending and queued transactions match up 1503 pool.AddRemotes(txs) 1504 pool.AddLocal(ltx) 1505 1506 pending, queued := pool.Stats() 1507 if pending != 7 { 1508 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7) 1509 } 1510 if queued != 3 { 1511 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) 1512 } 1513 if err := validateEvents(events, 7); err != nil { 1514 t.Fatalf("original event firing failed: %v", err) 1515 } 1516 if err := validateTxPoolInternals(pool); err != nil { 1517 t.Fatalf("pool internal state corrupted: %v", err) 1518 } 1519 // Reprice the pool and check that underpriced transactions get dropped 1520 pool.SetGasPrice(big.NewInt(2)) 1521 1522 pending, queued = pool.Stats() 1523 if pending != 2 { 1524 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1525 } 1526 if queued != 5 { 1527 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5) 1528 } 1529 if err := validateEvents(events, 0); err != nil { 1530 t.Fatalf("reprice event firing failed: %v", err) 1531 } 1532 if err := validateTxPoolInternals(pool); err != nil { 1533 t.Fatalf("pool internal state corrupted: %v", err) 1534 } 1535 // NOTE-Klaytn Klaytn currently accepts remote txs regardless of gas price. 1536 // TODO-Klaytn-RemoveLater Remove or uncomment the code below once the policy for how to 1537 // deal with underpriced remote txs is decided. 1538 // Check that we can't add the old transactions back 1539 //if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); err != ErrUnderpriced { 1540 // t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1541 //} 1542 //if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1543 // t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1544 //} 1545 //if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[2])); err != ErrUnderpriced { 1546 // t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1547 //} 1548 if err := validateEvents(events, 0); err != nil { 1549 t.Fatalf("post-reprice event firing failed: %v", err) 1550 } 1551 if err := validateTxPoolInternals(pool); err != nil { 1552 t.Fatalf("pool internal state corrupted: %v", err) 1553 } 1554 // However we can add local underpriced transactions 1555 tx := pricedTransaction(1, 100000, big.NewInt(1), keys[3]) 1556 if err := pool.AddLocal(tx); err != nil { 1557 t.Fatalf("failed to add underpriced local transaction: %v", err) 1558 } 1559 if pending, _ = pool.Stats(); pending != 3 { 1560 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1561 } 1562 if err := validateEvents(events, 1); err != nil { 1563 t.Fatalf("post-reprice local event firing failed: %v", err) 1564 } 1565 if err := validateTxPoolInternals(pool); err != nil { 1566 t.Fatalf("pool internal state corrupted: %v", err) 1567 } 1568 // And we can fill gaps with properly priced transactions 1569 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil { 1570 t.Fatalf("failed to add pending transaction: %v", err) 1571 } 1572 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), keys[1])); err != nil { 1573 t.Fatalf("failed to add pending transaction: %v", err) 1574 } 1575 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), keys[2])); err != nil { 1576 t.Fatalf("failed to add queued transaction: %v", err) 1577 } 1578 if err := validateEvents(events, 5); err != nil { 1579 t.Fatalf("post-reprice event firing failed: %v", err) 1580 } 1581 if err := validateTxPoolInternals(pool); err != nil { 1582 t.Fatalf("pool internal state corrupted: %v", err) 1583 } 1584 } 1585 */ 1586 1587 // NOTE-GS Disable test, because we don't have a repricing policy 1588 // TODO-Klaytn What's our rule for local transaction ? 1589 // Tests that setting the transaction pool gas price to a higher value does not 1590 // remove local transactions. 1591 /* 1592 func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { 1593 t.Parallel() 1594 1595 // Create the pool to test the pricing enforcement with 1596 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemDB())) 1597 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1598 1599 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1600 defer pool.Stop() 1601 1602 // Create a number of test accounts and fund them 1603 keys := make([]*ecdsa.PrivateKey, 3) 1604 for i := 0; i < len(keys); i++ { 1605 keys[i], _ = crypto.GenerateKey() 1606 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000*1000000)) 1607 } 1608 // Create transaction (both pending and queued) with a linearly growing gasprice 1609 for i := uint64(0); i < 500; i++ { 1610 // Add pending 1611 p_tx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2]) 1612 if err := pool.AddLocal(p_tx); err != nil { 1613 t.Fatal(err) 1614 } 1615 // Add queued 1616 q_tx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2]) 1617 if err := pool.AddLocal(q_tx); err != nil { 1618 t.Fatal(err) 1619 } 1620 } 1621 pending, queued := pool.Stats() 1622 expPending, expQueued := 500, 500 1623 validate := func() { 1624 pending, queued = pool.Stats() 1625 if pending != expPending { 1626 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending) 1627 } 1628 if queued != expQueued { 1629 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) 1630 } 1631 1632 if err := validateTxPoolInternals(pool); err != nil { 1633 t.Fatalf("pool internal state corrupted: %v", err) 1634 } 1635 } 1636 validate() 1637 1638 // Reprice the pool and check that nothing is dropped 1639 pool.SetGasPrice(big.NewInt(2)) 1640 validate() 1641 1642 pool.SetGasPrice(big.NewInt(2)) 1643 pool.SetGasPrice(big.NewInt(4)) 1644 pool.SetGasPrice(big.NewInt(8)) 1645 pool.SetGasPrice(big.NewInt(100)) 1646 validate() 1647 } 1648 */ 1649 1650 // NOTE-Klaytn Disable test, because we accept only transactions with a expected 1651 // gas price and there is no underpricing policy anymore. 1652 // Tests that when the pool reaches its global transaction limit, underpriced 1653 // transactions are gradually shifted out for more expensive ones and any gapped 1654 // pending transactions are moved into the queue. 1655 // 1656 // Note, local transactions are never allowed to be dropped. 1657 /* 1658 func TestTransactionPoolUnderpricing(t *testing.T) { 1659 t.Parallel() 1660 1661 // Create the pool to test the pricing enforcement with 1662 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemDB())) 1663 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1664 1665 config := testTxPoolConfig 1666 config.ExecSlotsAll = 2 1667 config.NonExecSlotsAll = 2 1668 1669 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1670 defer pool.Stop() 1671 1672 // Keep track of transaction events to ensure all executables get announced 1673 events := make(chan NewTxsEvent, 32) 1674 sub := pool.txFeed.Subscribe(events) 1675 defer sub.Unsubscribe() 1676 1677 // Create a number of test accounts and fund them 1678 keys := make([]*ecdsa.PrivateKey, 4) 1679 for i := 0; i < len(keys); i++ { 1680 keys[i], _ = crypto.GenerateKey() 1681 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1682 } 1683 // Generate and queue a batch of transactions, both pending and queued 1684 txs := types.Transactions{} 1685 1686 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) 1687 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) 1688 1689 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1])) 1690 1691 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2]) 1692 1693 // Import the batch and that both pending and queued transactions match up 1694 pool.AddRemotes(txs) 1695 pool.AddLocal(ltx) 1696 1697 pending, queued := pool.Stats() 1698 if pending != 3 { 1699 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1700 } 1701 if queued != 1 { 1702 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1703 } 1704 if err := validateEvents(events, 3); err != nil { 1705 t.Fatalf("original event firing failed: %v", err) 1706 } 1707 if err := validateTxPoolInternals(pool); err != nil { 1708 t.Fatalf("pool internal state corrupted: %v", err) 1709 } 1710 // Ensure that adding an underpriced transaction on block limit fails 1711 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1712 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1713 } 1714 // Ensure that adding high priced transactions drops cheap ones, but not own 1715 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil { // +K1:0 => -K1:1 => Pend K0:0, K0:1, K1:0, K2:0; Que - 1716 t.Fatalf("failed to add well priced transaction: %v", err) 1717 } 1718 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil { // +K1:2 => -K0:0 => Pend K1:0, K2:0; Que K0:1 K1:2 1719 t.Fatalf("failed to add well priced transaction: %v", err) 1720 } 1721 if err := pool.AddRemote(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil { // +K1:3 => -K0:1 => Pend K1:0, K2:0; Que K1:2 K1:3 1722 t.Fatalf("failed to add well priced transaction: %v", err) 1723 } 1724 pending, queued = pool.Stats() 1725 if pending != 2 { 1726 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1727 } 1728 if queued != 2 { 1729 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1730 } 1731 if err := validateEvents(events, 1); err != nil { 1732 t.Fatalf("additional event firing failed: %v", err) 1733 } 1734 if err := validateTxPoolInternals(pool); err != nil { 1735 t.Fatalf("pool internal state corrupted: %v", err) 1736 } 1737 // Ensure that adding local transactions can push out even higher priced ones 1738 ltx = pricedTransaction(1, 100000, big.NewInt(0), keys[2]) 1739 if err := pool.AddLocal(ltx); err != nil { 1740 t.Fatalf("failed to append underpriced local transaction: %v", err) 1741 } 1742 ltx = pricedTransaction(0, 100000, big.NewInt(0), keys[3]) 1743 if err := pool.AddLocal(ltx); err != nil { 1744 t.Fatalf("failed to add new underpriced local transaction: %v", err) 1745 } 1746 pending, queued = pool.Stats() 1747 if pending != 3 { 1748 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1749 } 1750 if queued != 1 { 1751 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1752 } 1753 if err := validateEvents(events, 2); err != nil { 1754 t.Fatalf("local event firing failed: %v", err) 1755 } 1756 if err := validateTxPoolInternals(pool); err != nil { 1757 t.Fatalf("pool internal state corrupted: %v", err) 1758 } 1759 } 1760 */ 1761 1762 // NOTE-Klaytn Disable test, because we accept only transactions with a expected 1763 // gas price and there is no underpricing policy anymore. 1764 // Tests that more expensive transactions push out cheap ones from the pool, but 1765 // without producing instability by creating gaps that start jumping transactions 1766 // back and forth between queued/pending. 1767 /* 1768 func TestTransactionPoolStableUnderpricing(t *testing.T) { 1769 t.Parallel() 1770 1771 // Create the pool to test the pricing enforcement with 1772 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemDB())) 1773 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1774 1775 config := testTxPoolConfig 1776 config.ExecSlotsAll = 128 1777 config.NonExecSlotsAll = 0 1778 1779 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1780 defer pool.Stop() 1781 1782 // Keep track of transaction events to ensure all executables get announced 1783 events := make(chan NewTxsEvent, 32) 1784 sub := pool.txFeed.Subscribe(events) 1785 defer sub.Unsubscribe() 1786 1787 // Create a number of test accounts and fund them 1788 keys := make([]*ecdsa.PrivateKey, 2) 1789 for i := 0; i < len(keys); i++ { 1790 keys[i], _ = crypto.GenerateKey() 1791 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1792 } 1793 // Fill up the entire queue with the same transaction price points 1794 txs := types.Transactions{} 1795 for i := uint64(0); i < config.ExecSlotsAll; i++ { 1796 txs = append(txs, pricedTransaction(i, 100000, big.NewInt(1), keys[0])) 1797 } 1798 pool.AddRemotes(txs) 1799 1800 pending, queued := pool.Stats() 1801 if pending != int(config.ExecSlotsAll) { 1802 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.ExecSlotsAll) 1803 } 1804 if queued != 0 { 1805 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1806 } 1807 if err := validateEvents(events, int(config.ExecSlotsAll)); err != nil { 1808 t.Fatalf("original event firing failed: %v", err) 1809 } 1810 if err := validateTxPoolInternals(pool); err != nil { 1811 t.Fatalf("pool internal state corrupted: %v", err) 1812 } 1813 // Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap 1814 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil { 1815 t.Fatalf("failed to add well priced transaction: %v", err) 1816 } 1817 pending, queued = pool.Stats() 1818 if pending != int(config.ExecSlotsAll) { 1819 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.ExecSlotsAll) 1820 } 1821 if queued != 0 { 1822 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1823 } 1824 if err := validateEvents(events, 1); err != nil { 1825 t.Fatalf("additional event firing failed: %v", err) 1826 } 1827 if err := validateTxPoolInternals(pool); err != nil { 1828 t.Fatalf("pool internal state corrupted: %v", err) 1829 } 1830 } 1831 */ 1832 1833 // NOTE-Klaytn Disable this test, because we don't have a replacement rule. 1834 // Tests that the pool rejects replacement transactions that don't meet the minimum 1835 // price bump required. 1836 /* 1837 func TestTransactionReplacement(t *testing.T) { 1838 t.Parallel() 1839 1840 // Create the pool to test the pricing enforcement with 1841 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemDB())) 1842 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1843 1844 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1845 defer pool.Stop() 1846 1847 // Keep track of transaction events to ensure all executables get announced 1848 events := make(chan NewTxsEvent, 32) 1849 sub := pool.txFeed.Subscribe(events) 1850 defer sub.Unsubscribe() 1851 1852 // Create a test account to add transactions with 1853 key, _ := crypto.GenerateKey() 1854 pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) 1855 1856 // Add pending transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1857 price := int64(100) 1858 threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100 1859 1860 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil { 1861 t.Fatalf("failed to add original cheap pending transaction: %v", err) 1862 } 1863 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1864 t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1865 } 1866 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil { 1867 t.Fatalf("failed to replace original cheap pending transaction: %v", err) 1868 } 1869 if err := validateEvents(events, 2); err != nil { 1870 t.Fatalf("cheap replacement event firing failed: %v", err) 1871 } 1872 1873 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil { 1874 t.Fatalf("failed to add original proper pending transaction: %v", err) 1875 } 1876 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1877 t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1878 } 1879 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil { 1880 t.Fatalf("failed to replace original proper pending transaction: %v", err) 1881 } 1882 if err := validateEvents(events, 2); err != nil { 1883 t.Fatalf("proper replacement event firing failed: %v", err) 1884 } 1885 // Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1886 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil { 1887 t.Fatalf("failed to add original cheap queued transaction: %v", err) 1888 } 1889 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1890 t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1891 } 1892 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil { 1893 t.Fatalf("failed to replace original cheap queued transaction: %v", err) 1894 } 1895 1896 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil { 1897 t.Fatalf("failed to add original proper queued transaction: %v", err) 1898 } 1899 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1900 t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1901 } 1902 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil { 1903 t.Fatalf("failed to replace original proper queued transaction: %v", err) 1904 } 1905 1906 if err := validateEvents(events, 0); err != nil { 1907 t.Fatalf("queued replacement event firing failed: %v", err) 1908 } 1909 if err := validateTxPoolInternals(pool); err != nil { 1910 t.Fatalf("pool internal state corrupted: %v", err) 1911 } 1912 } 1913 */ 1914 1915 // Tests that local transactions are journaled to disk, but remote transactions 1916 // get discarded between restarts. 1917 func TestTransactionJournaling(t *testing.T) { testTransactionJournaling(t, false) } 1918 func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) } 1919 1920 func testTransactionJournaling(t *testing.T, nolocals bool) { 1921 t.Parallel() 1922 1923 // Create a temporary file for the journal 1924 file, err := ioutil.TempFile("", "") 1925 if err != nil { 1926 t.Fatalf("failed to create temporary journal: %v", err) 1927 } 1928 journal := file.Name() 1929 defer os.Remove(journal) 1930 1931 // Clean up the temporary file, we only need the path for now 1932 file.Close() 1933 os.Remove(journal) 1934 1935 // Create the original pool to inject transaction into the journal 1936 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 1937 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1938 1939 config := testTxPoolConfig 1940 config.NoLocals = nolocals 1941 config.Journal = journal 1942 config.JournalInterval = time.Second 1943 1944 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1945 1946 // Create two test accounts to ensure remotes expire but locals do not 1947 local, _ := crypto.GenerateKey() 1948 remote, _ := crypto.GenerateKey() 1949 1950 testAddBalance(pool, crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 1951 testAddBalance(pool, crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 1952 1953 // Add three local and a remote transactions and ensure they are queued up 1954 if err := pool.AddLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil { 1955 t.Fatalf("failed to add local transaction: %v", err) 1956 } 1957 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 1958 t.Fatalf("failed to add local transaction: %v", err) 1959 } 1960 if err := pool.AddLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil { 1961 t.Fatalf("failed to add local transaction: %v", err) 1962 } 1963 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil { 1964 t.Fatalf("failed to add remote transaction: %v", err) 1965 } 1966 pending, queued := pool.Stats() 1967 if pending != 4 { 1968 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4) 1969 } 1970 if queued != 0 { 1971 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1972 } 1973 if err := validateTxPoolInternals(pool); err != nil { 1974 t.Fatalf("pool internal state corrupted: %v", err) 1975 } 1976 // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive 1977 pool.Stop() 1978 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1979 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 1980 1981 pool = NewTxPool(config, params.TestChainConfig, blockchain) 1982 1983 pending, queued = pool.Stats() 1984 if queued != 0 { 1985 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1986 } 1987 if nolocals { 1988 if pending != 0 { 1989 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1990 } 1991 } else { 1992 if pending != 2 { 1993 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1994 } 1995 } 1996 if err := validateTxPoolInternals(pool); err != nil { 1997 t.Fatalf("pool internal state corrupted: %v", err) 1998 } 1999 // Bump the nonce temporarily and ensure the newly invalidated transaction is removed 2000 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) 2001 pool.lockedReset(nil, nil) 2002 time.Sleep(2 * config.JournalInterval) 2003 pool.Stop() 2004 2005 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 2006 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 2007 pool = NewTxPool(config, params.TestChainConfig, blockchain) 2008 2009 pending, queued = pool.Stats() 2010 if pending != 0 { 2011 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 2012 } 2013 if nolocals { 2014 if queued != 0 { 2015 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 2016 } 2017 } else { 2018 if queued != 1 { 2019 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 2020 } 2021 } 2022 if err := validateTxPoolInternals(pool); err != nil { 2023 t.Fatalf("pool internal state corrupted: %v", err) 2024 } 2025 pool.Stop() 2026 } 2027 2028 // TestTransactionStatusCheck tests that the pool can correctly retrieve the 2029 // pending status of individual transactions. 2030 func TestTransactionStatusCheck(t *testing.T) { 2031 t.Parallel() 2032 2033 // Create the pool to test the status retrievals with 2034 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 2035 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 2036 2037 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 2038 defer pool.Stop() 2039 2040 // Create the test accounts to check various transaction statuses with 2041 keys := make([]*ecdsa.PrivateKey, 3) 2042 for i := 0; i < len(keys); i++ { 2043 keys[i], _ = crypto.GenerateKey() 2044 testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 2045 } 2046 // Generate and queue a batch of transactions, both pending and queued 2047 txs := types.Transactions{} 2048 2049 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // Pending only 2050 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) // Pending and queued 2051 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1])) 2052 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) // Queued only 2053 2054 // Import the transaction and ensure they are correctly added 2055 pool.AddRemotes(txs) 2056 2057 pending, queued := pool.Stats() 2058 if pending != 2 { 2059 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 2060 } 2061 if queued != 2 { 2062 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 2063 } 2064 if err := validateTxPoolInternals(pool); err != nil { 2065 t.Fatalf("pool internal state corrupted: %v", err) 2066 } 2067 // Retrieve the status of each transaction and validate them 2068 hashes := make([]common.Hash, len(txs)) 2069 for i, tx := range txs { 2070 hashes[i] = tx.Hash() 2071 } 2072 hashes = append(hashes, common.Hash{}) 2073 2074 statuses := pool.Status(hashes) 2075 expect := []TxStatus{TxStatusPending, TxStatusPending, TxStatusQueued, TxStatusQueued, TxStatusUnknown} 2076 2077 for i := 0; i < len(statuses); i++ { 2078 if statuses[i] != expect[i] { 2079 t.Errorf("transaction %d: status mismatch: have %v, want %v", i, statuses[i], expect[i]) 2080 } 2081 } 2082 } 2083 2084 func TestDynamicFeeTransactionVeryHighValues(t *testing.T) { 2085 t.Parallel() 2086 2087 pool, key := setupTxPoolWithConfig(eip1559Config) 2088 defer pool.Stop() 2089 2090 veryBigNumber := big.NewInt(1) 2091 veryBigNumber.Lsh(veryBigNumber, 300) 2092 2093 tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key) 2094 if err := pool.AddRemote(tx); err != ErrTipVeryHigh { 2095 t.Error("expected", ErrTipVeryHigh, "got", err) 2096 } 2097 2098 tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key) 2099 if err := pool.AddRemote(tx2); err != ErrFeeCapVeryHigh { 2100 t.Error("expected", ErrFeeCapVeryHigh, "got", err) 2101 } 2102 } 2103 2104 func TestDynamicFeeTransactionHasNotSameGasPrice(t *testing.T) { 2105 t.Parallel() 2106 2107 pool, key := setupTxPoolWithConfig(eip1559Config) 2108 defer pool.Stop() 2109 2110 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) 2111 2112 // Ensure gasFeeCap is greater than or equal to gasTipCap. 2113 tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key) 2114 if err := pool.AddRemote(tx); err != ErrTipAboveFeeCap { 2115 t.Error("expected", ErrTipAboveFeeCap, "got", err) 2116 } 2117 2118 // The GasTipCap is equal to gasPrice that config at TxPool. 2119 tx2 := dynamicFeeTx(0, 100, big.NewInt(2), big.NewInt(2), key) 2120 if err := pool.AddRemote(tx2); err != ErrInvalidGasTipCap { 2121 t.Error("expected", ErrInvalidGasTipCap, "got", err) 2122 } 2123 } 2124 2125 func TestDynamicFeeTransactionAccepted(t *testing.T) { 2126 t.Parallel() 2127 2128 pool, key := setupTxPoolWithConfig(eip1559Config) 2129 defer pool.Stop() 2130 2131 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000)) 2132 2133 tx := dynamicFeeTx(0, 21000, big.NewInt(1), big.NewInt(1), key) 2134 if err := pool.AddRemote(tx); err != nil { 2135 t.Error("error", "got", err) 2136 } 2137 2138 tx2 := dynamicFeeTx(1, 21000, big.NewInt(1), big.NewInt(1), key) 2139 if err := pool.AddRemote(tx2); err != nil { 2140 t.Error("error", "got", err) 2141 } 2142 } 2143 2144 // TestDynamicFeeTransactionNotAcceptedNotEnableHardfork tests that the pool didn't accept dynamic tx if the pool didn't enable eip1559 hardfork. 2145 func TestDynamicFeeTransactionNotAcceptedNotEnableHardfork(t *testing.T) { 2146 t.Parallel() 2147 2148 pool, key := setupTxPool() 2149 2150 tx := dynamicFeeTx(0, 21000, big.NewInt(1), big.NewInt(1), key) 2151 if err := pool.AddRemote(tx); err != ErrTxTypeNotSupported { 2152 t.Error("expected", ErrTxTypeNotSupported, "got", err) 2153 } 2154 2155 if err := pool.AddLocal(tx); err != ErrTxTypeNotSupported { 2156 t.Error("expected", ErrTxTypeNotSupported, "got", err) 2157 } 2158 } 2159 2160 func TestDynamicFeeTransactionAcceptedEip1559(t *testing.T) { 2161 t.Parallel() 2162 baseFee := big.NewInt(30) 2163 2164 pool, key := setupTxPoolWithConfig(eip1559Config) 2165 defer pool.Stop() 2166 pool.SetGasPrice(baseFee) 2167 2168 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) 2169 2170 tx := dynamicFeeTx(0, 21000, big.NewInt(30), big.NewInt(30), key) 2171 if err := pool.AddRemote(tx); err != nil { 2172 t.Error("error", "got", err) 2173 } 2174 2175 tx1 := dynamicFeeTx(1, 21000, big.NewInt(30), big.NewInt(1), key) 2176 if err := pool.AddRemote(tx1); err != nil { 2177 assert.Equal(t, ErrInvalidGasTipCap, err) 2178 } 2179 2180 tx2 := dynamicFeeTx(2, 21000, big.NewInt(40), big.NewInt(30), key) 2181 if err := pool.AddRemote(tx2); err != nil { 2182 assert.Equal(t, ErrInvalidGasFeeCap, err) 2183 } 2184 } 2185 2186 // TestDynamicFeeTransactionAccepted tests that pool accept the transaction which has gasFeeCap bigger than or equal to baseFee. 2187 func TestDynamicFeeTransactionAcceptedMagma(t *testing.T) { 2188 t.Parallel() 2189 baseFee := big.NewInt(30) 2190 2191 pool, key := setupTxPoolWithConfig(kip71Config) 2192 defer pool.Stop() 2193 pool.SetBaseFee(baseFee) 2194 2195 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) 2196 2197 // The GasFeeCap equal to baseFee and gasTipCap is lower than baseFee(ignored). 2198 tx := dynamicFeeTx(0, 21000, big.NewInt(30), big.NewInt(1), key) 2199 if err := pool.AddRemote(tx); err != nil { 2200 t.Error("error", "got", err) 2201 } 2202 2203 // The GasFeeCap bigger than baseFee and gasTipCap is equal to baseFee(ignored). 2204 tx2 := dynamicFeeTx(1, 21000, big.NewInt(40), big.NewInt(30), key) 2205 if err := pool.AddRemote(tx2); err != nil { 2206 t.Error("error", "got", err) 2207 } 2208 2209 // The GasFeeCap greater than baseFee and gasTipCap is bigger than baseFee(ignored). 2210 tx3 := dynamicFeeTx(2, 21000, big.NewInt(50), big.NewInt(50), key) 2211 if err := pool.AddRemote(tx3); err != nil { 2212 t.Error("error", "got", err) 2213 } 2214 } 2215 2216 func TestTransactionAcceptedEip1559(t *testing.T) { 2217 t.Parallel() 2218 baseFee := big.NewInt(30) 2219 2220 pool, key := setupTxPoolWithConfig(eip1559Config) 2221 defer pool.Stop() 2222 pool.SetBaseFee(baseFee) 2223 2224 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) 2225 2226 // The transaction's gasPrice equal to baseFee. 2227 tx1 := pricedTransaction(0, 21000, big.NewInt(30), key) 2228 if err := pool.AddRemote(tx1); err != nil { 2229 t.Error("error", "got", err) 2230 } 2231 2232 // The transaction's gasPrice bigger than baseFee. 2233 tx2 := pricedTransaction(1, 21000, big.NewInt(40), key) 2234 if err := pool.AddRemote(tx2); err != nil { 2235 assert.Equal(t, ErrInvalidUnitPrice, err) 2236 } 2237 } 2238 2239 // TestTransactionAccepted tests that pool accepted transaction which has gasPrice bigger than or equal to baseFee. 2240 func TestTransactionAcceptedMagma(t *testing.T) { 2241 t.Parallel() 2242 baseFee := big.NewInt(30) 2243 2244 pool, key := setupTxPoolWithConfig(kip71Config) 2245 defer pool.Stop() 2246 pool.SetBaseFee(baseFee) 2247 2248 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) 2249 2250 // The transaction's gasPrice equal to baseFee. 2251 tx1 := pricedTransaction(0, 21000, big.NewInt(30), key) 2252 if err := pool.AddRemote(tx1); err != nil { 2253 t.Error("error", "got", err) 2254 } 2255 2256 // The transaction's gasPrice bigger than baseFee. 2257 tx2 := pricedTransaction(1, 21000, big.NewInt(40), key) 2258 if err := pool.AddRemote(tx2); err != nil { 2259 t.Error("error", "got", err) 2260 } 2261 } 2262 2263 func TestCancelTransactionAcceptedMagma(t *testing.T) { 2264 t.Parallel() 2265 baseFee := big.NewInt(30) 2266 2267 pool, key := setupTxPoolWithConfig(kip71Config) 2268 defer pool.Stop() 2269 pool.SetBaseFee(baseFee) 2270 2271 sender := crypto.PubkeyToAddress(key.PublicKey) 2272 testAddBalance(pool, sender, big.NewInt(10000000000)) 2273 2274 // The transaction's gasPrice equal to baseFee. 2275 tx1 := pricedTransaction(0, 21000, big.NewInt(30), key) 2276 if err := pool.AddRemote(tx1); err != nil { 2277 t.Error("error", "got", err) 2278 } 2279 tx2 := pricedTransaction(1, 21000, big.NewInt(30), key) 2280 if err := pool.AddRemote(tx2); err != nil { 2281 t.Error("error", "got", err) 2282 } 2283 tx3 := pricedTransaction(2, 21000, big.NewInt(30), key) 2284 if err := pool.AddRemote(tx3); err != nil { 2285 t.Error("error", "got", err) 2286 } 2287 2288 tx1CancelWithLowerPrice := cancelTx(0, 21000, big.NewInt(20), sender, key) 2289 if err := pool.AddRemote(tx1CancelWithLowerPrice); err != nil { 2290 assert.Equal(t, ErrGasPriceBelowBaseFee, err) 2291 } 2292 tx2CancelWithSamePrice := cancelTx(1, 21000, big.NewInt(30), sender, key) 2293 if err := pool.AddRemote(tx2CancelWithSamePrice); err != nil { 2294 t.Error("error", "got", err) 2295 } 2296 tx3CancelWithExceedPrice := cancelTx(2, 21000, big.NewInt(40), sender, key) 2297 if err := pool.AddRemote(tx3CancelWithExceedPrice); err != nil { 2298 t.Error("error", "got", err) 2299 } 2300 } 2301 2302 // TestDynamicFeeTransactionNotAcceptedWithLowerGasPrice tests that pool didn't accept the transaction which has gasFeeCap lower than baseFee. 2303 func TestDynamicFeeTransactionNotAcceptedWithLowerGasPrice(t *testing.T) { 2304 t.Parallel() 2305 baseFee := big.NewInt(30) 2306 2307 pool, key := setupTxPoolWithConfig(kip71Config) 2308 defer pool.Stop() 2309 pool.SetBaseFee(baseFee) 2310 2311 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) 2312 2313 // The gasFeeCap equal to baseFee and gasTipCap is lower than baseFee(ignored). 2314 tx := dynamicFeeTx(0, 21000, big.NewInt(20), big.NewInt(1), key) 2315 if err := pool.AddRemote(tx); err != ErrFeeCapBelowBaseFee { 2316 t.Error("error", "got", err) 2317 } 2318 } 2319 2320 // TestTransactionNotAcceptedWithLowerGasPrice tests that pool didn't accept the transaction which has gasPrice lower than baseFee. 2321 func TestTransactionNotAcceptedWithLowerGasPrice(t *testing.T) { 2322 t.Parallel() 2323 2324 pool, key := setupTxPoolWithConfig(kip71Config) 2325 defer pool.Stop() 2326 2327 baseFee := big.NewInt(30) 2328 pool.SetBaseFee(baseFee) 2329 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(10000000000)) 2330 2331 tx := pricedTransaction(0, 21000, big.NewInt(20), key) 2332 if err := pool.AddRemote(tx); err != ErrGasPriceBelowBaseFee { 2333 t.Error("error", "got", err) 2334 } 2335 } 2336 2337 // TestTransactionsPromoteFull is a test to check whether transactions in the queue are promoted to Pending 2338 // by filtering them with gasPrice greater than or equal to baseFee and sorting them in nonce sequentially order. 2339 // This test expected that all transactions in queue promoted pending. 2340 func TestTransactionsPromoteFull(t *testing.T) { 2341 t.Parallel() 2342 2343 pool, key := setupTxPoolWithConfig(kip71Config) 2344 defer pool.Stop() 2345 2346 from := crypto.PubkeyToAddress(key.PublicKey) 2347 2348 baseFee := big.NewInt(10) 2349 pool.SetBaseFee(baseFee) 2350 2351 testAddBalance(pool, from, big.NewInt(1000000000)) 2352 2353 // Generate and queue a batch of transactions, both pending and queued 2354 txs := types.Transactions{} 2355 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(50), key)) 2356 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(30), key)) 2357 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(30), key)) 2358 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(30), key)) 2359 2360 for _, tx := range txs { 2361 pool.enqueueTx(tx.Hash(), tx) 2362 } 2363 2364 pool.promoteExecutables(nil) 2365 2366 assert.Equal(t, pool.pending[from].Len(), 4) 2367 for i, tx := range txs { 2368 assert.True(t, reflect.DeepEqual(tx, pool.pending[from].txs.items[uint64(i)])) 2369 } 2370 } 2371 2372 // TestTransactionsPromotePartial is a test to check whether transactions in the queue are promoted to Pending 2373 // by filtering them with gasPrice greater than or equal to baseFee and sorting them in nonce sequentially order. 2374 // This test expected that partially transaction in queue promoted pending. 2375 func TestTransactionsPromotePartial(t *testing.T) { 2376 t.Parallel() 2377 2378 pool, key := setupTxPoolWithConfig(kip71Config) 2379 defer pool.Stop() 2380 2381 from := crypto.PubkeyToAddress(key.PublicKey) 2382 2383 baseFee := big.NewInt(10) 2384 pool.SetBaseFee(baseFee) 2385 2386 testAddBalance(pool, from, big.NewInt(1000000000)) 2387 2388 // Generate and queue a batch of transactions, both pending and queued 2389 txs := types.Transactions{} 2390 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(50), key)) 2391 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(20), key)) 2392 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(20), key)) 2393 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(10), key)) 2394 2395 for _, tx := range txs { 2396 pool.enqueueTx(tx.Hash(), tx) 2397 } 2398 2399 // set baseFee to 20. 2400 baseFee = big.NewInt(20) 2401 pool.gasPrice = baseFee 2402 2403 pool.promoteExecutables(nil) 2404 2405 assert.Equal(t, pool.pending[from].Len(), 3) 2406 assert.Equal(t, pool.queue[from].Len(), 1) 2407 2408 // txs[0:2] should be promoted. 2409 for i := 0; i < 3; i++ { 2410 assert.True(t, reflect.DeepEqual(txs[i], pool.pending[from].txs.items[uint64(i)])) 2411 } 2412 2413 // txs[3] shouldn't be promoted. 2414 assert.True(t, reflect.DeepEqual(txs[3], pool.queue[from].txs.items[3])) 2415 } 2416 2417 // TestTransactionsPromoteMultipleAccount is a test to check whether transactions in the queue are promoted to Pending 2418 // by filtering them with gasPrice greater than or equal to baseFee and sorting them in nonce sequentially order. 2419 // This test expected that all transactions in queue promoted pending. 2420 func TestTransactionsPromoteMultipleAccount(t *testing.T) { 2421 t.Parallel() 2422 2423 pool, _ := setupTxPoolWithConfig(kip71Config) 2424 defer pool.Stop() 2425 pool.SetBaseFee(big.NewInt(10)) 2426 2427 keys := make([]*ecdsa.PrivateKey, 3) 2428 froms := make([]common.Address, 3) 2429 for i := 0; i < 3; i++ { 2430 keys[i], _ = crypto.GenerateKey() 2431 froms[i] = crypto.PubkeyToAddress(keys[i].PublicKey) 2432 testAddBalance(pool, froms[i], big.NewInt(1000000000)) 2433 } 2434 2435 txs := types.Transactions{} 2436 2437 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(50), keys[0])) // Pending 2438 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(40), keys[0])) // Pending 2439 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(30), keys[0])) // Pending 2440 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(20), keys[0])) // Pending 2441 2442 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(10), keys[1])) // Only Queue 2443 2444 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(50), keys[2])) // Pending 2445 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(30), keys[2])) // Pending 2446 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(30), keys[2])) // Pending 2447 txs = append(txs, pricedTransaction(4, 100000, big.NewInt(10), keys[2])) // Queue 2448 2449 for i := 0; i < 9; i++ { 2450 pool.enqueueTx(txs[i].Hash(), txs[i]) 2451 } 2452 2453 pool.gasPrice = big.NewInt(20) 2454 2455 pool.promoteExecutables(nil) 2456 2457 assert.Equal(t, pool.pending[froms[0]].Len(), 4) 2458 2459 assert.True(t, reflect.DeepEqual(txs[0], pool.pending[froms[0]].txs.items[uint64(0)])) 2460 assert.True(t, reflect.DeepEqual(txs[1], pool.pending[froms[0]].txs.items[uint64(1)])) 2461 assert.True(t, reflect.DeepEqual(txs[2], pool.pending[froms[0]].txs.items[uint64(2)])) 2462 assert.True(t, reflect.DeepEqual(txs[3], pool.pending[froms[0]].txs.items[uint64(3)])) 2463 2464 assert.Equal(t, pool.queue[froms[1]].Len(), 1) 2465 assert.True(t, reflect.DeepEqual(txs[4], pool.queue[froms[1]].txs.items[1])) 2466 2467 assert.Equal(t, pool.queue[froms[2]].Len(), 1) 2468 assert.Equal(t, pool.pending[froms[2]].Len(), 3) 2469 2470 assert.True(t, reflect.DeepEqual(txs[5], pool.pending[froms[2]].txs.items[0])) 2471 assert.True(t, reflect.DeepEqual(txs[6], pool.pending[froms[2]].txs.items[1])) 2472 assert.True(t, reflect.DeepEqual(txs[7], pool.pending[froms[2]].txs.items[2])) 2473 assert.True(t, reflect.DeepEqual(txs[8], pool.queue[froms[2]].txs.items[4])) 2474 } 2475 2476 // TestTransactionsDemotionMultipleAccount is a test if the transactions in pending are 2477 // less than the gasPrice of the configured tx pool, check if they are demoted to the queue. 2478 func TestTransactionsDemotionMultipleAccount(t *testing.T) { 2479 t.Parallel() 2480 2481 pool, _ := setupTxPoolWithConfig(kip71Config) 2482 defer pool.Stop() 2483 pool.SetBaseFee(big.NewInt(10)) 2484 2485 keys := make([]*ecdsa.PrivateKey, 3) 2486 froms := make([]common.Address, 3) 2487 for i := 0; i < 3; i++ { 2488 keys[i], _ = crypto.GenerateKey() 2489 froms[i] = crypto.PubkeyToAddress(keys[i].PublicKey) 2490 testAddBalance(pool, froms[i], big.NewInt(1000000000)) 2491 } 2492 2493 txs := types.Transactions{} 2494 2495 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(50), keys[0])) 2496 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(40), keys[0])) 2497 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(30), keys[0])) 2498 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(20), keys[0])) 2499 2500 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(10), keys[1])) 2501 2502 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(50), keys[2])) 2503 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(30), keys[2])) 2504 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(30), keys[2])) 2505 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(10), keys[2])) 2506 2507 for i := 0; i < 9; i++ { 2508 pool.enqueueTx(txs[i].Hash(), txs[i]) 2509 } 2510 2511 pool.promoteExecutables(nil) 2512 assert.Equal(t, 4, pool.pending[froms[0]].Len()) 2513 assert.Equal(t, 1, pool.pending[froms[1]].Len()) 2514 assert.Equal(t, 4, pool.pending[froms[2]].Len()) 2515 // If gasPrice of txPool is set to 35, when demoteUnexecutables() is executed, it is saved for each transaction as shown below. 2516 // tx[0] : pending[from[0]] 2517 // tx[1] : pending[from[0]] 2518 // tx[2] : queue[from[0]] 2519 // tx[3] : queue[from[0]] 2520 2521 // tx[4] : queue[from[1]] 2522 2523 // tx[5] : pending[from[2]] 2524 // tx[6] : queue[from[2]] 2525 // tx[7] : queue[from[2]] 2526 // tx[7] : queue[from[2]] 2527 pool.SetBaseFee(big.NewInt(35)) 2528 pool.demoteUnexecutables() 2529 2530 assert.Equal(t, 2, pool.queue[froms[0]].Len()) 2531 assert.Equal(t, 2, pool.pending[froms[0]].Len()) 2532 2533 assert.True(t, reflect.DeepEqual(txs[0], pool.pending[froms[0]].txs.items[uint64(0)])) 2534 assert.True(t, reflect.DeepEqual(txs[1], pool.pending[froms[0]].txs.items[uint64(1)])) 2535 assert.True(t, reflect.DeepEqual(txs[2], pool.queue[froms[0]].txs.items[uint64(2)])) 2536 assert.True(t, reflect.DeepEqual(txs[3], pool.queue[froms[0]].txs.items[uint64(3)])) 2537 2538 assert.Equal(t, pool.queue[froms[1]].Len(), 1) 2539 assert.True(t, reflect.DeepEqual(txs[4], pool.queue[froms[1]].txs.items[0])) 2540 2541 assert.Equal(t, pool.queue[froms[2]].Len(), 3) 2542 assert.Equal(t, pool.pending[froms[2]].Len(), 1) 2543 2544 assert.True(t, reflect.DeepEqual(txs[5], pool.pending[froms[2]].txs.items[0])) 2545 assert.True(t, reflect.DeepEqual(txs[6], pool.queue[froms[2]].txs.items[1])) 2546 assert.True(t, reflect.DeepEqual(txs[7], pool.queue[froms[2]].txs.items[2])) 2547 assert.True(t, reflect.DeepEqual(txs[8], pool.queue[froms[2]].txs.items[3])) 2548 } 2549 2550 // TestFeeDelegatedTransaction checks feeDelegatedValueTransfer logic on tx pool 2551 // the case when sender = feePayer has been included 2552 func TestFeeDelegatedTransaction(t *testing.T) { 2553 t.Parallel() 2554 2555 pool, key := setupTxPool() 2556 senderKey, _ := crypto.GenerateKey() 2557 feePayerKey, _ := crypto.GenerateKey() 2558 defer pool.Stop() 2559 2560 testAddBalance(pool, crypto.PubkeyToAddress(senderKey.PublicKey), big.NewInt(60000)) 2561 testAddBalance(pool, crypto.PubkeyToAddress(feePayerKey.PublicKey), big.NewInt(60000)) 2562 2563 tx := feeDelegatedTx(0, 40000, big.NewInt(1), big.NewInt(40000), senderKey, feePayerKey) 2564 2565 if err := pool.AddRemote(tx); err != nil { 2566 t.Error("expected", "got", err) 2567 } 2568 2569 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(60000)) 2570 2571 // test on case when sender = feePayer 2572 // balance : 60k, tx.value : 40k, tx.fee : 40k 2573 tx1 := feeDelegatedTx(0, 40000, big.NewInt(1), big.NewInt(40000), key, key) 2574 2575 // balance : 60k, tx.value : 10k, tx.fee : 40k 2576 tx2 := feeDelegatedTx(0, 40000, big.NewInt(1), big.NewInt(10000), key, key) 2577 2578 if err := pool.AddRemote(tx1); err != ErrInsufficientFundsFrom { 2579 t.Error("expected", ErrInsufficientFundsFrom, "got", err) 2580 } 2581 2582 if err := pool.AddRemote(tx2); err != nil { 2583 t.Error("expected", "got", err) 2584 } 2585 } 2586 2587 func TestFeeDelegatedWithRatioTransaction(t *testing.T) { 2588 t.Parallel() 2589 2590 pool, key := setupTxPool() 2591 senderKey, _ := crypto.GenerateKey() 2592 feePayerKey, _ := crypto.GenerateKey() 2593 defer pool.Stop() 2594 2595 testAddBalance(pool, crypto.PubkeyToAddress(senderKey.PublicKey), big.NewInt(100000)) 2596 testAddBalance(pool, crypto.PubkeyToAddress(feePayerKey.PublicKey), big.NewInt(100000)) 2597 2598 // Sender balance : 100k, FeePayer balance : 100k tx.value : 50k, tx.fee : 100k, FeeRatio : 10% 2599 tx1 := feeDelegatedWithRatioTx(0, 100000, big.NewInt(1), big.NewInt(50000), senderKey, feePayerKey, 10) 2600 2601 // Sender balance : 100k, FeePayer balance : 100k tx.value : 50k, tx.fee : 100k, FeeRatio : 70% 2602 tx2 := feeDelegatedWithRatioTx(0, 100000, big.NewInt(1), big.NewInt(50000), senderKey, feePayerKey, 70) 2603 2604 // Sender balance : 100k, FeePayer balance : 100k tx.value : 50k, tx.fee : 110k, FeeRatio : 99% 2605 tx3 := feeDelegatedWithRatioTx(1, 110000, big.NewInt(1), big.NewInt(50000), senderKey, feePayerKey, 99) 2606 2607 if err := pool.AddRemote(tx1); err != ErrInsufficientFundsFrom { 2608 t.Error("expected", ErrInsufficientFundsFrom, "got", err) 2609 } 2610 2611 if err := pool.AddRemote(tx2); err != nil { 2612 t.Error("expected", "got", err) 2613 } 2614 2615 if err := pool.AddRemote(tx3); err != ErrInsufficientFundsFeePayer { 2616 t.Error("expected", ErrInsufficientFundsFeePayer, "got", err) 2617 } 2618 2619 testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(60000)) 2620 2621 // test on case when sender = feePayer 2622 // balance : 60k, tx.value : 40k, tx.fee : 40k, ratio : 30% 2623 tx4 := feeDelegatedWithRatioTx(0, 40000, big.NewInt(1), big.NewInt(40000), key, key, 30) 2624 2625 // balance : 60k, tx.value : 10k, tx.fee : 40k, ratio : 30% 2626 tx5 := feeDelegatedWithRatioTx(0, 40000, big.NewInt(1), big.NewInt(10000), key, key, 30) 2627 2628 if err := pool.AddRemote(tx4); err != ErrInsufficientFundsFrom { 2629 t.Error("expected", ErrInsufficientFundsFrom, "got", err) 2630 } 2631 2632 if err := pool.AddRemote(tx5); err != nil { 2633 t.Error("expected", "got", err) 2634 } 2635 } 2636 2637 func TestTransactionJournalingSortedByTime(t *testing.T) { 2638 t.Parallel() 2639 2640 // Create a temporary file for the journal 2641 file, err := ioutil.TempFile("", "") 2642 if err != nil { 2643 t.Fatalf("failed to create temporary journal: %v", err) 2644 } 2645 journal := file.Name() 2646 defer os.Remove(journal) 2647 2648 // Clean up the temporary file, we only need the path for now 2649 file.Close() 2650 os.Remove(journal) 2651 2652 // Create the pool to test the status retrievals with 2653 statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil) 2654 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 2655 2656 config := testTxPoolConfig 2657 config.Journal = journal 2658 2659 pool := NewTxPool(config, params.TestChainConfig, blockchain) 2660 defer pool.Stop() 2661 2662 // Create the test accounts to check various transaction statuses with 2663 keys := make([]*ecdsa.PrivateKey, 3) 2664 for i := 0; i < len(keys); i++ { 2665 keys[i], _ = crypto.GenerateKey() 2666 testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 2667 } 2668 // Generate and queue a batch of transactions, both pending and queued 2669 txs := types.Transactions{} 2670 2671 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // Pending only 2672 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) // Pending and queued 2673 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1])) 2674 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) // Queued only 2675 2676 // Import the transaction locally and ensure they are correctly added 2677 pool.AddLocals(txs) 2678 2679 // Execute rotate() to write transactions to file. 2680 pool.mu.Lock() 2681 if err := pool.journal.rotate(pool.local(), pool.signer); err != nil { 2682 t.Error("Failed to rotate local tx journal", "err", err) 2683 } 2684 pool.mu.Unlock() 2685 2686 // Read a journal and load it. 2687 input, err := os.Open(pool.journal.path) 2688 if err != nil { 2689 t.Error(err) 2690 } 2691 defer input.Close() 2692 2693 txsFromFile := make(types.Transactions, 4) 2694 stream := rlp.NewStream(input, 0) 2695 for i := 0; i < 4; i++ { 2696 tx := new(types.Transaction) 2697 if err = stream.Decode(tx); err != nil { 2698 if err != io.EOF { 2699 t.Error(err) 2700 } 2701 2702 break 2703 } 2704 txsFromFile[i] = tx 2705 } 2706 2707 // Check whether transactions loaded from journal file is sorted by time 2708 for i, tx := range txsFromFile { 2709 assert.Equal(t, txs[i].Hash(), tx.Hash()) 2710 assert.False(t, txs[i].Time().Equal(tx.Time())) 2711 } 2712 } 2713 2714 // Test the transaction slots consumption is computed correctly 2715 func TestTransactionSlotCount(t *testing.T) { 2716 t.Parallel() 2717 2718 key, _ := crypto.GenerateKey() 2719 2720 testcases := []struct { 2721 sizeOfTxData uint64 2722 nonce uint64 2723 sizeOfSlot int // expected result 2724 }{ 2725 // smallTx: Check that an empty transaction consumes a single slot 2726 {0, 0, 1}, 2727 // bigTx: Check that a large transaction consumes the correct number of slots 2728 {uint64(10 * txSlotSize), 0, 11}, 2729 } 2730 for _, tc := range testcases { 2731 tx := pricedDataTransaction(tc.nonce, 0, big.NewInt(0), key, tc.sizeOfTxData) 2732 assert.Equal(t, tc.sizeOfSlot, numSlots(tx), "transaction slot count mismatch") 2733 } 2734 } 2735 2736 // Benchmarks the speed of validating the contents of the pending queue of the 2737 // transaction pool. 2738 func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } 2739 func BenchmarkPendingDemotion1000(b *testing.B) { benchmarkPendingDemotion(b, 1000) } 2740 func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) } 2741 2742 func benchmarkPendingDemotion(b *testing.B, size int) { 2743 // Add a batch of transactions to a pool one by one 2744 pool, key := setupTxPool() 2745 defer pool.Stop() 2746 2747 account := crypto.PubkeyToAddress(key.PublicKey) 2748 testAddBalance(pool, account, big.NewInt(1000000)) 2749 2750 for i := 0; i < size; i++ { 2751 tx := transaction(uint64(i), 100000, key) 2752 pool.promoteTx(account, tx.Hash(), tx) 2753 } 2754 // Benchmark the speed of pool validation 2755 b.ResetTimer() 2756 for i := 0; i < b.N; i++ { 2757 pool.demoteUnexecutables() 2758 } 2759 } 2760 2761 // Benchmarks the speed of scheduling the contents of the future queue of the 2762 // transaction pool. 2763 func BenchmarkFuturePromotion100(b *testing.B) { benchmarkFuturePromotion(b, 100) } 2764 func BenchmarkFuturePromotion1000(b *testing.B) { benchmarkFuturePromotion(b, 1000) } 2765 func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) } 2766 2767 func benchmarkFuturePromotion(b *testing.B, size int) { 2768 // Add a batch of transactions to a pool one by one 2769 pool, key := setupTxPool() 2770 defer pool.Stop() 2771 2772 account := crypto.PubkeyToAddress(key.PublicKey) 2773 testAddBalance(pool, account, big.NewInt(1000000)) 2774 2775 for i := 0; i < size; i++ { 2776 tx := transaction(uint64(1+i), 100000, key) 2777 pool.enqueueTx(tx.Hash(), tx) 2778 } 2779 // Benchmark the speed of pool validation 2780 b.ResetTimer() 2781 for i := 0; i < b.N; i++ { 2782 pool.promoteExecutables(nil) 2783 } 2784 } 2785 2786 // Benchmarks the speed of iterative transaction insertion. 2787 func BenchmarkPoolInsert(b *testing.B) { 2788 // Generate a batch of transactions to enqueue into the pool 2789 pool, key := setupTxPool() 2790 defer pool.Stop() 2791 2792 account := crypto.PubkeyToAddress(key.PublicKey) 2793 testAddBalance(pool, account, big.NewInt(1000000)) 2794 2795 txs := make(types.Transactions, b.N) 2796 for i := 0; i < b.N; i++ { 2797 txs[i] = transaction(uint64(i), 100000, key) 2798 } 2799 // Benchmark importing the transactions into the queue 2800 b.ResetTimer() 2801 for _, tx := range txs { 2802 pool.AddRemote(tx) 2803 } 2804 } 2805 2806 // Benchmarks the speed of batched transaction insertion. 2807 func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100) } 2808 func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000) } 2809 func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) } 2810 2811 func benchmarkPoolBatchInsert(b *testing.B, size int) { 2812 // Generate a batch of transactions to enqueue into the pool 2813 pool, key := setupTxPool() 2814 defer pool.Stop() 2815 2816 account := crypto.PubkeyToAddress(key.PublicKey) 2817 testAddBalance(pool, account, big.NewInt(1000000)) 2818 2819 batches := make([]types.Transactions, b.N) 2820 for i := 0; i < b.N; i++ { 2821 batches[i] = make(types.Transactions, size) 2822 for j := 0; j < size; j++ { 2823 batches[i][j] = transaction(uint64(size*i+j), 100000, key) 2824 } 2825 } 2826 // Benchmark importing the transactions into the queue 2827 b.ResetTimer() 2828 for _, batch := range batches { 2829 pool.AddRemotes(batch) 2830 } 2831 }