all: refactor txpool into it's own package in prep for 4844

pull/26038/head
Péter Szilágyi 2 years ago
parent 5f70f9fd37
commit a6dda03644
No known key found for this signature in database
GPG Key ID: E9AE538CEDF8293D
  1. 7
      cmd/utils/flags.go
  2. 9
      core/blockchain.go
  3. 14
      core/sender_cacher.go
  4. 18
      core/txpool/journal.go
  5. 102
      core/txpool/list.go
  6. 18
      core/txpool/list_test.go
  7. 20
      core/txpool/noncer.go
  8. 150
      core/txpool/txpool.go
  9. 295
      core/txpool/txpool_test.go
  10. 3
      eth/api_backend.go
  11. 7
      eth/backend.go
  12. 5
      eth/ethconfig/config.go
  13. 5
      eth/ethconfig/gen_config.go
  14. 8
      eth/fetcher/tx_fetcher.go
  15. 8
      eth/fetcher/tx_fetcher_test.go
  16. 7
      eth/protocols/eth/handler_test.go
  17. 23
      les/handler_test.go
  18. 5
      les/odr.go
  19. 5
      les/odr_test.go
  20. 3
      les/server.go
  21. 7
      les/server_handler.go
  22. 9
      les/server_requests.go
  23. 5
      les/test_helper.go
  24. 3
      light/odr.go
  25. 4
      light/odr_util.go
  26. 7
      light/txpool.go
  27. 3
      miner/miner.go
  28. 9
      miner/miner_test.go
  29. 3
      miner/stress/1559/main.go
  30. 5
      miner/stress/beacon/main.go
  31. 3
      miner/stress/clique/main.go
  32. 3
      miner/stress/ethash/main.go
  33. 2
      miner/worker.go
  34. 11
      miner/worker_test.go
  35. 7
      tests/fuzzers/les/les-fuzzer.go

@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -390,13 +391,13 @@ var (
TxPoolJournalFlag = &cli.StringFlag{ TxPoolJournalFlag = &cli.StringFlag{
Name: "txpool.journal", Name: "txpool.journal",
Usage: "Disk journal for local transaction to survive node restarts", Usage: "Disk journal for local transaction to survive node restarts",
Value: core.DefaultTxPoolConfig.Journal, Value: txpool.DefaultConfig.Journal,
Category: flags.TxPoolCategory, Category: flags.TxPoolCategory,
} }
TxPoolRejournalFlag = &cli.DurationFlag{ TxPoolRejournalFlag = &cli.DurationFlag{
Name: "txpool.rejournal", Name: "txpool.rejournal",
Usage: "Time interval to regenerate the local transaction journal", Usage: "Time interval to regenerate the local transaction journal",
Value: core.DefaultTxPoolConfig.Rejournal, Value: txpool.DefaultConfig.Rejournal,
Category: flags.TxPoolCategory, Category: flags.TxPoolCategory,
} }
TxPoolPriceLimitFlag = &cli.Uint64Flag{ TxPoolPriceLimitFlag = &cli.Uint64Flag{
@ -1573,7 +1574,7 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
} }
} }
func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { func setTxPool(ctx *cli.Context, cfg *txpool.Config) {
if ctx.IsSet(TxPoolLocalsFlag.Name) { if ctx.IsSet(TxPoolLocalsFlag.Name) {
locals := strings.Split(ctx.String(TxPoolLocalsFlag.Name), ",") locals := strings.Split(ctx.String(TxPoolLocalsFlag.Name), ",")
for _, account := range locals { for _, account := range locals {

@ -77,10 +77,9 @@ var (
blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil) blockExecutionTimer = metrics.NewRegisteredTimer("chain/execution", nil)
blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil) blockWriteTimer = metrics.NewRegisteredTimer("chain/write", nil)
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil) blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil) blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil) blockReorgDropMeter = metrics.NewRegisteredMeter("chain/reorg/drop", nil)
blockReorgInvalidatedTx = metrics.NewRegisteredMeter("chain/reorg/invalidTx", nil)
blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil) blockPrefetchExecuteTimer = metrics.NewRegisteredTimer("chain/prefetch/executes", nil)
blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil) blockPrefetchInterruptMeter = metrics.NewRegisteredMeter("chain/prefetch/interrupts", nil)
@ -1492,7 +1491,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
} }
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss) // Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain) SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain)
var ( var (
stats = insertStats{startTime: mclock.Now()} stats = insertStats{startTime: mclock.Now()}

@ -22,8 +22,8 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
// senderCacher is a concurrent transaction sender recoverer and cacher. // SenderCacher is a concurrent transaction sender recoverer and cacher.
var senderCacher = newTxSenderCacher(runtime.NumCPU()) var SenderCacher = newTxSenderCacher(runtime.NumCPU())
// txSenderCacherRequest is a request for recovering transaction senders with a // txSenderCacherRequest is a request for recovering transaction senders with a
// specific signature scheme and caching it into the transactions themselves. // specific signature scheme and caching it into the transactions themselves.
@ -67,10 +67,10 @@ func (cacher *txSenderCacher) cache() {
} }
} }
// recover recovers the senders from a batch of transactions and caches them // Recover recovers the senders from a batch of transactions and caches them
// back into the same data structures. There is no validation being done, nor // back into the same data structures. There is no validation being done, nor
// any reaction to invalid signatures. That is up to calling code later. // any reaction to invalid signatures. That is up to calling code later.
func (cacher *txSenderCacher) recover(signer types.Signer, txs []*types.Transaction) { func (cacher *txSenderCacher) Recover(signer types.Signer, txs []*types.Transaction) {
// If there's nothing to recover, abort // If there's nothing to recover, abort
if len(txs) == 0 { if len(txs) == 0 {
return return
@ -89,10 +89,10 @@ func (cacher *txSenderCacher) recover(signer types.Signer, txs []*types.Transact
} }
} }
// recoverFromBlocks recovers the senders from a batch of blocks and caches them // RecoverFromBlocks recovers the senders from a batch of blocks and caches them
// back into the same data structures. There is no validation being done, nor // back into the same data structures. There is no validation being done, nor
// any reaction to invalid signatures. That is up to calling code later. // any reaction to invalid signatures. That is up to calling code later.
func (cacher *txSenderCacher) recoverFromBlocks(signer types.Signer, blocks []*types.Block) { func (cacher *txSenderCacher) RecoverFromBlocks(signer types.Signer, blocks []*types.Block) {
count := 0 count := 0
for _, block := range blocks { for _, block := range blocks {
count += len(block.Transactions()) count += len(block.Transactions())
@ -101,5 +101,5 @@ func (cacher *txSenderCacher) recoverFromBlocks(signer types.Signer, blocks []*t
for _, block := range blocks { for _, block := range blocks {
txs = append(txs, block.Transactions()...) txs = append(txs, block.Transactions()...)
} }
cacher.recover(signer, txs) cacher.Recover(signer, txs)
} }

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package txpool
import ( import (
"errors" "errors"
@ -41,23 +41,23 @@ type devNull struct{}
func (*devNull) Write(p []byte) (n int, err error) { return len(p), nil } func (*devNull) Write(p []byte) (n int, err error) { return len(p), nil }
func (*devNull) Close() error { return nil } func (*devNull) Close() error { return nil }
// txJournal is a rotating log of transactions with the aim of storing locally // journal is a rotating log of transactions with the aim of storing locally
// created transactions to allow non-executed ones to survive node restarts. // created transactions to allow non-executed ones to survive node restarts.
type txJournal struct { type journal struct {
path string // Filesystem path to store the transactions at path string // Filesystem path to store the transactions at
writer io.WriteCloser // Output stream to write new transactions into writer io.WriteCloser // Output stream to write new transactions into
} }
// newTxJournal creates a new transaction journal to // newTxJournal creates a new transaction journal to
func newTxJournal(path string) *txJournal { func newTxJournal(path string) *journal {
return &txJournal{ return &journal{
path: path, path: path,
} }
} }
// load parses a transaction journal dump from disk, loading its contents into // load parses a transaction journal dump from disk, loading its contents into
// the specified pool. // the specified pool.
func (journal *txJournal) load(add func([]*types.Transaction) []error) error { func (journal *journal) load(add func([]*types.Transaction) []error) error {
// Open the journal for loading any past transactions // Open the journal for loading any past transactions
input, err := os.Open(journal.path) input, err := os.Open(journal.path)
if errors.Is(err, fs.ErrNotExist) { if errors.Is(err, fs.ErrNotExist) {
@ -118,7 +118,7 @@ func (journal *txJournal) load(add func([]*types.Transaction) []error) error {
} }
// insert adds the specified transaction to the local disk journal. // insert adds the specified transaction to the local disk journal.
func (journal *txJournal) insert(tx *types.Transaction) error { func (journal *journal) insert(tx *types.Transaction) error {
if journal.writer == nil { if journal.writer == nil {
return errNoActiveJournal return errNoActiveJournal
} }
@ -130,7 +130,7 @@ func (journal *txJournal) insert(tx *types.Transaction) error {
// rotate regenerates the transaction journal based on the current contents of // rotate regenerates the transaction journal based on the current contents of
// the transaction pool. // the transaction pool.
func (journal *txJournal) rotate(all map[common.Address]types.Transactions) error { func (journal *journal) rotate(all map[common.Address]types.Transactions) error {
// Close the current journal (if any is open) // Close the current journal (if any is open)
if journal.writer != nil { if journal.writer != nil {
if err := journal.writer.Close(); err != nil { if err := journal.writer.Close(); err != nil {
@ -170,7 +170,7 @@ func (journal *txJournal) rotate(all map[common.Address]types.Transactions) erro
} }
// close flushes the transaction journal contents to disk and closes the file. // close flushes the transaction journal contents to disk and closes the file.
func (journal *txJournal) close() error { func (journal *journal) close() error {
var err error var err error
if journal.writer != nil { if journal.writer != nil {

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package txpool
import ( import (
"container/heap" "container/heap"
@ -49,30 +49,30 @@ func (h *nonceHeap) Pop() interface{} {
return x return x
} }
// txSortedMap is a nonce->transaction hash map with a heap based index to allow // sortedMap is a nonce->transaction hash map with a heap based index to allow
// iterating over the contents in a nonce-incrementing way. // iterating over the contents in a nonce-incrementing way.
type txSortedMap struct { type sortedMap struct {
items map[uint64]*types.Transaction // Hash map storing the transaction data items map[uint64]*types.Transaction // Hash map storing the transaction data
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode) index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
cache types.Transactions // Cache of the transactions already sorted cache types.Transactions // Cache of the transactions already sorted
} }
// newTxSortedMap creates a new nonce-sorted transaction map. // newSortedMap creates a new nonce-sorted transaction map.
func newTxSortedMap() *txSortedMap { func newSortedMap() *sortedMap {
return &txSortedMap{ return &sortedMap{
items: make(map[uint64]*types.Transaction), items: make(map[uint64]*types.Transaction),
index: new(nonceHeap), index: new(nonceHeap),
} }
} }
// Get retrieves the current transactions associated with the given nonce. // Get retrieves the current transactions associated with the given nonce.
func (m *txSortedMap) Get(nonce uint64) *types.Transaction { func (m *sortedMap) Get(nonce uint64) *types.Transaction {
return m.items[nonce] return m.items[nonce]
} }
// Put inserts a new transaction into the map, also updating the map's nonce // Put inserts a new transaction into the map, also updating the map's nonce
// index. If a transaction already exists with the same nonce, it's overwritten. // index. If a transaction already exists with the same nonce, it's overwritten.
func (m *txSortedMap) Put(tx *types.Transaction) { func (m *sortedMap) Put(tx *types.Transaction) {
nonce := tx.Nonce() nonce := tx.Nonce()
if m.items[nonce] == nil { if m.items[nonce] == nil {
heap.Push(m.index, nonce) heap.Push(m.index, nonce)
@ -83,7 +83,7 @@ func (m *txSortedMap) Put(tx *types.Transaction) {
// Forward removes all transactions from the map with a nonce lower than the // Forward removes all transactions from the map with a nonce lower than the
// provided threshold. Every removed transaction is returned for any post-removal // provided threshold. Every removed transaction is returned for any post-removal
// maintenance. // maintenance.
func (m *txSortedMap) Forward(threshold uint64) types.Transactions { func (m *sortedMap) Forward(threshold uint64) types.Transactions {
var removed types.Transactions var removed types.Transactions
// Pop off heap items until the threshold is reached // Pop off heap items until the threshold is reached
@ -104,7 +104,7 @@ func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
// Filter, as opposed to 'filter', re-initialises the heap after the operation is done. // Filter, as opposed to 'filter', re-initialises the heap after the operation is done.
// If you want to do several consecutive filterings, it's therefore better to first // If you want to do several consecutive filterings, it's therefore better to first
// do a .filter(func1) followed by .Filter(func2) or reheap() // do a .filter(func1) followed by .Filter(func2) or reheap()
func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions { func (m *sortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
removed := m.filter(filter) removed := m.filter(filter)
// If transactions were removed, the heap and cache are ruined // If transactions were removed, the heap and cache are ruined
if len(removed) > 0 { if len(removed) > 0 {
@ -113,7 +113,7 @@ func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transac
return removed return removed
} }
func (m *txSortedMap) reheap() { func (m *sortedMap) reheap() {
*m.index = make([]uint64, 0, len(m.items)) *m.index = make([]uint64, 0, len(m.items))
for nonce := range m.items { for nonce := range m.items {
*m.index = append(*m.index, nonce) *m.index = append(*m.index, nonce)
@ -124,7 +124,7 @@ func (m *txSortedMap) reheap() {
// filter is identical to Filter, but **does not** regenerate the heap. This method // filter is identical to Filter, but **does not** regenerate the heap. This method
// should only be used if followed immediately by a call to Filter or reheap() // should only be used if followed immediately by a call to Filter or reheap()
func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transactions { func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transactions {
var removed types.Transactions var removed types.Transactions
// Collect all the transactions to filter out // Collect all the transactions to filter out
@ -142,7 +142,7 @@ func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transac
// Cap places a hard limit on the number of items, returning all transactions // Cap places a hard limit on the number of items, returning all transactions
// exceeding that limit. // exceeding that limit.
func (m *txSortedMap) Cap(threshold int) types.Transactions { func (m *sortedMap) Cap(threshold int) types.Transactions {
// Short circuit if the number of items is under the limit // Short circuit if the number of items is under the limit
if len(m.items) <= threshold { if len(m.items) <= threshold {
return nil return nil
@ -167,7 +167,7 @@ func (m *txSortedMap) Cap(threshold int) types.Transactions {
// Remove deletes a transaction from the maintained map, returning whether the // Remove deletes a transaction from the maintained map, returning whether the
// transaction was found. // transaction was found.
func (m *txSortedMap) Remove(nonce uint64) bool { func (m *sortedMap) Remove(nonce uint64) bool {
// Short circuit if no transaction is present // Short circuit if no transaction is present
_, ok := m.items[nonce] _, ok := m.items[nonce]
if !ok { if !ok {
@ -193,7 +193,7 @@ func (m *txSortedMap) Remove(nonce uint64) bool {
// Note, all transactions with nonces lower than start will also be returned to // Note, all transactions with nonces lower than start will also be returned to
// prevent getting into and invalid state. This is not something that should ever // prevent getting into and invalid state. This is not something that should ever
// happen but better to be self correcting than failing! // happen but better to be self correcting than failing!
func (m *txSortedMap) Ready(start uint64) types.Transactions { func (m *sortedMap) Ready(start uint64) types.Transactions {
// Short circuit if no transactions are available // Short circuit if no transactions are available
if m.index.Len() == 0 || (*m.index)[0] > start { if m.index.Len() == 0 || (*m.index)[0] > start {
return nil return nil
@ -211,11 +211,11 @@ func (m *txSortedMap) Ready(start uint64) types.Transactions {
} }
// Len returns the length of the transaction map. // Len returns the length of the transaction map.
func (m *txSortedMap) Len() int { func (m *sortedMap) Len() int {
return len(m.items) return len(m.items)
} }
func (m *txSortedMap) flatten() types.Transactions { func (m *sortedMap) flatten() types.Transactions {
// If the sorting was not cached yet, create and cache it // If the sorting was not cached yet, create and cache it
if m.cache == nil { if m.cache == nil {
m.cache = make(types.Transactions, 0, len(m.items)) m.cache = make(types.Transactions, 0, len(m.items))
@ -230,7 +230,7 @@ func (m *txSortedMap) flatten() types.Transactions {
// Flatten creates a nonce-sorted slice of transactions based on the loosely // Flatten creates a nonce-sorted slice of transactions based on the loosely
// sorted internal representation. The result of the sorting is cached in case // sorted internal representation. The result of the sorting is cached in case
// it's requested again before any modifications are made to the contents. // it's requested again before any modifications are made to the contents.
func (m *txSortedMap) Flatten() types.Transactions { func (m *sortedMap) Flatten() types.Transactions {
// Copy the cache to prevent accidental modifications // Copy the cache to prevent accidental modifications
cache := m.flatten() cache := m.flatten()
txs := make(types.Transactions, len(cache)) txs := make(types.Transactions, len(cache))
@ -240,36 +240,36 @@ func (m *txSortedMap) Flatten() types.Transactions {
// LastElement returns the last element of a flattened list, thus, the // LastElement returns the last element of a flattened list, thus, the
// transaction with the highest nonce // transaction with the highest nonce
func (m *txSortedMap) LastElement() *types.Transaction { func (m *sortedMap) LastElement() *types.Transaction {
cache := m.flatten() cache := m.flatten()
return cache[len(cache)-1] return cache[len(cache)-1]
} }
// txList is a "list" of transactions belonging to an account, sorted by account // list is a "list" of transactions belonging to an account, sorted by account
// nonce. The same type can be used both for storing contiguous transactions for // nonce. The same type can be used both for storing contiguous transactions for
// the executable/pending queue; and for storing gapped transactions for the non- // the executable/pending queue; and for storing gapped transactions for the non-
// executable/future queue, with minor behavioral changes. // executable/future queue, with minor behavioral changes.
type txList struct { type list struct {
strict bool // Whether nonces are strictly continuous or not strict bool // Whether nonces are strictly continuous or not
txs *txSortedMap // Heap indexed sorted hash map of the transactions txs *sortedMap // Heap indexed sorted hash map of the transactions
costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance) costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit) gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
} }
// newTxList create a new transaction list for maintaining nonce-indexable fast, // newList create a new transaction list for maintaining nonce-indexable fast,
// gapped, sortable transaction lists. // gapped, sortable transaction lists.
func newTxList(strict bool) *txList { func newList(strict bool) *list {
return &txList{ return &list{
strict: strict, strict: strict,
txs: newTxSortedMap(), txs: newSortedMap(),
costcap: new(big.Int), costcap: new(big.Int),
} }
} }
// Overlaps returns whether the transaction specified has the same nonce as one // Overlaps returns whether the transaction specified has the same nonce as one
// already contained within the list. // already contained within the list.
func (l *txList) Overlaps(tx *types.Transaction) bool { func (l *list) Overlaps(tx *types.Transaction) bool {
return l.txs.Get(tx.Nonce()) != nil return l.txs.Get(tx.Nonce()) != nil
} }
@ -278,7 +278,7 @@ func (l *txList) Overlaps(tx *types.Transaction) bool {
// //
// If the new transaction is accepted into the list, the lists' cost and gas // If the new transaction is accepted into the list, the lists' cost and gas
// thresholds are also potentially updated. // thresholds are also potentially updated.
func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) { func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
// If there's an older better transaction, abort // If there's an older better transaction, abort
old := l.txs.Get(tx.Nonce()) old := l.txs.Get(tx.Nonce())
if old != nil { if old != nil {
@ -316,7 +316,7 @@ func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Tran
// Forward removes all transactions from the list with a nonce lower than the // Forward removes all transactions from the list with a nonce lower than the
// provided threshold. Every removed transaction is returned for any post-removal // provided threshold. Every removed transaction is returned for any post-removal
// maintenance. // maintenance.
func (l *txList) Forward(threshold uint64) types.Transactions { func (l *list) Forward(threshold uint64) types.Transactions {
return l.txs.Forward(threshold) return l.txs.Forward(threshold)
} }
@ -329,7 +329,7 @@ func (l *txList) Forward(threshold uint64) types.Transactions {
// a point in calculating all the costs or if the balance covers all. If the threshold // a point in calculating all the costs or if the balance covers all. If the threshold
// is lower than the costgas cap, the caps will be reset to a new high after removing // is lower than the costgas cap, the caps will be reset to a new high after removing
// the newly invalidated transactions. // the newly invalidated transactions.
func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) { func (l *list) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
// If all transactions are below the threshold, short circuit // If all transactions are below the threshold, short circuit
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit { if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
return nil, nil return nil, nil
@ -362,14 +362,14 @@ func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions
// Cap places a hard limit on the number of items, returning all transactions // Cap places a hard limit on the number of items, returning all transactions
// exceeding that limit. // exceeding that limit.
func (l *txList) Cap(threshold int) types.Transactions { func (l *list) Cap(threshold int) types.Transactions {
return l.txs.Cap(threshold) return l.txs.Cap(threshold)
} }
// Remove deletes a transaction from the maintained list, returning whether the // Remove deletes a transaction from the maintained list, returning whether the
// transaction was found, and also returning any transaction invalidated due to // transaction was found, and also returning any transaction invalidated due to
// the deletion (strict mode only). // the deletion (strict mode only).
func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) { func (l *list) Remove(tx *types.Transaction) (bool, types.Transactions) {
// Remove the transaction from the set // Remove the transaction from the set
nonce := tx.Nonce() nonce := tx.Nonce()
if removed := l.txs.Remove(nonce); !removed { if removed := l.txs.Remove(nonce); !removed {
@ -389,30 +389,30 @@ func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) {
// Note, all transactions with nonces lower than start will also be returned to // Note, all transactions with nonces lower than start will also be returned to
// prevent getting into and invalid state. This is not something that should ever // prevent getting into and invalid state. This is not something that should ever
// happen but better to be self correcting than failing! // happen but better to be self correcting than failing!
func (l *txList) Ready(start uint64) types.Transactions { func (l *list) Ready(start uint64) types.Transactions {
return l.txs.Ready(start) return l.txs.Ready(start)
} }
// Len returns the length of the transaction list. // Len returns the length of the transaction list.
func (l *txList) Len() int { func (l *list) Len() int {
return l.txs.Len() return l.txs.Len()
} }
// Empty returns whether the list of transactions is empty or not. // Empty returns whether the list of transactions is empty or not.
func (l *txList) Empty() bool { func (l *list) Empty() bool {
return l.Len() == 0 return l.Len() == 0
} }
// Flatten creates a nonce-sorted slice of transactions based on the loosely // Flatten creates a nonce-sorted slice of transactions based on the loosely
// sorted internal representation. The result of the sorting is cached in case // sorted internal representation. The result of the sorting is cached in case
// it's requested again before any modifications are made to the contents. // it's requested again before any modifications are made to the contents.
func (l *txList) Flatten() types.Transactions { func (l *list) Flatten() types.Transactions {
return l.txs.Flatten() return l.txs.Flatten()
} }
// LastElement returns the last element of a flattened list, thus, the // LastElement returns the last element of a flattened list, thus, the
// transaction with the highest nonce // transaction with the highest nonce
func (l *txList) LastElement() *types.Transaction { func (l *list) LastElement() *types.Transaction {
return l.txs.LastElement() return l.txs.LastElement()
} }
@ -468,7 +468,7 @@ func (h *priceHeap) Pop() interface{} {
return x return x
} }
// txPricedList is a price-sorted heap to allow operating on transactions pool // pricedList is a price-sorted heap to allow operating on transactions pool
// contents in a price-incrementing way. It's built upon the all transactions // contents in a price-incrementing way. It's built upon the all transactions
// in txpool but only interested in the remote part. It means only remote transactions // in txpool but only interested in the remote part. It means only remote transactions
// will be considered for tracking, sorting, eviction, etc. // will be considered for tracking, sorting, eviction, etc.
@ -479,14 +479,14 @@ func (h *priceHeap) Pop() interface{} {
// In some cases (during a congestion, when blocks are full) the urgent heap can provide // In some cases (during a congestion, when blocks are full) the urgent heap can provide
// better candidates for inclusion while in other cases (at the top of the baseFee peak) // better candidates for inclusion while in other cases (at the top of the baseFee peak)
// the floating heap is better. When baseFee is decreasing they behave similarly. // the floating heap is better. When baseFee is decreasing they behave similarly.
type txPricedList struct { type pricedList struct {
// Number of stale price points to (re-heap trigger). // Number of stale price points to (re-heap trigger).
// This field is accessed atomically, and must be the first field // This field is accessed atomically, and must be the first field
// to ensure it has correct alignment for atomic.AddInt64. // to ensure it has correct alignment for atomic.AddInt64.
// See https://golang.org/pkg/sync/atomic/#pkg-note-BUG. // See https://golang.org/pkg/sync/atomic/#pkg-note-BUG.
stales int64 stales int64
all *txLookup // Pointer to the map of all transactions all *lookup // Pointer to the map of all transactions
urgent, floating priceHeap // Heaps of prices of all the stored **remote** transactions urgent, floating priceHeap // Heaps of prices of all the stored **remote** transactions
reheapMu sync.Mutex // Mutex asserts that only one routine is reheaping the list reheapMu sync.Mutex // Mutex asserts that only one routine is reheaping the list
} }
@ -497,15 +497,15 @@ const (
floatingRatio = 1 floatingRatio = 1
) )
// newTxPricedList creates a new price-sorted transaction heap. // newPricedList creates a new price-sorted transaction heap.
func newTxPricedList(all *txLookup) *txPricedList { func newPricedList(all *lookup) *pricedList {
return &txPricedList{ return &pricedList{
all: all, all: all,
} }
} }
// Put inserts a new transaction into the heap. // Put inserts a new transaction into the heap.
func (l *txPricedList) Put(tx *types.Transaction, local bool) { func (l *pricedList) Put(tx *types.Transaction, local bool) {
if local { if local {
return return
} }
@ -516,7 +516,7 @@ func (l *txPricedList) Put(tx *types.Transaction, local bool) {
// Removed notifies the prices transaction list that an old transaction dropped // Removed notifies the prices transaction list that an old transaction dropped
// from the pool. The list will just keep a counter of stale objects and update // from the pool. The list will just keep a counter of stale objects and update
// the heap if a large enough ratio of transactions go stale. // the heap if a large enough ratio of transactions go stale.
func (l *txPricedList) Removed(count int) { func (l *pricedList) Removed(count int) {
// Bump the stale counter, but exit if still too low (< 25%) // Bump the stale counter, but exit if still too low (< 25%)
stales := atomic.AddInt64(&l.stales, int64(count)) stales := atomic.AddInt64(&l.stales, int64(count))
if int(stales) <= (len(l.urgent.list)+len(l.floating.list))/4 { if int(stales) <= (len(l.urgent.list)+len(l.floating.list))/4 {
@ -528,7 +528,7 @@ func (l *txPricedList) Removed(count int) {
// Underpriced checks whether a transaction is cheaper than (or as cheap as) the // Underpriced checks whether a transaction is cheaper than (or as cheap as) the
// lowest priced (remote) transaction currently being tracked. // lowest priced (remote) transaction currently being tracked.
func (l *txPricedList) Underpriced(tx *types.Transaction) bool { func (l *pricedList) Underpriced(tx *types.Transaction) bool {
// Note: with two queues, being underpriced is defined as being worse than the worst item // Note: with two queues, being underpriced is defined as being worse than the worst item
// in all non-empty queues if there is any. If both queues are empty then nothing is underpriced. // in all non-empty queues if there is any. If both queues are empty then nothing is underpriced.
return (l.underpricedFor(&l.urgent, tx) || len(l.urgent.list) == 0) && return (l.underpricedFor(&l.urgent, tx) || len(l.urgent.list) == 0) &&
@ -538,7 +538,7 @@ func (l *txPricedList) Underpriced(tx *types.Transaction) bool {
// underpricedFor checks whether a transaction is cheaper than (or as cheap as) the // underpricedFor checks whether a transaction is cheaper than (or as cheap as) the
// lowest priced (remote) transaction in the given heap. // lowest priced (remote) transaction in the given heap.
func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool { func (l *pricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool {
// Discard stale price points if found at the heap start // Discard stale price points if found at the heap start
for len(h.list) > 0 { for len(h.list) > 0 {
head := h.list[0] head := h.list[0]
@ -562,7 +562,7 @@ func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool
// priced list and returns them for further removal from the entire pool. // priced list and returns them for further removal from the entire pool.
// //
// Note local transaction won't be considered for eviction. // Note local transaction won't be considered for eviction.
func (l *txPricedList) Discard(slots int, force bool) (types.Transactions, bool) { func (l *pricedList) Discard(slots int, force bool) (types.Transactions, bool) {
drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop
for slots > 0 { for slots > 0 {
if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio || floatingRatio == 0 { if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio || floatingRatio == 0 {
@ -601,7 +601,7 @@ func (l *txPricedList) Discard(slots int, force bool) (types.Transactions, bool)
} }
// Reheap forcibly rebuilds the heap based on the current remote transaction set. // Reheap forcibly rebuilds the heap based on the current remote transaction set.
func (l *txPricedList) Reheap() { func (l *pricedList) Reheap() {
l.reheapMu.Lock() l.reheapMu.Lock()
defer l.reheapMu.Unlock() defer l.reheapMu.Unlock()
start := time.Now() start := time.Now()
@ -629,7 +629,7 @@ func (l *txPricedList) Reheap() {
// SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not // SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not
// necessary to call right before SetBaseFee when processing a new block. // necessary to call right before SetBaseFee when processing a new block.
func (l *txPricedList) SetBaseFee(baseFee *big.Int) { func (l *pricedList) SetBaseFee(baseFee *big.Int) {
l.urgent.baseFee = baseFee l.urgent.baseFee = baseFee
l.Reheap() l.Reheap()
} }

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package txpool
import ( import (
"math/big" "math/big"
@ -27,7 +27,7 @@ import (
// Tests that transactions can be added to strict lists and list contents and // Tests that transactions can be added to strict lists and list contents and
// nonce boundaries are correctly maintained. // nonce boundaries are correctly maintained.
func TestStrictTxListAdd(t *testing.T) { func TestStrictListAdd(t *testing.T) {
// Generate a list of transactions to insert // Generate a list of transactions to insert
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
@ -36,9 +36,9 @@ func TestStrictTxListAdd(t *testing.T) {
txs[i] = transaction(uint64(i), 0, key) txs[i] = transaction(uint64(i), 0, key)
} }
// Insert the transactions in a random order // Insert the transactions in a random order
list := newTxList(true) list := newList(true)
for _, v := range rand.Perm(len(txs)) { for _, v := range rand.Perm(len(txs)) {
list.Add(txs[v], DefaultTxPoolConfig.PriceBump) list.Add(txs[v], DefaultConfig.PriceBump)
} }
// Verify internal state // Verify internal state
if len(list.txs.items) != len(txs) { if len(list.txs.items) != len(txs) {
@ -51,7 +51,7 @@ func TestStrictTxListAdd(t *testing.T) {
} }
} }
func BenchmarkTxListAdd(b *testing.B) { func BenchmarkListAdd(b *testing.B) {
// Generate a list of transactions to insert // Generate a list of transactions to insert
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
@ -60,13 +60,13 @@ func BenchmarkTxListAdd(b *testing.B) {
txs[i] = transaction(uint64(i), 0, key) txs[i] = transaction(uint64(i), 0, key)
} }
// Insert the transactions in a random order // Insert the transactions in a random order
priceLimit := big.NewInt(int64(DefaultTxPoolConfig.PriceLimit)) priceLimit := big.NewInt(int64(DefaultConfig.PriceLimit))
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
list := newTxList(true) list := newList(true)
for _, v := range rand.Perm(len(txs)) { for _, v := range rand.Perm(len(txs)) {
list.Add(txs[v], DefaultTxPoolConfig.PriceBump) list.Add(txs[v], DefaultConfig.PriceBump)
list.Filter(priceLimit, DefaultTxPoolConfig.PriceBump) list.Filter(priceLimit, DefaultConfig.PriceBump)
} }
} }
} }

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package txpool
import ( import (
"sync" "sync"
@ -23,18 +23,18 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
) )
// txNoncer is a tiny virtual state database to manage the executable nonces of // noncer is a tiny virtual state database to manage the executable nonces of
// accounts in the pool, falling back to reading from a real state database if // accounts in the pool, falling back to reading from a real state database if
// an account is unknown. // an account is unknown.
type txNoncer struct { type noncer struct {
fallback *state.StateDB fallback *state.StateDB
nonces map[common.Address]uint64 nonces map[common.Address]uint64
lock sync.Mutex lock sync.Mutex
} }
// newTxNoncer creates a new virtual state database to track the pool nonces. // newNoncer creates a new virtual state database to track the pool nonces.
func newTxNoncer(statedb *state.StateDB) *txNoncer { func newNoncer(statedb *state.StateDB) *noncer {
return &txNoncer{ return &noncer{
fallback: statedb.Copy(), fallback: statedb.Copy(),
nonces: make(map[common.Address]uint64), nonces: make(map[common.Address]uint64),
} }
@ -42,7 +42,7 @@ func newTxNoncer(statedb *state.StateDB) *txNoncer {
// get returns the current nonce of an account, falling back to a real state // get returns the current nonce of an account, falling back to a real state
// database if the account is unknown. // database if the account is unknown.
func (txn *txNoncer) get(addr common.Address) uint64 { func (txn *noncer) get(addr common.Address) uint64 {
// We use mutex for get operation is the underlying // We use mutex for get operation is the underlying
// state will mutate db even for read access. // state will mutate db even for read access.
txn.lock.Lock() txn.lock.Lock()
@ -58,7 +58,7 @@ func (txn *txNoncer) get(addr common.Address) uint64 {
// set inserts a new virtual nonce into the virtual state database to be returned // set inserts a new virtual nonce into the virtual state database to be returned
// whenever the pool requests it instead of reaching into the real state database. // whenever the pool requests it instead of reaching into the real state database.
func (txn *txNoncer) set(addr common.Address, nonce uint64) { func (txn *noncer) set(addr common.Address, nonce uint64) {
txn.lock.Lock() txn.lock.Lock()
defer txn.lock.Unlock() defer txn.lock.Unlock()
@ -67,7 +67,7 @@ func (txn *txNoncer) set(addr common.Address, nonce uint64) {
// setIfLower updates a new virtual nonce into the virtual state database if the // setIfLower updates a new virtual nonce into the virtual state database if the
// new one is lower. // new one is lower.
func (txn *txNoncer) setIfLower(addr common.Address, nonce uint64) { func (txn *noncer) setIfLower(addr common.Address, nonce uint64) {
txn.lock.Lock() txn.lock.Lock()
defer txn.lock.Unlock() defer txn.lock.Unlock()
@ -83,7 +83,7 @@ func (txn *txNoncer) setIfLower(addr common.Address, nonce uint64) {
} }
// setAll sets the nonces for all accounts to the given map. // setAll sets the nonces for all accounts to the given map.
func (txn *txNoncer) setAll(all map[common.Address]uint64) { func (txn *noncer) setAll(all map[common.Address]uint64) {
txn.lock.Lock() txn.lock.Lock()
defer txn.lock.Unlock() defer txn.lock.Unlock()

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package txpool
import ( import (
"errors" "errors"
@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -112,6 +113,7 @@ var (
invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil) invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil)
underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil) underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil)
overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil) overflowedTxMeter = metrics.NewRegisteredMeter("txpool/overflowed", nil)
// throttleTxMeter counts how many transactions are rejected due to too-many-changes between // throttleTxMeter counts how many transactions are rejected due to too-many-changes between
// txpool reorgs. // txpool reorgs.
throttleTxMeter = metrics.NewRegisteredMeter("txpool/throttle", nil) throttleTxMeter = metrics.NewRegisteredMeter("txpool/throttle", nil)
@ -146,11 +148,11 @@ type blockChain interface {
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
StateAt(root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (*state.StateDB, error)
SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
} }
// TxPoolConfig are the configuration parameters of the transaction pool. // Config are the configuration parameters of the transaction pool.
type TxPoolConfig struct { type Config struct {
Locals []common.Address // Addresses that should be treated by default as local Locals []common.Address // Addresses that should be treated by default as local
NoLocals bool // Whether local transaction handling should be disabled NoLocals bool // Whether local transaction handling should be disabled
Journal string // Journal of local transactions to survive node restarts Journal string // Journal of local transactions to survive node restarts
@ -167,9 +169,9 @@ type TxPoolConfig struct {
Lifetime time.Duration // Maximum amount of time non-executable transaction are queued Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
} }
// DefaultTxPoolConfig contains the default configurations for the transaction // DefaultConfig contains the default configurations for the transaction
// pool. // pool.
var DefaultTxPoolConfig = TxPoolConfig{ var DefaultConfig = Config{
Journal: "transactions.rlp", Journal: "transactions.rlp",
Rejournal: time.Hour, Rejournal: time.Hour,
@ -186,39 +188,39 @@ var DefaultTxPoolConfig = TxPoolConfig{
// sanitize checks the provided user configurations and changes anything that's // sanitize checks the provided user configurations and changes anything that's
// unreasonable or unworkable. // unreasonable or unworkable.
func (config *TxPoolConfig) sanitize() TxPoolConfig { func (config *Config) sanitize() Config {
conf := *config conf := *config
if conf.Rejournal < time.Second { if conf.Rejournal < time.Second {
log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second) log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second)
conf.Rejournal = time.Second conf.Rejournal = time.Second
} }
if conf.PriceLimit < 1 { if conf.PriceLimit < 1 {
log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit) log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultConfig.PriceLimit)
conf.PriceLimit = DefaultTxPoolConfig.PriceLimit conf.PriceLimit = DefaultConfig.PriceLimit
} }
if conf.PriceBump < 1 { if conf.PriceBump < 1 {
log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultTxPoolConfig.PriceBump) log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultConfig.PriceBump)
conf.PriceBump = DefaultTxPoolConfig.PriceBump conf.PriceBump = DefaultConfig.PriceBump
} }
if conf.AccountSlots < 1 { if conf.AccountSlots < 1 {
log.Warn("Sanitizing invalid txpool account slots", "provided", conf.AccountSlots, "updated", DefaultTxPoolConfig.AccountSlots) log.Warn("Sanitizing invalid txpool account slots", "provided", conf.AccountSlots, "updated", DefaultConfig.AccountSlots)
conf.AccountSlots = DefaultTxPoolConfig.AccountSlots conf.AccountSlots = DefaultConfig.AccountSlots
} }
if conf.GlobalSlots < 1 { if conf.GlobalSlots < 1 {
log.Warn("Sanitizing invalid txpool global slots", "provided", conf.GlobalSlots, "updated", DefaultTxPoolConfig.GlobalSlots) log.Warn("Sanitizing invalid txpool global slots", "provided", conf.GlobalSlots, "updated", DefaultConfig.GlobalSlots)
conf.GlobalSlots = DefaultTxPoolConfig.GlobalSlots conf.GlobalSlots = DefaultConfig.GlobalSlots
} }
if conf.AccountQueue < 1 { if conf.AccountQueue < 1 {
log.Warn("Sanitizing invalid txpool account queue", "provided", conf.AccountQueue, "updated", DefaultTxPoolConfig.AccountQueue) log.Warn("Sanitizing invalid txpool account queue", "provided", conf.AccountQueue, "updated", DefaultConfig.AccountQueue)
conf.AccountQueue = DefaultTxPoolConfig.AccountQueue conf.AccountQueue = DefaultConfig.AccountQueue
} }
if conf.GlobalQueue < 1 { if conf.GlobalQueue < 1 {
log.Warn("Sanitizing invalid txpool global queue", "provided", conf.GlobalQueue, "updated", DefaultTxPoolConfig.GlobalQueue) log.Warn("Sanitizing invalid txpool global queue", "provided", conf.GlobalQueue, "updated", DefaultConfig.GlobalQueue)
conf.GlobalQueue = DefaultTxPoolConfig.GlobalQueue conf.GlobalQueue = DefaultConfig.GlobalQueue
} }
if conf.Lifetime < 1 { if conf.Lifetime < 1 {
log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultTxPoolConfig.Lifetime) log.Warn("Sanitizing invalid txpool lifetime", "provided", conf.Lifetime, "updated", DefaultConfig.Lifetime)
conf.Lifetime = DefaultTxPoolConfig.Lifetime conf.Lifetime = DefaultConfig.Lifetime
} }
return conf return conf
} }
@ -231,7 +233,7 @@ func (config *TxPoolConfig) sanitize() TxPoolConfig {
// current state) and future transactions. Transactions move between those // current state) and future transactions. Transactions move between those
// two states over time as they are received and processed. // two states over time as they are received and processed.
type TxPool struct { type TxPool struct {
config TxPoolConfig config Config
chainconfig *params.ChainConfig chainconfig *params.ChainConfig
chain blockChain chain blockChain
gasPrice *big.Int gasPrice *big.Int
@ -245,19 +247,19 @@ type TxPool struct {
eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions. eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions.
currentState *state.StateDB // Current state in the blockchain head currentState *state.StateDB // Current state in the blockchain head
pendingNonces *txNoncer // Pending state tracking virtual nonces pendingNonces *noncer // Pending state tracking virtual nonces
currentMaxGas uint64 // Current gas limit for transaction caps currentMaxGas uint64 // Current gas limit for transaction caps
locals *accountSet // Set of local transaction to exempt from eviction rules locals *accountSet // Set of local transaction to exempt from eviction rules
journal *txJournal // Journal of local transaction to back up to disk journal *journal // Journal of local transaction to back up to disk
pending map[common.Address]*txList // All currently processable transactions pending map[common.Address]*list // All currently processable transactions
queue map[common.Address]*txList // Queued but non-processable transactions queue map[common.Address]*list // Queued but non-processable transactions
beats map[common.Address]time.Time // Last heartbeat from each known account beats map[common.Address]time.Time // Last heartbeat from each known account
all *txLookup // All transactions to allow lookups all *lookup // All transactions to allow lookups
priced *txPricedList // All transactions sorted by price priced *pricedList // All transactions sorted by price
chainHeadCh chan ChainHeadEvent chainHeadCh chan core.ChainHeadEvent
chainHeadSub event.Subscription chainHeadSub event.Subscription
reqResetCh chan *txpoolResetRequest reqResetCh chan *txpoolResetRequest
reqPromoteCh chan *accountSet reqPromoteCh chan *accountSet
@ -276,7 +278,7 @@ type txpoolResetRequest struct {
// NewTxPool creates a new transaction pool to gather, sort and filter inbound // NewTxPool creates a new transaction pool to gather, sort and filter inbound
// transactions from the network. // transactions from the network.
func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool { func NewTxPool(config Config, chainconfig *params.ChainConfig, chain blockChain) *TxPool {
// Sanitize the input to ensure no vulnerable gas prices are set // Sanitize the input to ensure no vulnerable gas prices are set
config = (&config).sanitize() config = (&config).sanitize()
@ -286,11 +288,11 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
chainconfig: chainconfig, chainconfig: chainconfig,
chain: chain, chain: chain,
signer: types.LatestSigner(chainconfig), signer: types.LatestSigner(chainconfig),
pending: make(map[common.Address]*txList), pending: make(map[common.Address]*list),
queue: make(map[common.Address]*txList), queue: make(map[common.Address]*list),
beats: make(map[common.Address]time.Time), beats: make(map[common.Address]time.Time),
all: newTxLookup(), all: newLookup(),
chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
reqResetCh: make(chan *txpoolResetRequest), reqResetCh: make(chan *txpoolResetRequest),
reqPromoteCh: make(chan *accountSet), reqPromoteCh: make(chan *accountSet),
queueTxEventCh: make(chan *types.Transaction), queueTxEventCh: make(chan *types.Transaction),
@ -304,7 +306,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
log.Info("Setting new local account", "address", addr) log.Info("Setting new local account", "address", addr)
pool.locals.add(addr) pool.locals.add(addr)
} }
pool.priced = newTxPricedList(pool.all) pool.priced = newPricedList(pool.all)
pool.reset(nil, chain.CurrentBlock().Header()) pool.reset(nil, chain.CurrentBlock().Header())
// Start the reorg loop early so it can handle requests generated during journal loading. // Start the reorg loop early so it can handle requests generated during journal loading.
@ -427,7 +429,7 @@ func (pool *TxPool) Stop() {
// SubscribeNewTxsEvent registers a subscription of NewTxsEvent and // SubscribeNewTxsEvent registers a subscription of NewTxsEvent and
// starts sending event to the given channel. // starts sending event to the given channel.
func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- NewTxsEvent) event.Subscription { func (pool *TxPool) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
return pool.scope.Track(pool.txFeed.Subscribe(ch)) return pool.scope.Track(pool.txFeed.Subscribe(ch))
} }
@ -586,11 +588,11 @@ func (pool *TxPool) local() map[common.Address]types.Transactions {
func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
// Accept only legacy transactions until EIP-2718/2930 activates. // Accept only legacy transactions until EIP-2718/2930 activates.
if !pool.eip2718 && tx.Type() != types.LegacyTxType { if !pool.eip2718 && tx.Type() != types.LegacyTxType {
return ErrTxTypeNotSupported return core.ErrTxTypeNotSupported
} }
// Reject dynamic fee transactions until EIP-1559 activates. // Reject dynamic fee transactions until EIP-1559 activates.
if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType { if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType {
return ErrTxTypeNotSupported return core.ErrTxTypeNotSupported
} }
// Reject transactions over defined size to prevent DOS attacks // Reject transactions over defined size to prevent DOS attacks
if uint64(tx.Size()) > txMaxSize { if uint64(tx.Size()) > txMaxSize {
@ -607,14 +609,14 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
} }
// Sanity check for extremely large numbers // Sanity check for extremely large numbers
if tx.GasFeeCap().BitLen() > 256 { if tx.GasFeeCap().BitLen() > 256 {
return ErrFeeCapVeryHigh return core.ErrFeeCapVeryHigh
} }
if tx.GasTipCap().BitLen() > 256 { if tx.GasTipCap().BitLen() > 256 {
return ErrTipVeryHigh return core.ErrTipVeryHigh
} }
// Ensure gasFeeCap is greater than or equal to gasTipCap. // Ensure gasFeeCap is greater than or equal to gasTipCap.
if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 { if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 {
return ErrTipAboveFeeCap return core.ErrTipAboveFeeCap
} }
// Make sure the transaction is signed properly. // Make sure the transaction is signed properly.
from, err := types.Sender(pool.signer, tx) from, err := types.Sender(pool.signer, tx)
@ -627,20 +629,20 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
} }
// Ensure the transaction adheres to nonce ordering // Ensure the transaction adheres to nonce ordering
if pool.currentState.GetNonce(from) > tx.Nonce() { if pool.currentState.GetNonce(from) > tx.Nonce() {
return ErrNonceTooLow return core.ErrNonceTooLow
} }
// Transactor should have enough funds to cover the costs // Transactor should have enough funds to cover the costs
// cost == V + GP * GL // cost == V + GP * GL
if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
return ErrInsufficientFunds return core.ErrInsufficientFunds
} }
// Ensure the transaction has more gas than the basic tx fee. // Ensure the transaction has more gas than the basic tx fee.
intrGas, err := IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, pool.istanbul) intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, pool.istanbul)
if err != nil { if err != nil {
return err return err
} }
if tx.Gas() < intrGas { if tx.Gas() < intrGas {
return ErrIntrinsicGas return core.ErrIntrinsicGas
} }
return nil return nil
} }
@ -759,7 +761,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction, local boo
// Try to insert the transaction into the future queue // Try to insert the transaction into the future queue
from, _ := types.Sender(pool.signer, tx) // already validated from, _ := types.Sender(pool.signer, tx) // already validated
if pool.queue[from] == nil { if pool.queue[from] == nil {
pool.queue[from] = newTxList(false) pool.queue[from] = newList(false)
} }
inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump)
if !inserted { if !inserted {
@ -811,7 +813,7 @@ func (pool *TxPool) journalTx(from common.Address, tx *types.Transaction) {
func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) bool { func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) bool {
// Try to insert the transaction into the pending queue // Try to insert the transaction into the pending queue
if pool.pending[addr] == nil { if pool.pending[addr] == nil {
pool.pending[addr] = newTxList(true) pool.pending[addr] = newList(true)
} }
list := pool.pending[addr] list := pool.pending[addr]
@ -1078,7 +1080,7 @@ func (pool *TxPool) scheduleReorgLoop() {
launchNextRun bool launchNextRun bool
reset *txpoolResetRequest reset *txpoolResetRequest
dirtyAccounts *accountSet dirtyAccounts *accountSet
queuedEvents = make(map[common.Address]*txSortedMap) queuedEvents = make(map[common.Address]*sortedMap)
) )
for { for {
// Launch next background reorg if needed // Launch next background reorg if needed
@ -1091,7 +1093,7 @@ func (pool *TxPool) scheduleReorgLoop() {
launchNextRun = false launchNextRun = false
reset, dirtyAccounts = nil, nil reset, dirtyAccounts = nil, nil
queuedEvents = make(map[common.Address]*txSortedMap) queuedEvents = make(map[common.Address]*sortedMap)
} }
select { select {
@ -1120,7 +1122,7 @@ func (pool *TxPool) scheduleReorgLoop() {
// request one later if they want the events sent. // request one later if they want the events sent.
addr, _ := types.Sender(pool.signer, tx) addr, _ := types.Sender(pool.signer, tx)
if _, ok := queuedEvents[addr]; !ok { if _, ok := queuedEvents[addr]; !ok {
queuedEvents[addr] = newTxSortedMap() queuedEvents[addr] = newSortedMap()
} }
queuedEvents[addr].Put(tx) queuedEvents[addr].Put(tx)
@ -1139,7 +1141,7 @@ func (pool *TxPool) scheduleReorgLoop() {
} }
// runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop. // runReorg runs reset and promoteExecutables on behalf of scheduleReorgLoop.
func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*txSortedMap) { func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirtyAccounts *accountSet, events map[common.Address]*sortedMap) {
defer func(t0 time.Time) { defer func(t0 time.Time) {
reorgDurationTimer.Update(time.Since(t0)) reorgDurationTimer.Update(time.Since(t0))
}(time.Now()) }(time.Now())
@ -1202,7 +1204,7 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt
for _, tx := range promoted { for _, tx := range promoted {
addr, _ := types.Sender(pool.signer, tx) addr, _ := types.Sender(pool.signer, tx)
if _, ok := events[addr]; !ok { if _, ok := events[addr]; !ok {
events[addr] = newTxSortedMap() events[addr] = newSortedMap()
} }
events[addr].Put(tx) events[addr].Put(tx)
} }
@ -1211,7 +1213,7 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt
for _, set := range events { for _, set := range events {
txs = append(txs, set.Flatten()...) txs = append(txs, set.Flatten()...)
} }
pool.txFeed.Send(NewTxsEvent{txs}) pool.txFeed.Send(core.NewTxsEvent{Txs: txs})
} }
} }
@ -1238,7 +1240,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
if rem == nil { if rem == nil {
// This can happen if a setHead is performed, where we simply discard the old // This can happen if a setHead is performed, where we simply discard the old
// head from the chain. // head from the chain.
// If that is the case, we don't have the lost transactions any more, and // If that is the case, we don't have the lost transactions anymore, and
// there's nothing to add // there's nothing to add
if newNum >= oldNum { if newNum >= oldNum {
// If we reorged to a same or higher number, then it's not a case of setHead // If we reorged to a same or higher number, then it's not a case of setHead
@ -1291,12 +1293,12 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
return return
} }
pool.currentState = statedb pool.currentState = statedb
pool.pendingNonces = newTxNoncer(statedb) pool.pendingNonces = newNoncer(statedb)
pool.currentMaxGas = newHead.GasLimit pool.currentMaxGas = newHead.GasLimit
// Inject any transactions discarded due to reorgs // Inject any transactions discarded due to reorgs
log.Debug("Reinjecting stale transactions", "count", len(reinject)) log.Debug("Reinjecting stale transactions", "count", len(reinject))
senderCacher.recover(pool.signer, reinject) core.SenderCacher.Recover(pool.signer, reinject)
pool.addTxsLocked(reinject, false) pool.addTxsLocked(reinject, false)
// Update all fork indicator by next pending block number. // Update all fork indicator by next pending block number.
@ -1554,8 +1556,6 @@ func (pool *TxPool) demoteUnexecutables() {
pool.enqueueTx(hash, tx, false, false) pool.enqueueTx(hash, tx, false, false)
} }
pendingGauge.Dec(int64(len(gapped))) pendingGauge.Dec(int64(len(gapped)))
// This might happen in a reorg, so log it to the metering
blockReorgInvalidatedTx.Mark(int64(len(gapped)))
} }
// Delete the entire pending entry if it became empty. // Delete the entire pending entry if it became empty.
if list.Empty() { if list.Empty() {
@ -1646,7 +1646,7 @@ func (as *accountSet) merge(other *accountSet) {
as.cache = nil as.cache = nil
} }
// txLookup is used internally by TxPool to track transactions while allowing // lookup is used internally by TxPool to track transactions while allowing
// lookup without mutex contention. // lookup without mutex contention.
// //
// Note, although this type is properly protected against concurrent access, it // Note, although this type is properly protected against concurrent access, it
@ -1658,16 +1658,16 @@ func (as *accountSet) merge(other *accountSet) {
// //
// This lookup set combines the notion of "local transactions", which is useful // This lookup set combines the notion of "local transactions", which is useful
// to build upper-level structure. // to build upper-level structure.
type txLookup struct { type lookup struct {
slots int slots int
lock sync.RWMutex lock sync.RWMutex
locals map[common.Hash]*types.Transaction locals map[common.Hash]*types.Transaction
remotes map[common.Hash]*types.Transaction remotes map[common.Hash]*types.Transaction
} }
// newTxLookup returns a new txLookup structure. // newLookup returns a new lookup structure.
func newTxLookup() *txLookup { func newLookup() *lookup {
return &txLookup{ return &lookup{
locals: make(map[common.Hash]*types.Transaction), locals: make(map[common.Hash]*types.Transaction),
remotes: make(map[common.Hash]*types.Transaction), remotes: make(map[common.Hash]*types.Transaction),
} }
@ -1676,7 +1676,7 @@ func newTxLookup() *txLookup {
// Range calls f on each key and value present in the map. The callback passed // Range calls f on each key and value present in the map. The callback passed
// should return the indicator whether the iteration needs to be continued. // should return the indicator whether the iteration needs to be continued.
// Callers need to specify which set (or both) to be iterated. // Callers need to specify which set (or both) to be iterated.
func (t *txLookup) Range(f func(hash common.Hash, tx *types.Transaction, local bool) bool, local bool, remote bool) { func (t *lookup) Range(f func(hash common.Hash, tx *types.Transaction, local bool) bool, local bool, remote bool) {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1697,7 +1697,7 @@ func (t *txLookup) Range(f func(hash common.Hash, tx *types.Transaction, local b
} }
// Get returns a transaction if it exists in the lookup, or nil if not found. // Get returns a transaction if it exists in the lookup, or nil if not found.
func (t *txLookup) Get(hash common.Hash) *types.Transaction { func (t *lookup) Get(hash common.Hash) *types.Transaction {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1708,7 +1708,7 @@ func (t *txLookup) Get(hash common.Hash) *types.Transaction {
} }
// GetLocal returns a transaction if it exists in the lookup, or nil if not found. // GetLocal returns a transaction if it exists in the lookup, or nil if not found.
func (t *txLookup) GetLocal(hash common.Hash) *types.Transaction { func (t *lookup) GetLocal(hash common.Hash) *types.Transaction {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1716,7 +1716,7 @@ func (t *txLookup) GetLocal(hash common.Hash) *types.Transaction {
} }
// GetRemote returns a transaction if it exists in the lookup, or nil if not found. // GetRemote returns a transaction if it exists in the lookup, or nil if not found.
func (t *txLookup) GetRemote(hash common.Hash) *types.Transaction { func (t *lookup) GetRemote(hash common.Hash) *types.Transaction {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1724,7 +1724,7 @@ func (t *txLookup) GetRemote(hash common.Hash) *types.Transaction {
} }
// Count returns the current number of transactions in the lookup. // Count returns the current number of transactions in the lookup.
func (t *txLookup) Count() int { func (t *lookup) Count() int {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1732,7 +1732,7 @@ func (t *txLookup) Count() int {
} }
// LocalCount returns the current number of local transactions in the lookup. // LocalCount returns the current number of local transactions in the lookup.
func (t *txLookup) LocalCount() int { func (t *lookup) LocalCount() int {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1740,7 +1740,7 @@ func (t *txLookup) LocalCount() int {
} }
// RemoteCount returns the current number of remote transactions in the lookup. // RemoteCount returns the current number of remote transactions in the lookup.
func (t *txLookup) RemoteCount() int { func (t *lookup) RemoteCount() int {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1748,7 +1748,7 @@ func (t *txLookup) RemoteCount() int {
} }
// Slots returns the current number of slots used in the lookup. // Slots returns the current number of slots used in the lookup.
func (t *txLookup) Slots() int { func (t *lookup) Slots() int {
t.lock.RLock() t.lock.RLock()
defer t.lock.RUnlock() defer t.lock.RUnlock()
@ -1756,7 +1756,7 @@ func (t *txLookup) Slots() int {
} }
// Add adds a transaction to the lookup. // Add adds a transaction to the lookup.
func (t *txLookup) Add(tx *types.Transaction, local bool) { func (t *lookup) Add(tx *types.Transaction, local bool) {
t.lock.Lock() t.lock.Lock()
defer t.lock.Unlock() defer t.lock.Unlock()
@ -1771,7 +1771,7 @@ func (t *txLookup) Add(tx *types.Transaction, local bool) {
} }
// Remove removes a transaction from the lookup. // Remove removes a transaction from the lookup.
func (t *txLookup) Remove(hash common.Hash) { func (t *lookup) Remove(hash common.Hash) {
t.lock.Lock() t.lock.Lock()
defer t.lock.Unlock() defer t.lock.Unlock()
@ -1792,7 +1792,7 @@ func (t *txLookup) Remove(hash common.Hash) {
// RemoteToLocals migrates the transactions belongs to the given locals to locals // RemoteToLocals migrates the transactions belongs to the given locals to locals
// set. The assumption is held the locals set is thread-safe to be used. // set. The assumption is held the locals set is thread-safe to be used.
func (t *txLookup) RemoteToLocals(locals *accountSet) int { func (t *lookup) RemoteToLocals(locals *accountSet) int {
t.lock.Lock() t.lock.Lock()
defer t.lock.Unlock() defer t.lock.Unlock()
@ -1808,7 +1808,7 @@ func (t *txLookup) RemoteToLocals(locals *accountSet) int {
} }
// RemotesBelowTip finds all remote transactions below the given tip threshold. // RemotesBelowTip finds all remote transactions below the given tip threshold.
func (t *txLookup) RemotesBelowTip(threshold *big.Int) types.Transactions { func (t *lookup) RemotesBelowTip(threshold *big.Int) types.Transactions {
found := make(types.Transactions, 0, 128) found := make(types.Transactions, 0, 128)
t.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool { t.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool {
if tx.GasTipCapIntCmp(threshold) < 0 { if tx.GasTipCapIntCmp(threshold) < 0 {

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package txpool
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
@ -28,6 +28,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -40,14 +41,14 @@ import (
var ( var (
// testTxPoolConfig is a transaction pool configuration without stateful disk // testTxPoolConfig is a transaction pool configuration without stateful disk
// sideeffects used during testing. // sideeffects used during testing.
testTxPoolConfig TxPoolConfig testTxPoolConfig Config
// eip1559Config is a chain config with EIP-1559 enabled at block 0. // eip1559Config is a chain config with EIP-1559 enabled at block 0.
eip1559Config *params.ChainConfig eip1559Config *params.ChainConfig
) )
func init() { func init() {
testTxPoolConfig = DefaultTxPoolConfig testTxPoolConfig = DefaultConfig
testTxPoolConfig.Journal = "" testTxPoolConfig.Journal = ""
cpy := *params.TestChainConfig cpy := *params.TestChainConfig
@ -76,7 +77,7 @@ func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
return bc.statedb, nil return bc.statedb, nil
} }
func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return bc.chainHeadFeed.Subscribe(ch) return bc.chainHeadFeed.Subscribe(ch)
} }
@ -112,11 +113,11 @@ func dynamicFeeTx(nonce uint64, gaslimit uint64, gasFee *big.Int, tip *big.Int,
return tx return tx
} }
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { func setupPool() (*TxPool, *ecdsa.PrivateKey) {
return setupTxPoolWithConfig(params.TestChainConfig) return setupPoolWithConfig(params.TestChainConfig)
} }
func setupTxPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) { func setupPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
blockchain := &testBlockChain{10000000, statedb, new(event.Feed)} blockchain := &testBlockChain{10000000, statedb, new(event.Feed)}
@ -128,8 +129,8 @@ func setupTxPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateK
return pool, key return pool, key
} }
// validateTxPoolInternals checks various consistency invariants within the pool. // validatePoolInternals checks various consistency invariants within the pool.
func validateTxPoolInternals(pool *TxPool) error { func validatePoolInternals(pool *TxPool) error {
pool.mu.RLock() pool.mu.RLock()
defer pool.mu.RUnlock() defer pool.mu.RUnlock()
@ -161,7 +162,7 @@ func validateTxPoolInternals(pool *TxPool) error {
// validateEvents checks that the correct number of transaction addition events // validateEvents checks that the correct number of transaction addition events
// were fired on the pool's event feed. // were fired on the pool's event feed.
func validateEvents(events chan NewTxsEvent, count int) error { func validateEvents(events chan core.NewTxsEvent, count int) error {
var received []*types.Transaction var received []*types.Transaction
for len(received) < count { for len(received) < count {
@ -218,7 +219,7 @@ func (c *testChain) State() (*state.StateDB, error) {
// This test simulates a scenario where a new block is imported during a // This test simulates a scenario where a new block is imported during a
// state reset and tests whether the pending state is in sync with the // state reset and tests whether the pending state is in sync with the
// block head event that initiated the resetState(). // block head event that initiated the resetState().
func TestStateChangeDuringTransactionPoolReset(t *testing.T) { func TestStateChangeDuringReset(t *testing.T) {
t.Parallel() t.Parallel()
var ( var (
@ -275,28 +276,28 @@ func testSetNonce(pool *TxPool, addr common.Address, nonce uint64) {
func TestInvalidTransactions(t *testing.T) { func TestInvalidTransactions(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
tx := transaction(0, 100, key) tx := transaction(0, 100, key)
from, _ := deriveSender(tx) from, _ := deriveSender(tx)
testAddBalance(pool, from, big.NewInt(1)) testAddBalance(pool, from, big.NewInt(1))
if err := pool.AddRemote(tx); !errors.Is(err, ErrInsufficientFunds) { if err := pool.AddRemote(tx); !errors.Is(err, core.ErrInsufficientFunds) {
t.Error("expected", ErrInsufficientFunds) t.Error("expected", core.ErrInsufficientFunds)
} }
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()))
testAddBalance(pool, from, balance) testAddBalance(pool, from, balance)
if err := pool.AddRemote(tx); !errors.Is(err, ErrIntrinsicGas) { if err := pool.AddRemote(tx); !errors.Is(err, core.ErrIntrinsicGas) {
t.Error("expected", ErrIntrinsicGas, "got", err) t.Error("expected", core.ErrIntrinsicGas, "got", err)
} }
testSetNonce(pool, from, 1) testSetNonce(pool, from, 1)
testAddBalance(pool, from, big.NewInt(0xffffffffffffff)) testAddBalance(pool, from, big.NewInt(0xffffffffffffff))
tx = transaction(0, 100000, key) tx = transaction(0, 100000, key)
if err := pool.AddRemote(tx); !errors.Is(err, ErrNonceTooLow) { if err := pool.AddRemote(tx); !errors.Is(err, core.ErrNonceTooLow) {
t.Error("expected", ErrNonceTooLow) t.Error("expected", core.ErrNonceTooLow)
} }
tx = transaction(1, 100000, key) tx = transaction(1, 100000, key)
@ -309,10 +310,10 @@ func TestInvalidTransactions(t *testing.T) {
} }
} }
func TestTransactionQueue(t *testing.T) { func TestQueue(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
tx := transaction(0, 100, key) tx := transaction(0, 100, key)
@ -340,10 +341,10 @@ func TestTransactionQueue(t *testing.T) {
} }
} }
func TestTransactionQueue2(t *testing.T) { func TestQueue2(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
tx1 := transaction(0, 100, key) tx1 := transaction(0, 100, key)
@ -366,10 +367,10 @@ func TestTransactionQueue2(t *testing.T) {
} }
} }
func TestTransactionNegativeValue(t *testing.T) { func TestNegativeValue(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key)
@ -380,43 +381,43 @@ func TestTransactionNegativeValue(t *testing.T) {
} }
} }
func TestTransactionTipAboveFeeCap(t *testing.T) { func TestTipAboveFeeCap(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPoolWithConfig(eip1559Config) pool, key := setupPoolWithConfig(eip1559Config)
defer pool.Stop() defer pool.Stop()
tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key) tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key)
if err := pool.AddRemote(tx); err != ErrTipAboveFeeCap { if err := pool.AddRemote(tx); err != core.ErrTipAboveFeeCap {
t.Error("expected", ErrTipAboveFeeCap, "got", err) t.Error("expected", core.ErrTipAboveFeeCap, "got", err)
} }
} }
func TestTransactionVeryHighValues(t *testing.T) { func TestVeryHighValues(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPoolWithConfig(eip1559Config) pool, key := setupPoolWithConfig(eip1559Config)
defer pool.Stop() defer pool.Stop()
veryBigNumber := big.NewInt(1) veryBigNumber := big.NewInt(1)
veryBigNumber.Lsh(veryBigNumber, 300) veryBigNumber.Lsh(veryBigNumber, 300)
tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key) tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key)
if err := pool.AddRemote(tx); err != ErrTipVeryHigh { if err := pool.AddRemote(tx); err != core.ErrTipVeryHigh {
t.Error("expected", ErrTipVeryHigh, "got", err) t.Error("expected", core.ErrTipVeryHigh, "got", err)
} }
tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key) tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key)
if err := pool.AddRemote(tx2); err != ErrFeeCapVeryHigh { if err := pool.AddRemote(tx2); err != core.ErrFeeCapVeryHigh {
t.Error("expected", ErrFeeCapVeryHigh, "got", err) t.Error("expected", core.ErrFeeCapVeryHigh, "got", err)
} }
} }
func TestTransactionChainFork(t *testing.T) { func TestChainFork(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
@ -442,10 +443,10 @@ func TestTransactionChainFork(t *testing.T) {
} }
} }
func TestTransactionDoubleNonce(t *testing.T) { func TestDoubleNonce(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
@ -493,10 +494,10 @@ func TestTransactionDoubleNonce(t *testing.T) {
} }
} }
func TestTransactionMissingNonce(t *testing.T) { func TestMissingNonce(t *testing.T) {
t.Parallel() t.Parallel()
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
@ -516,11 +517,11 @@ func TestTransactionMissingNonce(t *testing.T) {
} }
} }
func TestTransactionNonceRecovery(t *testing.T) { func TestNonceRecovery(t *testing.T) {
t.Parallel() t.Parallel()
const n = 10 const n = 10
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
addr := crypto.PubkeyToAddress(key.PublicKey) addr := crypto.PubkeyToAddress(key.PublicKey)
@ -542,11 +543,11 @@ func TestTransactionNonceRecovery(t *testing.T) {
// Tests that if an account runs out of funds, any pending and queued transactions // Tests that if an account runs out of funds, any pending and queued transactions
// are dropped. // are dropped.
func TestTransactionDropping(t *testing.T) { func TestDropping(t *testing.T) {
t.Parallel() t.Parallel()
// Create a test account and fund it // Create a test account and fund it
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
@ -646,7 +647,7 @@ func TestTransactionDropping(t *testing.T) {
// Tests that if a transaction is dropped from the current pending pool (e.g. out // Tests that if a transaction is dropped from the current pending pool (e.g. out
// of fund), all consecutive (still valid, but not executable) transactions are // of fund), all consecutive (still valid, but not executable) transactions are
// postponed back into the future queue to prevent broadcasting them. // postponed back into the future queue to prevent broadcasting them.
func TestTransactionPostponing(t *testing.T) { func TestPostponing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the postponing with // Create the pool to test the postponing with
@ -759,18 +760,18 @@ func TestTransactionPostponing(t *testing.T) {
// Tests that if the transaction pool has both executable and non-executable // Tests that if the transaction pool has both executable and non-executable
// transactions from an origin account, filling the nonce gap moves all queued // transactions from an origin account, filling the nonce gap moves all queued
// ones into the pending pool. // ones into the pending pool.
func TestTransactionGapFilling(t *testing.T) { func TestGapFilling(t *testing.T) {
t.Parallel() t.Parallel()
// Create a test account and fund it // Create a test account and fund it
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
testAddBalance(pool, account, big.NewInt(1000000)) testAddBalance(pool, account, big.NewInt(1000000))
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5) events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -789,7 +790,7 @@ func TestTransactionGapFilling(t *testing.T) {
if err := validateEvents(events, 1); err != nil { if err := validateEvents(events, 1); err != nil {
t.Fatalf("original event firing failed: %v", err) t.Fatalf("original event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Fill the nonce gap and ensure all transactions become pending // Fill the nonce gap and ensure all transactions become pending
@ -806,18 +807,18 @@ func TestTransactionGapFilling(t *testing.T) {
if err := validateEvents(events, 2); err != nil { if err := validateEvents(events, 2); err != nil {
t.Fatalf("gap-filling event firing failed: %v", err) t.Fatalf("gap-filling event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
// Tests that if the transaction count belonging to a single account goes above // Tests that if the transaction count belonging to a single account goes above
// some threshold, the higher transactions are dropped to prevent DOS attacks. // some threshold, the higher transactions are dropped to prevent DOS attacks.
func TestTransactionQueueAccountLimiting(t *testing.T) { func TestQueueAccountLimiting(t *testing.T) {
t.Parallel() t.Parallel()
// Create a test account and fund it // Create a test account and fund it
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
@ -851,14 +852,14 @@ func TestTransactionQueueAccountLimiting(t *testing.T) {
// //
// This logic should not hold for local transactions, unless the local tracking // This logic should not hold for local transactions, unless the local tracking
// mechanism is disabled. // mechanism is disabled.
func TestTransactionQueueGlobalLimiting(t *testing.T) { func TestQueueGlobalLimiting(t *testing.T) {
testTransactionQueueGlobalLimiting(t, false) testQueueGlobalLimiting(t, false)
} }
func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { func TestQueueGlobalLimitingNoLocals(t *testing.T) {
testTransactionQueueGlobalLimiting(t, true) testQueueGlobalLimiting(t, true)
} }
func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
@ -941,14 +942,14 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
// //
// This logic should not hold for local transactions, unless the local tracking // This logic should not hold for local transactions, unless the local tracking
// mechanism is disabled. // mechanism is disabled.
func TestTransactionQueueTimeLimiting(t *testing.T) { func TestQueueTimeLimiting(t *testing.T) {
testTransactionQueueTimeLimiting(t, false) testQueueTimeLimiting(t, false)
} }
func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { func TestQueueTimeLimitingNoLocals(t *testing.T) {
testTransactionQueueTimeLimiting(t, true) testQueueTimeLimiting(t, true)
} }
func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { func testQueueTimeLimiting(t *testing.T, nolocals bool) {
// Reduce the eviction interval to a testable amount // Reduce the eviction interval to a testable amount
defer func(old time.Duration) { evictionInterval = old }(evictionInterval) defer func(old time.Duration) { evictionInterval = old }(evictionInterval)
evictionInterval = time.Millisecond * 100 evictionInterval = time.Millisecond * 100
@ -985,7 +986,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
if queued != 2 { if queued != 2 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
@ -1000,7 +1001,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
if queued != 2 { if queued != 2 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
@ -1020,7 +1021,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
} }
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
@ -1037,7 +1038,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
if queued != 0 { if queued != 0 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
@ -1067,7 +1068,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
if queued != 2 { if queued != 2 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
@ -1086,7 +1087,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
} }
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1094,18 +1095,18 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
// Tests that even if the transaction count belonging to a single account goes // Tests that even if the transaction count belonging to a single account goes
// above some threshold, as long as the transactions are executable, they are // above some threshold, as long as the transactions are executable, they are
// accepted. // accepted.
func TestTransactionPendingLimiting(t *testing.T) { func TestPendingLimiting(t *testing.T) {
t.Parallel() t.Parallel()
// Create a test account and fund it // Create a test account and fund it
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
testAddBalance(pool, account, big.NewInt(1000000)) testAddBalance(pool, account, big.NewInt(1000000))
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5) events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -1127,7 +1128,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil { if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil {
t.Fatalf("event firing failed: %v", err) t.Fatalf("event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1135,7 +1136,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
// Tests that if the transaction count belonging to multiple accounts go above // Tests that if the transaction count belonging to multiple accounts go above
// some hard threshold, the higher transactions are dropped to prevent DOS // some hard threshold, the higher transactions are dropped to prevent DOS
// attacks. // attacks.
func TestTransactionPendingGlobalLimiting(t *testing.T) { func TestPendingGlobalLimiting(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
@ -1175,7 +1176,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
if pending > int(config.GlobalSlots) { if pending > int(config.GlobalSlots) {
t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1183,11 +1184,11 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
// Test the limit on transaction size is enforced correctly. // Test the limit on transaction size is enforced correctly.
// This test verifies every transaction having allowed size // This test verifies every transaction having allowed size
// is added to the pool, and longer transactions are rejected. // is added to the pool, and longer transactions are rejected.
func TestTransactionAllowedTxSize(t *testing.T) { func TestAllowedTxSize(t *testing.T) {
t.Parallel() t.Parallel()
// Create a test account and fund it // Create a test account and fund it
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
@ -1231,13 +1232,13 @@ func TestTransactionAllowedTxSize(t *testing.T) {
if queued != 0 { if queued != 0 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
// Tests that if transactions start being capped, transactions are also removed from 'all' // Tests that if transactions start being capped, transactions are also removed from 'all'
func TestTransactionCapClearsFromAll(t *testing.T) { func TestCapClearsFromAll(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
@ -1263,7 +1264,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
} }
// Import the batch and verify that limits have been enforced // Import the batch and verify that limits have been enforced
pool.AddRemotes(txs) pool.AddRemotes(txs)
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1271,7 +1272,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) {
// Tests that if the transaction count belonging to multiple accounts go above // Tests that if the transaction count belonging to multiple accounts go above
// some hard threshold, if they are under the minimum guaranteed slot count then // some hard threshold, if they are under the minimum guaranteed slot count then
// the transactions are still kept. // the transactions are still kept.
func TestTransactionPendingMinimumAllowance(t *testing.T) { func TestPendingMinimumAllowance(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the limit enforcement with // Create the pool to test the limit enforcement with
@ -1309,7 +1310,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots)
} }
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1319,7 +1320,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
// from the pending pool to the queue. // from the pending pool to the queue.
// //
// Note, local transactions are never allowed to be dropped. // Note, local transactions are never allowed to be dropped.
func TestTransactionPoolRepricing(t *testing.T) { func TestRepricing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
@ -1330,7 +1331,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
defer pool.Stop() defer pool.Stop()
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, 32) events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -1371,7 +1372,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 7); err != nil { if err := validateEvents(events, 7); err != nil {
t.Fatalf("original event firing failed: %v", err) t.Fatalf("original event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Reprice the pool and check that underpriced transactions get dropped // Reprice the pool and check that underpriced transactions get dropped
@ -1387,7 +1388,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 0); err != nil { if err := validateEvents(events, 0); err != nil {
t.Fatalf("reprice event firing failed: %v", err) t.Fatalf("reprice event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Check that we can't add the old transactions back // Check that we can't add the old transactions back
@ -1403,7 +1404,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 0); err != nil { if err := validateEvents(events, 0); err != nil {
t.Fatalf("post-reprice event firing failed: %v", err) t.Fatalf("post-reprice event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// However we can add local underpriced transactions // However we can add local underpriced transactions
@ -1417,7 +1418,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 1); err != nil { if err := validateEvents(events, 1); err != nil {
t.Fatalf("post-reprice local event firing failed: %v", err) t.Fatalf("post-reprice local event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// And we can fill gaps with properly priced transactions // And we can fill gaps with properly priced transactions
@ -1433,7 +1434,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 5); err != nil { if err := validateEvents(events, 5); err != nil {
t.Fatalf("post-reprice event firing failed: %v", err) t.Fatalf("post-reprice event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1443,15 +1444,15 @@ func TestTransactionPoolRepricing(t *testing.T) {
// gapped transactions back from the pending pool to the queue. // gapped transactions back from the pending pool to the queue.
// //
// Note, local transactions are never allowed to be dropped. // Note, local transactions are never allowed to be dropped.
func TestTransactionPoolRepricingDynamicFee(t *testing.T) { func TestRepricingDynamicFee(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
pool, _ := setupTxPoolWithConfig(eip1559Config) pool, _ := setupPoolWithConfig(eip1559Config)
defer pool.Stop() defer pool.Stop()
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, 32) events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -1492,7 +1493,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 7); err != nil { if err := validateEvents(events, 7); err != nil {
t.Fatalf("original event firing failed: %v", err) t.Fatalf("original event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Reprice the pool and check that underpriced transactions get dropped // Reprice the pool and check that underpriced transactions get dropped
@ -1508,7 +1509,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 0); err != nil { if err := validateEvents(events, 0); err != nil {
t.Fatalf("reprice event firing failed: %v", err) t.Fatalf("reprice event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Check that we can't add the old transactions back // Check that we can't add the old transactions back
@ -1527,7 +1528,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 0); err != nil { if err := validateEvents(events, 0); err != nil {
t.Fatalf("post-reprice event firing failed: %v", err) t.Fatalf("post-reprice event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// However we can add local underpriced transactions // However we can add local underpriced transactions
@ -1541,7 +1542,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 1); err != nil { if err := validateEvents(events, 1); err != nil {
t.Fatalf("post-reprice local event firing failed: %v", err) t.Fatalf("post-reprice local event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// And we can fill gaps with properly priced transactions // And we can fill gaps with properly priced transactions
@ -1560,14 +1561,14 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 5); err != nil { if err := validateEvents(events, 5); err != nil {
t.Fatalf("post-reprice event firing failed: %v", err) t.Fatalf("post-reprice event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
// Tests that setting the transaction pool gas price to a higher value does not // Tests that setting the transaction pool gas price to a higher value does not
// remove local transactions (legacy & dynamic fee). // remove local transactions (legacy & dynamic fee).
func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { func TestRepricingKeepsLocals(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
@ -1618,7 +1619,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1640,7 +1641,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
// pending transactions are moved into the queue. // pending transactions are moved into the queue.
// //
// Note, local transactions are never allowed to be dropped. // Note, local transactions are never allowed to be dropped.
func TestTransactionPoolUnderpricing(t *testing.T) { func TestUnderpricing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
@ -1655,7 +1656,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
defer pool.Stop() defer pool.Stop()
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, 32) events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -1689,7 +1690,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := validateEvents(events, 3); err != nil { if err := validateEvents(events, 3); err != nil {
t.Fatalf("original event firing failed: %v", err) t.Fatalf("original event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Ensure that adding an underpriced transaction on block limit fails // Ensure that adding an underpriced transaction on block limit fails
@ -1716,7 +1717,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := validateEvents(events, 1); err != nil { if err := validateEvents(events, 1); err != nil {
t.Fatalf("additional event firing failed: %v", err) t.Fatalf("additional event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Ensure that adding local transactions can push out even higher priced ones // Ensure that adding local transactions can push out even higher priced ones
@ -1738,7 +1739,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := validateEvents(events, 2); err != nil { if err := validateEvents(events, 2); err != nil {
t.Fatalf("local event firing failed: %v", err) t.Fatalf("local event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1746,7 +1747,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
// Tests that more expensive transactions push out cheap ones from the pool, but // Tests that more expensive transactions push out cheap ones from the pool, but
// without producing instability by creating gaps that start jumping transactions // without producing instability by creating gaps that start jumping transactions
// back and forth between queued/pending. // back and forth between queued/pending.
func TestTransactionPoolStableUnderpricing(t *testing.T) { func TestStableUnderpricing(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
@ -1761,7 +1762,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
defer pool.Stop() defer pool.Stop()
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, 32) events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -1788,7 +1789,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
if err := validateEvents(events, int(config.GlobalSlots)); err != nil { if err := validateEvents(events, int(config.GlobalSlots)); err != nil {
t.Fatalf("original event firing failed: %v", err) t.Fatalf("original event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap // Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap
@ -1805,7 +1806,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
if err := validateEvents(events, 1); err != nil { if err := validateEvents(events, 1); err != nil {
t.Fatalf("additional event firing failed: %v", err) t.Fatalf("additional event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1815,17 +1816,17 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
// expensive ones and any gapped pending transactions are moved into the queue. // expensive ones and any gapped pending transactions are moved into the queue.
// //
// Note, local transactions are never allowed to be dropped. // Note, local transactions are never allowed to be dropped.
func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) { func TestUnderpricingDynamicFee(t *testing.T) {
t.Parallel() t.Parallel()
pool, _ := setupTxPoolWithConfig(eip1559Config) pool, _ := setupPoolWithConfig(eip1559Config)
defer pool.Stop() defer pool.Stop()
pool.config.GlobalSlots = 2 pool.config.GlobalSlots = 2
pool.config.GlobalQueue = 2 pool.config.GlobalQueue = 2
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, 32) events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -1859,7 +1860,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 3); err != nil { if err := validateEvents(events, 3); err != nil {
t.Fatalf("original event firing failed: %v", err) t.Fatalf("original event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
@ -1893,7 +1894,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 1); err != nil { if err := validateEvents(events, 1); err != nil {
t.Fatalf("additional event firing failed: %v", err) t.Fatalf("additional event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Ensure that adding local transactions can push out even higher priced ones // Ensure that adding local transactions can push out even higher priced ones
@ -1915,7 +1916,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
if err := validateEvents(events, 2); err != nil { if err := validateEvents(events, 2); err != nil {
t.Fatalf("local event firing failed: %v", err) t.Fatalf("local event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
@ -1925,7 +1926,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) {
func TestDualHeapEviction(t *testing.T) { func TestDualHeapEviction(t *testing.T) {
t.Parallel() t.Parallel()
pool, _ := setupTxPoolWithConfig(eip1559Config) pool, _ := setupPoolWithConfig(eip1559Config)
defer pool.Stop() defer pool.Stop()
pool.config.GlobalSlots = 10 pool.config.GlobalSlots = 10
@ -1972,13 +1973,13 @@ func TestDualHeapEviction(t *testing.T) {
check(highTip, "effective tip") check(highTip, "effective tip")
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
// Tests that the pool rejects duplicate transactions. // Tests that the pool rejects duplicate transactions.
func TestTransactionDeduplication(t *testing.T) { func TestDeduplication(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
@ -2037,14 +2038,14 @@ func TestTransactionDeduplication(t *testing.T) {
if queued != 0 { if queued != 0 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
// Tests that the pool rejects replacement transactions that don't meet the minimum // Tests that the pool rejects replacement transactions that don't meet the minimum
// price bump required. // price bump required.
func TestTransactionReplacement(t *testing.T) { func TestReplacement(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
@ -2055,7 +2056,7 @@ func TestTransactionReplacement(t *testing.T) {
defer pool.Stop() defer pool.Stop()
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, 32) events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -2117,23 +2118,23 @@ func TestTransactionReplacement(t *testing.T) {
if err := validateEvents(events, 0); err != nil { if err := validateEvents(events, 0); err != nil {
t.Fatalf("queued replacement event firing failed: %v", err) t.Fatalf("queued replacement event firing failed: %v", err)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
// Tests that the pool rejects replacement dynamic fee transactions that don't // Tests that the pool rejects replacement dynamic fee transactions that don't
// meet the minimum price bump required. // meet the minimum price bump required.
func TestTransactionReplacementDynamicFee(t *testing.T) { func TestReplacementDynamicFee(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the pricing enforcement with // Create the pool to test the pricing enforcement with
pool, key := setupTxPoolWithConfig(eip1559Config) pool, key := setupPoolWithConfig(eip1559Config)
defer pool.Stop() defer pool.Stop()
testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000))
// Keep track of transaction events to ensure all executables get announced // Keep track of transaction events to ensure all executables get announced
events := make(chan NewTxsEvent, 32) events := make(chan core.NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events) sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe() defer sub.Unsubscribe()
@ -2227,17 +2228,17 @@ func TestTransactionReplacementDynamicFee(t *testing.T) {
} }
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
} }
// Tests that local transactions are journaled to disk, but remote transactions // Tests that local transactions are journaled to disk, but remote transactions
// get discarded between restarts. // get discarded between restarts.
func TestTransactionJournaling(t *testing.T) { testTransactionJournaling(t, false) } func TestJournaling(t *testing.T) { testJournaling(t, false) }
func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) } func TestJournalingNoLocals(t *testing.T) { testJournaling(t, true) }
func testTransactionJournaling(t *testing.T, nolocals bool) { func testJournaling(t *testing.T, nolocals bool) {
t.Parallel() t.Parallel()
// Create a temporary file for the journal // Create a temporary file for the journal
@ -2290,7 +2291,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
if queued != 0 { if queued != 0 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive
@ -2313,7 +2314,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
} }
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Bump the nonce temporarily and ensure the newly invalidated transaction is removed // Bump the nonce temporarily and ensure the newly invalidated transaction is removed
@ -2339,15 +2340,15 @@ func testTransactionJournaling(t *testing.T, nolocals bool) {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
} }
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
pool.Stop() pool.Stop()
} }
// TestTransactionStatusCheck tests that the pool can correctly retrieve the // TestStatusCheck tests that the pool can correctly retrieve the
// pending status of individual transactions. // pending status of individual transactions.
func TestTransactionStatusCheck(t *testing.T) { func TestStatusCheck(t *testing.T) {
t.Parallel() t.Parallel()
// Create the pool to test the status retrievals with // Create the pool to test the status retrievals with
@ -2381,7 +2382,7 @@ func TestTransactionStatusCheck(t *testing.T) {
if queued != 2 { if queued != 2 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
} }
if err := validateTxPoolInternals(pool); err != nil { if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err) t.Fatalf("pool internal state corrupted: %v", err)
} }
// Retrieve the status of each transaction and validate them // Retrieve the status of each transaction and validate them
@ -2402,7 +2403,7 @@ func TestTransactionStatusCheck(t *testing.T) {
} }
// Test the transaction slots consumption is computed correctly // Test the transaction slots consumption is computed correctly
func TestTransactionSlotCount(t *testing.T) { func TestSlotCount(t *testing.T) {
t.Parallel() t.Parallel()
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
@ -2427,7 +2428,7 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1
func benchmarkPendingDemotion(b *testing.B, size int) { func benchmarkPendingDemotion(b *testing.B, size int) {
// Add a batch of transactions to a pool one by one // Add a batch of transactions to a pool one by one
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
@ -2452,7 +2453,7 @@ func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 1
func benchmarkFuturePromotion(b *testing.B, size int) { func benchmarkFuturePromotion(b *testing.B, size int) {
// Add a batch of transactions to a pool one by one // Add a batch of transactions to a pool one by one
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
@ -2470,17 +2471,17 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
} }
// Benchmarks the speed of batched transaction insertion. // Benchmarks the speed of batched transaction insertion.
func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100, false) } func BenchmarkBatchInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, false) }
func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000, false) } func BenchmarkBatchInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, false) }
func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000, false) } func BenchmarkBatchInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, false) }
func BenchmarkPoolBatchLocalInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100, true) } func BenchmarkBatchLocalInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, true) }
func BenchmarkPoolBatchLocalInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000, true) } func BenchmarkBatchLocalInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, true) }
func BenchmarkPoolBatchLocalInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000, true) } func BenchmarkBatchLocalInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, true) }
func benchmarkPoolBatchInsert(b *testing.B, size int, local bool) { func benchmarkBatchInsert(b *testing.B, size int, local bool) {
// Generate a batch of transactions to enqueue into the pool // Generate a batch of transactions to enqueue into the pool
pool, key := setupTxPool() pool, key := setupPool()
defer pool.Stop() defer pool.Stop()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
@ -2524,7 +2525,7 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
b.StopTimer() b.StopTimer()
pool, _ := setupTxPool() pool, _ := setupPool()
testAddBalance(pool, account, big.NewInt(100000000)) testAddBalance(pool, account, big.NewInt(100000000))
for _, local := range locals { for _, local := range locals {
pool.AddLocal(local) pool.AddLocal(local)
@ -2540,9 +2541,9 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) {
} }
// Benchmarks the speed of batch transaction insertion in case of multiple accounts. // Benchmarks the speed of batch transaction insertion in case of multiple accounts.
func BenchmarkPoolMultiAccountBatchInsert(b *testing.B) { func BenchmarkMultiAccountBatchInsert(b *testing.B) {
// Generate a batch of transactions to enqueue into the pool // Generate a batch of transactions to enqueue into the pool
pool, _ := setupTxPool() pool, _ := setupPool()
defer pool.Stop() defer pool.Stop()
b.ReportAllocs() b.ReportAllocs()
batches := make(types.Transactions, b.N) batches := make(types.Transactions, b.N)

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
@ -284,7 +285,7 @@ func (b *EthAPIBackend) TxPoolContentFrom(addr common.Address) (types.Transactio
return b.eth.TxPool().ContentFrom(addr) return b.eth.TxPool().ContentFrom(addr)
} }
func (b *EthAPIBackend) TxPool() *core.TxPool { func (b *EthAPIBackend) TxPool() *txpool.TxPool {
return b.eth.TxPool() return b.eth.TxPool()
} }

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/pruner" "github.com/ethereum/go-ethereum/core/state/pruner"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
@ -66,7 +67,7 @@ type Ethereum struct {
config *ethconfig.Config config *ethconfig.Config
// Handlers // Handlers
txPool *core.TxPool txPool *txpool.TxPool
blockchain *core.BlockChain blockchain *core.BlockChain
handler *handler handler *handler
ethDialCandidates enode.Iterator ethDialCandidates enode.Iterator
@ -209,7 +210,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.TxPool.Journal != "" { if config.TxPool.Journal != "" {
config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal)
} }
eth.txPool = core.NewTxPool(config.TxPool, eth.blockchain.Config(), eth.blockchain) eth.txPool = txpool.NewTxPool(config.TxPool, eth.blockchain.Config(), eth.blockchain)
// Permit the downloader to use the trie cache allowance during fast sync // Permit the downloader to use the trie cache allowance during fast sync
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
@ -482,7 +483,7 @@ func (s *Ethereum) Miner() *miner.Miner { return s.miner }
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) Engine() consensus.Engine { return s.engine }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/clique"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@ -85,7 +86,7 @@ var Defaults = Config{
SnapshotCache: 102, SnapshotCache: 102,
FilterLogCacheSize: 32, FilterLogCacheSize: 32,
Miner: miner.DefaultConfig, Miner: miner.DefaultConfig,
TxPool: core.DefaultTxPoolConfig, TxPool: txpool.DefaultConfig,
RPCGasCap: 50000000, RPCGasCap: 50000000,
RPCEVMTimeout: 5 * time.Second, RPCEVMTimeout: 5 * time.Second,
GPO: FullNodeGPO, GPO: FullNodeGPO,
@ -178,7 +179,7 @@ type Config struct {
Ethash ethash.Config Ethash ethash.Config
// Transaction pool options // Transaction pool options
TxPool core.TxPoolConfig TxPool txpool.Config
// Gas Price Oracle options // Gas Price Oracle options
GPO gasprice.Config GPO gasprice.Config

@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
@ -51,7 +52,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
FilterLogCacheSize int FilterLogCacheSize int
Miner miner.Config Miner miner.Config
Ethash ethash.Config Ethash ethash.Config
TxPool core.TxPoolConfig TxPool txpool.Config
GPO gasprice.Config GPO gasprice.Config
EnablePreimageRecording bool EnablePreimageRecording bool
DocRoot string `toml:"-"` DocRoot string `toml:"-"`
@ -147,7 +148,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
FilterLogCacheSize *int FilterLogCacheSize *int
Miner *miner.Config Miner *miner.Config
Ethash *ethash.Config Ethash *ethash.Config
TxPool *core.TxPoolConfig TxPool *txpool.Config
GPO *gasprice.Config GPO *gasprice.Config
EnablePreimageRecording *bool EnablePreimageRecording *bool
DocRoot *string `toml:"-"` DocRoot *string `toml:"-"`

@ -27,7 +27,7 @@ import (
mapset "github.com/deckarep/golang-set" mapset "github.com/deckarep/golang-set"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
@ -298,7 +298,7 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
// Track the transaction hash if the price is too low for us. // Track the transaction hash if the price is too low for us.
// Avoid re-request this transaction when we receive another // Avoid re-request this transaction when we receive another
// announcement. // announcement.
if errors.Is(err, core.ErrUnderpriced) || errors.Is(err, core.ErrReplaceUnderpriced) { if errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced) {
for f.underpriced.Cardinality() >= maxTxUnderpricedSetSize { for f.underpriced.Cardinality() >= maxTxUnderpricedSetSize {
f.underpriced.Pop() f.underpriced.Pop()
} }
@ -308,10 +308,10 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
switch { switch {
case err == nil: // Noop, but need to handle to not count these case err == nil: // Noop, but need to handle to not count these
case errors.Is(err, core.ErrAlreadyKnown): case errors.Is(err, txpool.ErrAlreadyKnown):
duplicate++ duplicate++
case errors.Is(err, core.ErrUnderpriced) || errors.Is(err, core.ErrReplaceUnderpriced): case errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced):
underpriced++ underpriced++
default: default:

@ -25,7 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
@ -869,9 +869,9 @@ func TestTransactionFetcherUnderpricedDedup(t *testing.T) {
errs := make([]error, len(txs)) errs := make([]error, len(txs))
for i := 0; i < len(errs); i++ { for i := 0; i < len(errs); i++ {
if i%2 == 0 { if i%2 == 0 {
errs[i] = core.ErrUnderpriced errs[i] = txpool.ErrUnderpriced
} else { } else {
errs[i] = core.ErrReplaceUnderpriced errs[i] = txpool.ErrReplaceUnderpriced
} }
} }
return errs return errs
@ -941,7 +941,7 @@ func TestTransactionFetcherUnderpricedDoSProtection(t *testing.T) {
func(txs []*types.Transaction) []error { func(txs []*types.Transaction) []error {
errs := make([]error, len(txs)) errs := make([]error, len(txs))
for i := 0; i < len(errs); i++ { for i := 0; i < len(errs); i++ {
errs[i] = core.ErrUnderpriced errs[i] = txpool.ErrUnderpriced
} }
return errs return errs
}, },

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@ -50,7 +51,7 @@ var (
type testBackend struct { type testBackend struct {
db ethdb.Database db ethdb.Database
chain *core.BlockChain chain *core.BlockChain
txpool *core.TxPool txpool *txpool.TxPool
} }
// newTestBackend creates an empty chain and wraps it into a mock backend. // newTestBackend creates an empty chain and wraps it into a mock backend.
@ -76,13 +77,13 @@ func newTestBackendWithGenerator(blocks int, generator func(int, *core.BlockGen)
for _, block := range bs { for _, block := range bs {
chain.StateCache().TrieDB().Commit(block.Root(), false, nil) chain.StateCache().TrieDB().Commit(block.Root(), false, nil)
} }
txconfig := core.DefaultTxPoolConfig txconfig := txpool.DefaultConfig
txconfig.Journal = "" // Don't litter the disk with test journals txconfig.Journal = "" // Don't litter the disk with test journals
return &testBackend{ return &testBackend{
db: db, db: db,
chain: chain, chain: chain,
txpool: core.NewTxPool(txconfig, params.TestChainConfig, chain), txpool: txpool.NewTxPool(txconfig, params.TestChainConfig, chain),
} }
} }

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/les/downloader" "github.com/ethereum/go-ethereum/les/downloader"
@ -624,20 +625,20 @@ func testTransactionStatus(t *testing.T, protocol int) {
// test error status by sending an underpriced transaction // test error status by sending an underpriced transaction
tx0, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, nil, nil), signer, bankKey) tx0, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, nil, nil), signer, bankKey)
test(tx0, true, light.TxStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced.Error()}) test(tx0, true, light.TxStatus{Status: txpool.TxStatusUnknown, Error: txpool.ErrUnderpriced.Error()})
tx1, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, bankKey) tx1, _ := types.SignTx(types.NewTransaction(0, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, bankKey)
test(tx1, false, light.TxStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown test(tx1, false, light.TxStatus{Status: txpool.TxStatusUnknown}) // query before sending, should be unknown
test(tx1, true, light.TxStatus{Status: core.TxStatusPending}) // send valid processable tx, should return pending test(tx1, true, light.TxStatus{Status: txpool.TxStatusPending}) // send valid processable tx, should return pending
test(tx1, true, light.TxStatus{Status: core.TxStatusPending}) // adding it again should not return an error test(tx1, true, light.TxStatus{Status: txpool.TxStatusPending}) // adding it again should not return an error
tx2, _ := types.SignTx(types.NewTransaction(1, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, bankKey) tx2, _ := types.SignTx(types.NewTransaction(1, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, bankKey)
tx3, _ := types.SignTx(types.NewTransaction(2, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, bankKey) tx3, _ := types.SignTx(types.NewTransaction(2, userAddr1, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, bankKey)
// send transactions in the wrong order, tx3 should be queued // send transactions in the wrong order, tx3 should be queued
test(tx3, true, light.TxStatus{Status: core.TxStatusQueued}) test(tx3, true, light.TxStatus{Status: txpool.TxStatusQueued})
test(tx2, true, light.TxStatus{Status: core.TxStatusPending}) test(tx2, true, light.TxStatus{Status: txpool.TxStatusPending})
// query again, now tx3 should be pending too // query again, now tx3 should be pending too
test(tx3, false, light.TxStatus{Status: core.TxStatusPending}) test(tx3, false, light.TxStatus{Status: txpool.TxStatusPending})
// generate and add a block with tx1 and tx2 included // generate and add a block with tx1 and tx2 included
gchain, _ := core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), server.db, 1, func(i int, block *core.BlockGen) { gchain, _ := core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), server.db, 1, func(i int, block *core.BlockGen) {
@ -663,9 +664,9 @@ func testTransactionStatus(t *testing.T, protocol int) {
// check if their status is included now // check if their status is included now
block1hash := rawdb.ReadCanonicalHash(server.db, 1) block1hash := rawdb.ReadCanonicalHash(server.db, 1)
test(tx1, false, light.TxStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.LegacyTxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}}) test(tx1, false, light.TxStatus{Status: txpool.TxStatusIncluded, Lookup: &rawdb.LegacyTxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}})
test(tx2, false, light.TxStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.LegacyTxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}}) test(tx2, false, light.TxStatus{Status: txpool.TxStatusIncluded, Lookup: &rawdb.LegacyTxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}})
// create a reorg that rolls them back // create a reorg that rolls them back
gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), server.db, 2, func(i int, block *core.BlockGen) {}) gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), server.db, 2, func(i int, block *core.BlockGen) {})
@ -687,8 +688,8 @@ func testTransactionStatus(t *testing.T, protocol int) {
msg.Discard() msg.Discard()
// check if their status is pending again // check if their status is pending again
test(tx1, false, light.TxStatus{Status: core.TxStatusPending}) test(tx1, false, light.TxStatus{Status: txpool.TxStatusPending})
test(tx2, false, light.TxStatus{Status: core.TxStatusPending}) test(tx2, false, light.TxStatus{Status: txpool.TxStatusPending})
} }
func TestStopResumeLES3(t *testing.T) { testStopResume(t, lpv3) } func TestStopResumeLES3(t *testing.T) { testStopResume(t, lpv3) }

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
) )
@ -176,10 +177,10 @@ func (odr *LesOdr) RetrieveTxStatus(ctx context.Context, req *light.TxStatusRequ
// All the response is not verifiable, so always pick the first // All the response is not verifiable, so always pick the first
// one we get. // one we get.
for index, status := range req.Status { for index, status := range req.Status {
if result[index].Status != core.TxStatusUnknown { if result[index].Status != txpool.TxStatusUnknown {
continue continue
} }
if status.Status == core.TxStatusUnknown { if status.Status == txpool.TxStatusUnknown {
continue continue
} }
result[index], missing = status, missing-1 result[index], missing = status, missing-1

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@ -294,7 +295,7 @@ func testGetTxStatusFromUnindexedPeers(t *testing.T, protocol int) {
if testHash == (common.Hash{}) { if testHash == (common.Hash{}) {
testHash = tx.Hash() testHash = tx.Hash()
testStatus = light.TxStatus{ testStatus = light.TxStatus{
Status: core.TxStatusIncluded, Status: txpool.TxStatusIncluded,
Lookup: &rawdb.LegacyTxLookupEntry{ Lookup: &rawdb.LegacyTxLookupEntry{
BlockHash: block.Hash(), BlockHash: block.Hash(),
BlockIndex: block.NumberU64(), BlockIndex: block.NumberU64(),
@ -327,7 +328,7 @@ func testGetTxStatusFromUnindexedPeers(t *testing.T, protocol int) {
if txLookup != txIndexUnlimited && (txLookup == txIndexDisabled || number < min) { if txLookup != txIndexUnlimited && (txLookup == txIndexDisabled || number < min) {
continue // Filter out unindexed transactions continue // Filter out unindexed transactions
} }
stats[i].Status = core.TxStatusIncluded stats[i].Status = txpool.TxStatusIncluded
stats[i].Lookup = &rawdb.LegacyTxLookupEntry{ stats[i].Lookup = &rawdb.LegacyTxLookupEntry{
BlockHash: blockHashes[hash], BlockHash: blockHashes[hash],
BlockIndex: number, BlockIndex: number,

@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/les/flowcontrol"
@ -49,7 +50,7 @@ type ethBackend interface {
BloomIndexer() *core.ChainIndexer BloomIndexer() *core.ChainIndexer
ChainDb() ethdb.Database ChainDb() ethdb.Database
Synced() bool Synced() bool
TxPool() *core.TxPool TxPool() *txpool.TxPool
} }
type LesServer struct { type LesServer struct {

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/les/flowcontrol" "github.com/ethereum/go-ethereum/les/flowcontrol"
@ -62,7 +63,7 @@ type serverHandler struct {
forkFilter forkid.Filter forkFilter forkid.Filter
blockchain *core.BlockChain blockchain *core.BlockChain
chainDb ethdb.Database chainDb ethdb.Database
txpool *core.TxPool txpool *txpool.TxPool
server *LesServer server *LesServer
closeCh chan struct{} // Channel used to exit all background routines of handler. closeCh chan struct{} // Channel used to exit all background routines of handler.
@ -73,7 +74,7 @@ type serverHandler struct {
addTxsSync bool addTxsSync bool
} }
func newServerHandler(server *LesServer, blockchain *core.BlockChain, chainDb ethdb.Database, txpool *core.TxPool, synced func() bool) *serverHandler { func newServerHandler(server *LesServer, blockchain *core.BlockChain, chainDb ethdb.Database, txpool *txpool.TxPool, synced func() bool) *serverHandler {
handler := &serverHandler{ handler := &serverHandler{
forkFilter: forkid.NewFilter(blockchain), forkFilter: forkid.NewFilter(blockchain),
server: server, server: server,
@ -343,7 +344,7 @@ func (h *serverHandler) BlockChain() *core.BlockChain {
} }
// TxPool implements serverBackend // TxPool implements serverBackend
func (h *serverHandler) TxPool() *core.TxPool { func (h *serverHandler) TxPool() *txpool.TxPool {
return h.txpool return h.txpool
} }

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -36,7 +37,7 @@ type serverBackend interface {
ArchiveMode() bool ArchiveMode() bool
AddTxsSync() bool AddTxsSync() bool
BlockChain() *core.BlockChain BlockChain() *core.BlockChain
TxPool() *core.TxPool TxPool() *txpool.TxPool
GetHelperTrie(typ uint, index uint64) *trie.Trie GetHelperTrie(typ uint, index uint64) *trie.Trie
} }
@ -516,7 +517,7 @@ func handleSendTx(msg Decoder) (serveRequestFn, uint64, uint64, error) {
} }
hash := tx.Hash() hash := tx.Hash()
stats[i] = txStatus(backend, hash) stats[i] = txStatus(backend, hash)
if stats[i].Status == core.TxStatusUnknown { if stats[i].Status == txpool.TxStatusUnknown {
addFn := backend.TxPool().AddRemotes addFn := backend.TxPool().AddRemotes
// Add txs synchronously for testing purpose // Add txs synchronously for testing purpose
if backend.AddTxsSync() { if backend.AddTxsSync() {
@ -558,10 +559,10 @@ func txStatus(b serverBackend, hash common.Hash) light.TxStatus {
stat.Status = b.TxPool().Status([]common.Hash{hash})[0] stat.Status = b.TxPool().Status([]common.Hash{hash})[0]
// If the transaction is unknown to the pool, try looking it up locally. // If the transaction is unknown to the pool, try looking it up locally.
if stat.Status == core.TxStatusUnknown { if stat.Status == txpool.TxStatusUnknown {
lookup := b.BlockChain().GetTransactionLookup(hash) lookup := b.BlockChain().GetTransactionLookup(hash)
if lookup != nil { if lookup != nil {
stat.Status = core.TxStatusIncluded stat.Status = txpool.TxStatusIncluded
stat.Lookup = lookup stat.Lookup = lookup
} }
} }

@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
@ -269,9 +270,9 @@ func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Da
simulation := backends.NewSimulatedBackendWithDatabase(db, gspec.Alloc, 100000000) simulation := backends.NewSimulatedBackendWithDatabase(db, gspec.Alloc, 100000000)
prepare(blocks, simulation) prepare(blocks, simulation)
txpoolConfig := core.DefaultTxPoolConfig txpoolConfig := txpool.DefaultConfig
txpoolConfig.Journal = "" txpoolConfig.Journal = ""
txpool := core.NewTxPool(txpoolConfig, gspec.Config, simulation.Blockchain()) txpool := txpool.NewTxPool(txpoolConfig, gspec.Config, simulation.Blockchain())
if indexers != nil { if indexers != nil {
checkpointConfig := &params.CheckpointOracleConfig{ checkpointConfig := &params.CheckpointOracleConfig{
Address: crypto.CreateAddress(bankAddr, 0), Address: crypto.CreateAddress(bankAddr, 0),

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
) )
@ -182,7 +183,7 @@ func (req *BloomRequest) StoreResult(db ethdb.Database) {
// TxStatus describes the status of a transaction // TxStatus describes the status of a transaction
type TxStatus struct { type TxStatus struct {
Status core.TxStatus Status txpool.TxStatus
Lookup *rawdb.LegacyTxLookupEntry `rlp:"nil"` Lookup *rawdb.LegacyTxLookupEntry `rlp:"nil"`
Error string Error string
} }

@ -23,8 +23,8 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -277,7 +277,7 @@ func GetBloomBits(ctx context.Context, odr OdrBackend, bit uint, sections []uint
// number of retries, thus giving a weak guarantee. // number of retries, thus giving a weak guarantee.
func GetTransaction(ctx context.Context, odr OdrBackend, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { func GetTransaction(ctx context.Context, odr OdrBackend, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
r := &TxStatusRequest{Hashes: []common.Hash{txHash}} r := &TxStatusRequest{Hashes: []common.Hash{txHash}}
if err := odr.RetrieveTxStatus(ctx, r); err != nil || r.Status[0].Status != core.TxStatusIncluded { if err := odr.RetrieveTxStatus(ctx, r); err != nil || r.Status[0].Status != txpool.TxStatusIncluded {
return nil, common.Hash{}, 0, 0, err return nil, common.Hash{}, 0, 0, err
} }
pos := r.Status[0].Lookup pos := r.Status[0].Lookup

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -354,7 +355,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// Validate the transaction sender and it's sig. Throw // Validate the transaction sender and it's sig. Throw
// if the from fields is invalid. // if the from fields is invalid.
if from, err = types.Sender(pool.signer, tx); err != nil { if from, err = types.Sender(pool.signer, tx); err != nil {
return core.ErrInvalidSender return txpool.ErrInvalidSender
} }
// Last but not least check for nonce errors // Last but not least check for nonce errors
currentState := pool.currentState(ctx) currentState := pool.currentState(ctx)
@ -366,14 +367,14 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
// block limit gas. // block limit gas.
header := pool.chain.GetHeaderByHash(pool.head) header := pool.chain.GetHeaderByHash(pool.head)
if header.GasLimit < tx.Gas() { if header.GasLimit < tx.Gas() {
return core.ErrGasLimit return txpool.ErrGasLimit
} }
// Transactions can't be negative. This may never happen // Transactions can't be negative. This may never happen
// using RLP decoded transactions but may occur if you create // using RLP decoded transactions but may occur if you create
// a transaction using the RPC for example. // a transaction using the RPC for example.
if tx.Value().Sign() < 0 { if tx.Value().Sign() < 0 {
return core.ErrNegativeValue return txpool.ErrNegativeValue
} }
// Transactor should have enough funds to cover the costs // Transactor should have enough funds to cover the costs

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -39,7 +40,7 @@ import (
// to offer all the functions here. // to offer all the functions here.
type Backend interface { type Backend interface {
BlockChain() *core.BlockChain BlockChain() *core.BlockChain
TxPool() *core.TxPool TxPool() *txpool.TxPool
} }
// Config is the configuration parameters of mining. // Config is the configuration parameters of mining.

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
@ -37,10 +38,10 @@ import (
type mockBackend struct { type mockBackend struct {
bc *core.BlockChain bc *core.BlockChain
txPool *core.TxPool txPool *txpool.TxPool
} }
func NewMockBackend(bc *core.BlockChain, txPool *core.TxPool) *mockBackend { func NewMockBackend(bc *core.BlockChain, txPool *txpool.TxPool) *mockBackend {
return &mockBackend{ return &mockBackend{
bc: bc, bc: bc,
txPool: txPool, txPool: txPool,
@ -51,7 +52,7 @@ func (m *mockBackend) BlockChain() *core.BlockChain {
return m.bc return m.bc
} }
func (m *mockBackend) TxPool() *core.TxPool { func (m *mockBackend) TxPool() *txpool.TxPool {
return m.txPool return m.txPool
} }
@ -263,7 +264,7 @@ func createMiner(t *testing.T) (*Miner, *event.TypeMux, func(skipMiner bool)) {
statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil) statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil)
blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)} blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)}
pool := core.NewTxPool(testTxPoolConfig, chainConfig, blockchain) pool := txpool.NewTxPool(testTxPoolConfig, chainConfig, blockchain)
backend := NewMockBackend(bc, pool) backend := NewMockBackend(bc, pool)
// Create event Mux // Create event Mux
mux := new(event.TypeMux) mux := new(event.TypeMux)

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -245,7 +246,7 @@ func makeMiner(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
SyncMode: downloader.FullSync, SyncMode: downloader.FullSync,
DatabaseCache: 256, DatabaseCache: 256,
DatabaseHandles: 256, DatabaseHandles: 256,
TxPool: core.DefaultTxPoolConfig, TxPool: txpool.DefaultConfig,
GPO: ethconfig.Defaults.GPO, GPO: ethconfig.Defaults.GPO,
Ethash: ethconfig.Defaults.Ethash, Ethash: ethconfig.Defaults.Ethash,
Miner: miner.Config{ Miner: miner.Config{

@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/beacon" "github.com/ethereum/go-ethereum/core/beacon"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -484,7 +485,7 @@ func makeFullNode(genesis *core.Genesis) (*node.Node, *eth.Ethereum, *ethcatalys
SyncMode: downloader.FullSync, SyncMode: downloader.FullSync,
DatabaseCache: 256, DatabaseCache: 256,
DatabaseHandles: 256, DatabaseHandles: 256,
TxPool: core.DefaultTxPoolConfig, TxPool: txpool.DefaultConfig,
GPO: ethconfig.Defaults.GPO, GPO: ethconfig.Defaults.GPO,
Ethash: ethconfig.Defaults.Ethash, Ethash: ethconfig.Defaults.Ethash,
Miner: miner.Config{ Miner: miner.Config{
@ -535,7 +536,7 @@ func makeLightNode(genesis *core.Genesis) (*node.Node, *les.LightEthereum, *lesc
SyncMode: downloader.LightSync, SyncMode: downloader.LightSync,
DatabaseCache: 256, DatabaseCache: 256,
DatabaseHandles: 256, DatabaseHandles: 256,
TxPool: core.DefaultTxPoolConfig, TxPool: txpool.DefaultConfig,
GPO: ethconfig.Defaults.GPO, GPO: ethconfig.Defaults.GPO,
Ethash: ethconfig.Defaults.Ethash, Ethash: ethconfig.Defaults.Ethash,
LightPeers: 10, LightPeers: 10,

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -206,7 +207,7 @@ func makeSealer(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
SyncMode: downloader.FullSync, SyncMode: downloader.FullSync,
DatabaseCache: 256, DatabaseCache: 256,
DatabaseHandles: 256, DatabaseHandles: 256,
TxPool: core.DefaultTxPoolConfig, TxPool: txpool.DefaultConfig,
GPO: ethconfig.Defaults.GPO, GPO: ethconfig.Defaults.GPO,
Miner: miner.Config{ Miner: miner.Config{
GasCeil: genesis.GasLimit * 11 / 10, GasCeil: genesis.GasLimit * 11 / 10,

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
@ -175,7 +176,7 @@ func makeMiner(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
SyncMode: downloader.FullSync, SyncMode: downloader.FullSync,
DatabaseCache: 256, DatabaseCache: 256,
DatabaseHandles: 256, DatabaseHandles: 256,
TxPool: core.DefaultTxPoolConfig, TxPool: txpool.DefaultConfig,
GPO: ethconfig.Defaults.GPO, GPO: ethconfig.Defaults.GPO,
Ethash: ethconfig.Defaults.Ethash, Ethash: ethconfig.Defaults.Ethash,
Miner: miner.Config{ Miner: miner.Config{

@ -917,7 +917,7 @@ func (w *worker) commitTransactions(env *environment, txs *types.TransactionsByP
env.tcount++ env.tcount++
txs.Shift() txs.Shift()
case errors.Is(err, core.ErrTxTypeNotSupported): case errors.Is(err, types.ErrTxTypeNotSupported):
// Pop the unsupported transaction without shifting in the next from the account // Pop the unsupported transaction without shifting in the next from the account
log.Trace("Skipping unsupported transaction type", "sender", from, "type", tx.Type()) log.Trace("Skipping unsupported transaction type", "sender", from, "type", tx.Type())
txs.Pop() txs.Pop()

@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@ -51,7 +52,7 @@ const (
var ( var (
// Test chain configurations // Test chain configurations
testTxPoolConfig core.TxPoolConfig testTxPoolConfig txpool.Config
ethashChainConfig *params.ChainConfig ethashChainConfig *params.ChainConfig
cliqueChainConfig *params.ChainConfig cliqueChainConfig *params.ChainConfig
@ -74,7 +75,7 @@ var (
) )
func init() { func init() {
testTxPoolConfig = core.DefaultTxPoolConfig testTxPoolConfig = txpool.DefaultConfig
testTxPoolConfig.Journal = "" testTxPoolConfig.Journal = ""
ethashChainConfig = new(params.ChainConfig) ethashChainConfig = new(params.ChainConfig)
*ethashChainConfig = *params.TestChainConfig *ethashChainConfig = *params.TestChainConfig
@ -111,7 +112,7 @@ func init() {
// testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing. // testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing.
type testWorkerBackend struct { type testWorkerBackend struct {
db ethdb.Database db ethdb.Database
txPool *core.TxPool txPool *txpool.TxPool
chain *core.BlockChain chain *core.BlockChain
genesis *core.Genesis genesis *core.Genesis
uncleBlock *types.Block uncleBlock *types.Block
@ -134,7 +135,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
t.Fatalf("unexpected consensus engine type: %T", engine) t.Fatalf("unexpected consensus engine type: %T", engine)
} }
chain, _ := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil, nil) chain, _ := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil, nil)
txpool := core.NewTxPool(testTxPoolConfig, chainConfig, chain) txpool := txpool.NewTxPool(testTxPoolConfig, chainConfig, chain)
// Generate a small n-block chain and an uncle block for it // Generate a small n-block chain and an uncle block for it
var uncle *types.Block var uncle *types.Block
@ -166,7 +167,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
} }
func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain } func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain }
func (b *testWorkerBackend) TxPool() *core.TxPool { return b.txPool } func (b *testWorkerBackend) TxPool() *txpool.TxPool { return b.txPool }
func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) {
return nil, errors.New("not supported") return nil, errors.New("not supported")
} }

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@ -111,7 +112,7 @@ func init() {
type fuzzer struct { type fuzzer struct {
chain *core.BlockChain chain *core.BlockChain
pool *core.TxPool pool *txpool.TxPool
chainLen int chainLen int
addr, txs []common.Hash addr, txs []common.Hash
@ -137,7 +138,7 @@ func newFuzzer(input []byte) *fuzzer {
chtKeys: chtKeys, chtKeys: chtKeys,
bloomKeys: bloomKeys, bloomKeys: bloomKeys,
nonce: uint64(len(txHashes)), nonce: uint64(len(txHashes)),
pool: core.NewTxPool(core.DefaultTxPoolConfig, params.TestChainConfig, chain), pool: txpool.NewTxPool(txpool.DefaultConfig, params.TestChainConfig, chain),
input: bytes.NewReader(input), input: bytes.NewReader(input),
} }
} }
@ -229,7 +230,7 @@ func (f *fuzzer) BlockChain() *core.BlockChain {
return f.chain return f.chain
} }
func (f *fuzzer) TxPool() *core.TxPool { func (f *fuzzer) TxPool() *txpool.TxPool {
return f.pool return f.pool
} }

Loading…
Cancel
Save