mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
core: replace txpool priced map with a simple heap
This commit is contained in:
parent
778ee5c4bf
commit
84f45def3a
2 changed files with 89 additions and 152 deletions
206
core/tx_list.go
206
core/tx_list.go
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -353,16 +352,16 @@ func (l *txList) Flatten() types.Transactions {
|
||||||
return l.txs.Flatten()
|
return l.txs.Flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
// priceHeap is a heap.Interface implementation over big integers for retrieving
|
// priceHeap is a heap.Interface implementation over transactions for retrieving
|
||||||
// sorted transaction prices to discard when the pool fills up.
|
// price-sorted transactions to discard when the pool fills up.
|
||||||
type priceHeap []*big.Int
|
type priceHeap []*types.Transaction
|
||||||
|
|
||||||
func (h priceHeap) Len() int { return len(h) }
|
func (h priceHeap) Len() int { return len(h) }
|
||||||
func (h priceHeap) Less(i, j int) bool { return h[i].Cmp(h[j]) < 0 }
|
func (h priceHeap) Less(i, j int) bool { return h[i].GasPrice().Cmp(h[j].GasPrice()) < 0 }
|
||||||
func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||||
|
|
||||||
func (h *priceHeap) Push(x interface{}) {
|
func (h *priceHeap) Push(x interface{}) {
|
||||||
*h = append(*h, x.(*big.Int))
|
*h = append(*h, x.(*types.Transaction))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *priceHeap) Pop() interface{} {
|
func (h *priceHeap) Pop() interface{} {
|
||||||
|
|
@ -373,190 +372,129 @@ func (h *priceHeap) Pop() interface{} {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
// priceKey is the hash map key type representing an unsigned big integer.
|
// txPricedList is a price-sorted heap to allow operating on transactions pool
|
||||||
type priceKey [256 / int(unsafe.Sizeof(uintptr(0)))]big.Word
|
// contents in a price-incrementing way.
|
||||||
|
type txPricedList struct {
|
||||||
// newPriceKey converts a bit integer to a hash map key.
|
all *map[common.Hash]*types.Transaction // Pointer to the map of all transactions
|
||||||
func newPriceKey(x *big.Int) priceKey {
|
items *priceHeap // Heap of prices of all the stored transactions
|
||||||
var key priceKey
|
stales int // Number of stale price points to (re-heap trigger)
|
||||||
copy(key[:], x.Bits())
|
|
||||||
return key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// txPricedMap is a price->transactions hash map with a heap based index to allow
|
// newTxPricedList creates a new price-sorted transaction heap.
|
||||||
// iterating over the contents in a price-incrementing way.
|
func newTxPricedList(all *map[common.Hash]*types.Transaction) *txPricedList {
|
||||||
type txPricedMap struct {
|
return &txPricedList{
|
||||||
items map[priceKey]map[common.Hash]*types.Transaction // Hash map storing the transaction data
|
all: all,
|
||||||
index *priceHeap // Heap of prices of all the stored transactions
|
items: new(priceHeap),
|
||||||
stales int // Number of stale price points to (re-heap trigger)
|
|
||||||
logger log.Logger // Logger reporting basic price pool stats
|
|
||||||
}
|
|
||||||
|
|
||||||
// newTxPricedMap creates a new price-sorted transaction map.
|
|
||||||
func newTxPricedMap() *txPricedMap {
|
|
||||||
m := &txPricedMap{
|
|
||||||
items: make(map[priceKey]map[common.Hash]*types.Transaction),
|
|
||||||
index: new(priceHeap),
|
|
||||||
}
|
}
|
||||||
m.logger = log.New(
|
|
||||||
"prices", log.Lazy{Fn: func() int { return len(*m.index) - m.stales }},
|
|
||||||
"stales", log.Lazy{Fn: func() int { return m.stales }},
|
|
||||||
)
|
|
||||||
return m
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put inserts a new transaction into the map, also updating the map's price index.
|
// Put inserts a new transaction into the heap.
|
||||||
func (m *txPricedMap) Put(tx *types.Transaction) {
|
func (l *txPricedList) Put(tx *types.Transaction) {
|
||||||
price, hash := tx.GasPrice(), tx.Hash()
|
heap.Push(l.items, tx)
|
||||||
|
|
||||||
// Generate the key and ensure we have a valid map for it
|
|
||||||
key := newPriceKey(price)
|
|
||||||
if m.items[key] == nil {
|
|
||||||
m.items[key] = make(map[common.Hash]*types.Transaction)
|
|
||||||
heap.Push(m.index, price)
|
|
||||||
} else if len(m.items[key]) == 0 {
|
|
||||||
m.stales--
|
|
||||||
}
|
|
||||||
// Add the transaction to the map
|
|
||||||
m.items[key][hash] = tx
|
|
||||||
|
|
||||||
m.logger.Trace("Accepted new transaction", "hash", hash, "price", price)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove looks up a transaction and deletes it from the sorted map. Even if no
|
// Removed notifies the prices transaction list that an old transaction dropped
|
||||||
// more transactions are left with the same price point, the price point itself
|
// from the pool. The list will just keep a counter of stale objects and update
|
||||||
// is retained to achieve hysteresis, until a staleness threshold is reached.
|
// the heap if a large enough ratio of transactions go stale.
|
||||||
func (m *txPricedMap) Remove(tx *types.Transaction) {
|
func (l *txPricedList) Removed() {
|
||||||
price, hash := tx.GasPrice(), tx.Hash()
|
// Bump the stale counter, but exit if still too low (< 25%)
|
||||||
|
l.stales++
|
||||||
key := newPriceKey(price)
|
if l.stales <= len(*l.items)/4 {
|
||||||
if txs := m.items[key]; txs != nil {
|
return
|
||||||
if txs[hash] != nil {
|
|
||||||
// Transaction found, delete and update stale counter
|
|
||||||
delete(m.items[key], hash)
|
|
||||||
if len(m.items[key]) == 0 {
|
|
||||||
m.stales++
|
|
||||||
}
|
|
||||||
// If the number of stale entries reached a critical threshold (25%), re-heap and clean up
|
|
||||||
if m.stales > len(*m.index)/4 {
|
|
||||||
m.reheap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m.logger.Trace("Removed old transaction", "hash", hash, "price", price)
|
// Seems we've reached a critical number of stale transactions, reheap
|
||||||
}
|
reheap := make(priceHeap, 0, len(*l.all))
|
||||||
|
|
||||||
// reheap discards the currently cached price point heap and regenerates it based
|
l.stales, l.items = 0, &reheap
|
||||||
// on the contents of the priced transaction map.
|
for _, tx := range *l.all {
|
||||||
func (m *txPricedMap) reheap() {
|
*l.items = append(*l.items, tx)
|
||||||
m.stales, m.index = 0, new(priceHeap)
|
|
||||||
for key, txs := range m.items {
|
|
||||||
if len(txs) == 0 {
|
|
||||||
delete(m.items, key)
|
|
||||||
} else {
|
|
||||||
*m.index = append(*m.index, new(big.Int).SetBits(key[:]))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
heap.Init(m.index)
|
heap.Init(l.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard finds all the transactions below the given price threshold, drops them
|
// Discard finds all the transactions below the given price threshold, drops them
|
||||||
// from the priced map and returs them for further removal from the entire pool.
|
// from the priced list and returs them for further removal from the entire pool.
|
||||||
func (m *txPricedMap) Cap(threshold *big.Int, local *txSet) types.Transactions {
|
func (l *txPricedList) Cap(threshold *big.Int, local *txSet) types.Transactions {
|
||||||
drop := make(types.Transactions, 0, 128) // Remote underpriced transactions to drop
|
drop := make(types.Transactions, 0, 128) // Remote underpriced transactions to drop
|
||||||
save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep
|
save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep
|
||||||
|
|
||||||
for len(*m.index) > 0 {
|
for len(*l.items) > 0 {
|
||||||
// Discard stale price points if found during cleanup
|
// Discard stale transactions if found during cleanup
|
||||||
price := []*big.Int(*m.index)[0]
|
tx := heap.Pop(l.items).(*types.Transaction)
|
||||||
key := newPriceKey(price)
|
|
||||||
|
|
||||||
if len(m.items[key]) == 0 {
|
hash := tx.Hash()
|
||||||
m.stales--
|
if _, ok := (*l.all)[hash]; !ok {
|
||||||
heap.Pop(m.index)
|
l.stales--
|
||||||
delete(m.items, key)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Stop the discards if we've reached the threshold
|
// Stop the discards if we've reached the threshold
|
||||||
if price.Cmp(threshold) >= 0 {
|
if tx.GasPrice().Cmp(threshold) >= 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Non stale price point found, discard its transactions
|
// Non stale transaction found, discard unless local
|
||||||
for hash, tx := range m.items[key] {
|
if local.contains(hash) {
|
||||||
if local.contains(hash) {
|
save = append(save, tx)
|
||||||
save = append(save, tx)
|
} else {
|
||||||
} else {
|
drop = append(drop, tx)
|
||||||
drop = append(drop, tx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m.items[key] = nil // will get removed in next iteration
|
|
||||||
}
|
}
|
||||||
for _, tx := range save {
|
for _, tx := range save {
|
||||||
m.Put(tx)
|
heap.Push(l.items, tx)
|
||||||
}
|
}
|
||||||
return drop
|
return drop
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 transaction currently being tracked.
|
// lowest priced transaction currently being tracked.
|
||||||
func (m *txPricedMap) Underpriced(tx *types.Transaction, local *txSet) bool {
|
func (l *txPricedList) Underpriced(tx *types.Transaction, local *txSet) bool {
|
||||||
// Local transactions cannot be underpriced
|
// Local transactions cannot be underpriced
|
||||||
if local.contains(tx.Hash()) {
|
if local.contains(tx.Hash()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Discard stale price points if found at the heap start
|
// Discard stale price points if found at the heap start
|
||||||
for len(*m.index) > 0 {
|
for len(*l.items) > 0 {
|
||||||
price := []*big.Int(*m.index)[0]
|
head := []*types.Transaction(*l.items)[0]
|
||||||
if key := newPriceKey(price); len(m.items[key]) == 0 {
|
if _, ok := (*l.all)[head.Hash()]; !ok {
|
||||||
m.stales--
|
l.stales--
|
||||||
heap.Pop(m.index)
|
heap.Pop(l.items)
|
||||||
delete(m.items, key)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Check if the transaction is underpriced or not
|
// Check if the transaction is underpriced or not
|
||||||
if len(*m.index) == 0 {
|
if len(*l.items) == 0 {
|
||||||
log.Error("Pricing query for empty pool") // This cannot happen, print to catch programming errors
|
log.Error("Pricing query for empty pool") // This cannot happen, print to catch programming errors
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
cheapest := []*big.Int(*m.index)[0]
|
cheapest := []*types.Transaction(*l.items)[0]
|
||||||
return cheapest.Cmp(tx.GasPrice()) >= 0
|
return cheapest.GasPrice().Cmp(tx.GasPrice()) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard finds a number of most underpriced transactions, removes them from the
|
// Discard finds a number of most underpriced transactions, removes them from the
|
||||||
// priced map and returs them for further removal from the entire pool.
|
// priced list and returs them for further removal from the entire pool.
|
||||||
func (m *txPricedMap) Discard(count int, local *txSet) types.Transactions {
|
func (l *txPricedList) Discard(count int, local *txSet) types.Transactions {
|
||||||
drop := make(types.Transactions, 0, count) // Remote underpriced transactions to drop
|
drop := make(types.Transactions, 0, count) // Remote underpriced transactions to drop
|
||||||
save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep
|
save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep
|
||||||
|
|
||||||
for len(*m.index) > 0 && count > 0 {
|
for len(*l.items) > 0 && count > 0 {
|
||||||
// Discard stale price points if found during cleanup
|
// Discard stale transactions if found during cleanup
|
||||||
price := []*big.Int(*m.index)[0]
|
tx := heap.Pop(l.items).(*types.Transaction)
|
||||||
key := newPriceKey(price)
|
|
||||||
|
|
||||||
if len(m.items[key]) == 0 {
|
hash := tx.Hash()
|
||||||
m.stales--
|
if _, ok := (*l.all)[hash]; !ok {
|
||||||
heap.Pop(m.index)
|
l.stales--
|
||||||
delete(m.items, key)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Non stale price point found, discard its transactions
|
// Non stale transaction found, discard unless local
|
||||||
for hash, tx := range m.items[key] {
|
if local.contains(hash) {
|
||||||
if count == 0 {
|
save = append(save, tx)
|
||||||
break
|
} else {
|
||||||
}
|
drop = append(drop, tx)
|
||||||
if local.contains(hash) {
|
count--
|
||||||
save = append(save, tx)
|
|
||||||
} else {
|
|
||||||
drop = append(drop, tx)
|
|
||||||
count--
|
|
||||||
}
|
|
||||||
delete(m.items[key], hash)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, tx := range save {
|
for _, tx := range save {
|
||||||
m.Put(tx)
|
heap.Push(l.items, tx)
|
||||||
}
|
}
|
||||||
return drop
|
return drop
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ type TxPool struct {
|
||||||
queue map[common.Address]*txList // Queued but non-processable transactions
|
queue map[common.Address]*txList // 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 map[common.Hash]*types.Transaction // All transactions to allow lookups
|
all map[common.Hash]*types.Transaction // All transactions to allow lookups
|
||||||
priced *txPricedMap // All transactions sorted by price
|
priced *txPricedList // All transactions sorted by price
|
||||||
|
|
||||||
wg sync.WaitGroup // for shutdown sync
|
wg sync.WaitGroup // for shutdown sync
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
|
|
@ -117,7 +117,6 @@ func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, currentState
|
||||||
queue: make(map[common.Address]*txList),
|
queue: make(map[common.Address]*txList),
|
||||||
beats: make(map[common.Address]time.Time),
|
beats: make(map[common.Address]time.Time),
|
||||||
all: make(map[common.Hash]*types.Transaction),
|
all: make(map[common.Hash]*types.Transaction),
|
||||||
priced: newTxPricedMap(),
|
|
||||||
eventMux: eventMux,
|
eventMux: eventMux,
|
||||||
currentState: currentStateFn,
|
currentState: currentStateFn,
|
||||||
gasLimit: gasLimitFn,
|
gasLimit: gasLimitFn,
|
||||||
|
|
@ -127,7 +126,7 @@ func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, currentState
|
||||||
events: eventMux.Subscribe(ChainHeadEvent{}, RemovedTransactionEvent{}),
|
events: eventMux.Subscribe(ChainHeadEvent{}, RemovedTransactionEvent{}),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
pool.priced = newTxPricedList(&pool.all)
|
||||||
pool.resetState()
|
pool.resetState()
|
||||||
|
|
||||||
pool.wg.Add(2)
|
pool.wg.Add(2)
|
||||||
|
|
@ -141,7 +140,7 @@ func (pool *TxPool) eventLoop() {
|
||||||
defer pool.wg.Done()
|
defer pool.wg.Done()
|
||||||
|
|
||||||
// Start a ticker and keep track of interesting pool stats to report
|
// Start a ticker and keep track of interesting pool stats to report
|
||||||
var prevPending, prevQueued, prevPrices, prevStales int
|
var prevPending, prevQueued, prevStales int
|
||||||
|
|
||||||
report := time.NewTicker(statsReportInterval)
|
report := time.NewTicker(statsReportInterval)
|
||||||
defer report.Stop()
|
defer report.Stop()
|
||||||
|
|
@ -175,12 +174,12 @@ func (pool *TxPool) eventLoop() {
|
||||||
case <-report.C:
|
case <-report.C:
|
||||||
pool.mu.RLock()
|
pool.mu.RLock()
|
||||||
pending, queued := pool.stats()
|
pending, queued := pool.stats()
|
||||||
prices, stales := len(pool.priced.items), pool.priced.stales
|
stales := pool.priced.stales
|
||||||
pool.mu.RUnlock()
|
pool.mu.RUnlock()
|
||||||
|
|
||||||
if pending != prevPending || queued != prevQueued || prices != prevPrices || stales != prevStales {
|
if pending != prevPending || queued != prevQueued || stales != prevStales {
|
||||||
log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "prices", prices-stales, "stales", stales)
|
log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales)
|
||||||
prevPending, prevQueued, prevPrices, prevStales = pending, queued, prices, stales
|
prevPending, prevQueued, prevStales = pending, queued, stales
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -414,7 +413,7 @@ func (pool *TxPool) add(tx *types.Transaction) (bool, error) {
|
||||||
// New transaction is better, replace old one
|
// New transaction is better, replace old one
|
||||||
if old != nil {
|
if old != nil {
|
||||||
delete(pool.all, old.Hash())
|
delete(pool.all, old.Hash())
|
||||||
pool.priced.Remove(old)
|
pool.priced.Removed()
|
||||||
pendingReplaceCounter.Inc(1)
|
pendingReplaceCounter.Inc(1)
|
||||||
}
|
}
|
||||||
pool.all[tx.Hash()] = tx
|
pool.all[tx.Hash()] = tx
|
||||||
|
|
@ -450,7 +449,7 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) (bool, er
|
||||||
// Discard any previous transaction and mark this
|
// Discard any previous transaction and mark this
|
||||||
if old != nil {
|
if old != nil {
|
||||||
delete(pool.all, old.Hash())
|
delete(pool.all, old.Hash())
|
||||||
pool.priced.Remove(old)
|
pool.priced.Removed()
|
||||||
queuedReplaceCounter.Inc(1)
|
queuedReplaceCounter.Inc(1)
|
||||||
}
|
}
|
||||||
pool.all[hash] = tx
|
pool.all[hash] = tx
|
||||||
|
|
@ -472,7 +471,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T
|
||||||
if !inserted {
|
if !inserted {
|
||||||
// An older transaction was better, discard this
|
// An older transaction was better, discard this
|
||||||
delete(pool.all, hash)
|
delete(pool.all, hash)
|
||||||
pool.priced.Remove(tx)
|
pool.priced.Removed()
|
||||||
|
|
||||||
pendingDiscardCounter.Inc(1)
|
pendingDiscardCounter.Inc(1)
|
||||||
return
|
return
|
||||||
|
|
@ -480,7 +479,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T
|
||||||
// Otherwise discard any previous transaction and mark this
|
// Otherwise discard any previous transaction and mark this
|
||||||
if old != nil {
|
if old != nil {
|
||||||
delete(pool.all, old.Hash())
|
delete(pool.all, old.Hash())
|
||||||
pool.priced.Remove(old)
|
pool.priced.Removed()
|
||||||
|
|
||||||
pendingReplaceCounter.Inc(1)
|
pendingReplaceCounter.Inc(1)
|
||||||
}
|
}
|
||||||
|
|
@ -583,7 +582,7 @@ func (pool *TxPool) removeTx(hash common.Hash) {
|
||||||
|
|
||||||
// Remove it from the list of known transactions
|
// Remove it from the list of known transactions
|
||||||
delete(pool.all, hash)
|
delete(pool.all, hash)
|
||||||
pool.priced.Remove(tx)
|
pool.priced.Removed()
|
||||||
|
|
||||||
// Remove the transaction from the pending lists and reset the account nonce
|
// Remove the transaction from the pending lists and reset the account nonce
|
||||||
if pending := pool.pending[addr]; pending != nil {
|
if pending := pool.pending[addr]; pending != nil {
|
||||||
|
|
@ -625,7 +624,7 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB) {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
log.Trace("Removed old queued transaction", "hash", hash)
|
log.Trace("Removed old queued transaction", "hash", hash)
|
||||||
delete(pool.all, hash)
|
delete(pool.all, hash)
|
||||||
pool.priced.Remove(tx)
|
pool.priced.Removed()
|
||||||
}
|
}
|
||||||
// Drop all transactions that are too costly (low balance)
|
// Drop all transactions that are too costly (low balance)
|
||||||
drops, _ := list.Filter(state.GetBalance(addr))
|
drops, _ := list.Filter(state.GetBalance(addr))
|
||||||
|
|
@ -633,7 +632,7 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB) {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
log.Trace("Removed unpayable queued transaction", "hash", hash)
|
log.Trace("Removed unpayable queued transaction", "hash", hash)
|
||||||
delete(pool.all, hash)
|
delete(pool.all, hash)
|
||||||
pool.priced.Remove(tx)
|
pool.priced.Removed()
|
||||||
queuedNofundsCounter.Inc(1)
|
queuedNofundsCounter.Inc(1)
|
||||||
}
|
}
|
||||||
// Gather all executable transactions and promote them
|
// Gather all executable transactions and promote them
|
||||||
|
|
@ -647,7 +646,7 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB) {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
log.Trace("Removed cap-exceeding queued transaction", "hash", hash)
|
log.Trace("Removed cap-exceeding queued transaction", "hash", hash)
|
||||||
delete(pool.all, hash)
|
delete(pool.all, hash)
|
||||||
pool.priced.Remove(tx)
|
pool.priced.Removed()
|
||||||
queuedRLCounter.Inc(1)
|
queuedRLCounter.Inc(1)
|
||||||
}
|
}
|
||||||
queued += uint64(list.Len())
|
queued += uint64(list.Len())
|
||||||
|
|
@ -761,7 +760,7 @@ func (pool *TxPool) demoteUnexecutables(state *state.StateDB) {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
log.Trace("Removed old pending transaction", "hash", hash)
|
log.Trace("Removed old pending transaction", "hash", hash)
|
||||||
delete(pool.all, hash)
|
delete(pool.all, hash)
|
||||||
pool.priced.Remove(tx)
|
pool.priced.Removed()
|
||||||
}
|
}
|
||||||
// Drop all transactions that are too costly (low balance), and queue any invalids back for later
|
// Drop all transactions that are too costly (low balance), and queue any invalids back for later
|
||||||
drops, invalids := list.Filter(state.GetBalance(addr))
|
drops, invalids := list.Filter(state.GetBalance(addr))
|
||||||
|
|
@ -769,7 +768,7 @@ func (pool *TxPool) demoteUnexecutables(state *state.StateDB) {
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
log.Trace("Removed unpayable pending transaction", "hash", hash)
|
log.Trace("Removed unpayable pending transaction", "hash", hash)
|
||||||
delete(pool.all, hash)
|
delete(pool.all, hash)
|
||||||
pool.priced.Remove(tx)
|
pool.priced.Removed()
|
||||||
pendingNofundsCounter.Inc(1)
|
pendingNofundsCounter.Inc(1)
|
||||||
}
|
}
|
||||||
for _, tx := range invalids {
|
for _, tx := range invalids {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue