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

This commit is contained in:
Péter Szilágyi 2022-10-24 16:13:55 +03:00
parent 5f70f9fd37
commit a6dda03644
No known key found for this signature in database
GPG Key ID: E9AE538CEDF8293D
35 changed files with 408 additions and 385 deletions

View File

@ -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 {

View File

@ -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()}

View File

@ -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)
} }

View File

@ -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 {

View File

@ -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()
} }

View File

@ -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)
} }
} }
} }

View File

@ -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()

View File

@ -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 {

View File

@ -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)

View File

@ -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()
} }

View File

@ -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 }

View File

@ -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

View File

@ -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:"-"`

View File

@ -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:

View File

@ -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
}, },

View File

@ -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),
} }
} }

View File

@ -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) }

View File

@ -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

View File

@ -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,

View File

@ -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 {

View File

@ -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
} }

View File

@ -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
} }
} }

View File

@ -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),

View File

@ -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
} }

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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{

View File

@ -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,

View File

@ -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,

View File

@ -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{

View File

@ -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()

View File

@ -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")
} }

View File

@ -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
} }