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