core/txpool: add pending, queued slots to txpool's stats

This commit is contained in:
Bui Quang Minh 2023-05-30 18:06:20 +07:00
parent 41ee96fdfe
commit e85fb69328
No known key found for this signature in database
GPG key ID: 9591AA13D0891B99
16 changed files with 114 additions and 78 deletions

View file

@ -1481,8 +1481,8 @@ func (p *BlobPool) Nonce(addr common.Address) uint64 {
}
// Stats retrieves the current pool stats, namely the number of pending and the
// number of queued (non-executable) transactions.
func (p *BlobPool) Stats() (int, int) {
// number of queued (non-executable) transactions, slots.
func (p *BlobPool) Stats() (int, int, int, int) {
p.lock.Lock()
defer p.lock.Unlock()
@ -1490,7 +1490,7 @@ func (p *BlobPool) Stats() (int, int) {
for _, txs := range p.index {
pending += len(txs)
}
return pending, 0 // No non-executable txs in the blob pool
return pending, 0, 0, 0 // No non-executable txs in the blob pool
}
// Content retrieves the data content of the transaction pool, returning all the

View file

@ -348,12 +348,17 @@ func (pool *LegacyPool) loop() {
// Handle stats reporting ticks
case <-report.C:
pool.mu.RLock()
pending, queued := pool.stats()
pending, queued, pendingSlots, queuedSlots := pool.stats()
pool.mu.RUnlock()
stales := int(pool.priced.stales.Load())
if pending != prevPending || queued != prevQueued || stales != prevStales {
log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales)
log.Debug(
"Transaction pool status report",
"executable", pending, "executable slots", pendingSlots,
"queued", queued, "queued slots", queuedSlots,
"stales", stales,
)
prevPending, prevQueued, prevStales = pending, queued, stales
}
@ -448,27 +453,35 @@ func (pool *LegacyPool) Nonce(addr common.Address) uint64 {
return pool.pendingNonces.get(addr)
}
// Stats retrieves the current pool stats, namely the number of pending and the
// number of queued (non-executable) transactions.
func (pool *LegacyPool) Stats() (int, int) {
// Stats retrieves the current pool stats, namely the number of pending transactions,
// slots, and the number of queued (non-executable) transactions, slots.
func (pool *LegacyPool) Stats() (int, int, int, int) {
pool.mu.RLock()
defer pool.mu.RUnlock()
return pool.stats()
}
// stats retrieves the current pool stats, namely the number of pending and the
// number of queued (non-executable) transactions.
func (pool *LegacyPool) stats() (int, int) {
// stats retrieves the current pool stats, namely the number of pending transactions,
// slots and the number of queued (non-executable) transactions, slots.
func (pool *LegacyPool) stats() (int, int, int, int) {
pending := 0
for _, list := range pool.pending {
pending += list.Len()
}
pendingSlots := 0
for _, list := range pool.pending {
pendingSlots += list.TotalSlots()
}
queued := 0
for _, list := range pool.queue {
queued += list.Len()
}
return pending, queued
queuedSlots := 0
for _, list := range pool.queue {
queuedSlots += list.TotalSlots()
}
return pending, queued, pendingSlots, queuedSlots
}
// Content retrieves the data content of the transaction pool, returning all the

View file

@ -35,7 +35,7 @@ func pricedValuedTransaction(nonce uint64, value int64, gaslimit uint64, gaspric
func count(t *testing.T, pool *LegacyPool) (pending int, queued int) {
t.Helper()
pending, queued = pool.stats()
pending, queued, _, _ = pool.stats()
if err := validatePoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -58,7 +58,7 @@ func fillPool(t testing.TB, pool *LegacyPool) {
// Import the batch and verify that limits have been enforced
pool.addRemotesSync(executableTxs)
pool.addRemotesSync(nonExecutableTxs)
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
slots := pool.all.Slots()
// sanity-check that the test prerequisites are ok (pending full)
if have, want := pending, slots; have != want {
@ -87,7 +87,7 @@ func TestTransactionFutureAttack(t *testing.T) {
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
defer pool.Close()
fillPool(t, pool)
pending, _ := pool.Stats()
pending, _, _, _ := pool.Stats()
// Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops
{
key, _ := crypto.GenerateKey()
@ -102,7 +102,7 @@ func TestTransactionFutureAttack(t *testing.T) {
t.Logf("pending: %d queued: %d, all: %d\n", newPending, newQueued, pool.all.Slots())
}
}
newPending, _ := pool.Stats()
newPending, _, _, _ := pool.Stats()
// Pending should not have been touched
if have, want := newPending, pending; have < want {
t.Errorf("wrong pending-count, have %d, want %d (GlobalSlots: %d)",
@ -123,7 +123,7 @@ func TestTransactionFuture1559(t *testing.T) {
// Create a number of test accounts, fund them and make transactions
fillPool(t, pool)
pending, _ := pool.Stats()
pending, _, _, _ := pool.Stats()
// Now, future transaction attack starts, let's add a bunch of expensive non-executables, and see if the pending-count drops
{
@ -135,7 +135,7 @@ func TestTransactionFuture1559(t *testing.T) {
}
pool.addRemotesSync(futureTxs)
}
newPending, _ := pool.Stats()
newPending, _, _, _ := pool.Stats()
// Pending should not have been touched
if have, want := newPending, pending; have != want {
t.Errorf("Wrong pending-count, have %d, want %d (GlobalSlots: %d)",

View file

@ -177,7 +177,7 @@ func validatePoolInternals(pool *LegacyPool) error {
defer pool.mu.RUnlock()
// Ensure the total transaction set is consistent with pending + queued
pending, queued := pool.stats()
pending, queued, _, _ := pool.stats()
if total := pool.all.Count(); total != pending+queued {
return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued)
}
@ -828,7 +828,7 @@ func TestGapFilling(t *testing.T) {
transaction(0, 100000, key),
transaction(2, 100000, key),
})
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 1 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1)
}
@ -845,7 +845,7 @@ func TestGapFilling(t *testing.T) {
if err := pool.addRemoteSync(transaction(1, 100000, key)); err != nil {
t.Fatalf("failed to add gapped transaction: %v", err)
}
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
@ -1029,7 +1029,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err)
}
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
@ -1044,7 +1044,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
time.Sleep(2 * evictionInterval)
// Transactions should not be evicted from the queue yet since lifetime duration has not passed
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
@ -1058,7 +1058,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
// Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains
time.Sleep(2 * config.Lifetime)
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
@ -1081,7 +1081,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
<-pool.requestReset(nil, nil)
// make sure queue, pending are cleared
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
@ -1111,7 +1111,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
time.Sleep(6 * evictionInterval)
// All gapped transactions shouldn't be kicked out
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@ -1124,7 +1124,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
// The whole life time pass after last promotion, kick out stale transactions
time.Sleep(2 * config.Lifetime)
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@ -1275,7 +1275,7 @@ func TestAllowedTxSize(t *testing.T) {
t.Fatalf("expected rejection on oversize transaction")
}
// Run some sanity checks on the pool internals
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@ -1415,7 +1415,7 @@ func TestRepricing(t *testing.T) {
pool.addRemotesSync(txs)
pool.addLocal(ltx)
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 7 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7)
}
@ -1431,7 +1431,7 @@ func TestRepricing(t *testing.T) {
// Reprice the pool and check that underpriced transactions get dropped
pool.SetGasTip(big.NewInt(2))
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@ -1465,7 +1465,7 @@ func TestRepricing(t *testing.T) {
if err := pool.addLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err)
}
if pending, _ = pool.Stats(); pending != 3 {
if pending, _, _, _ = pool.Stats(); pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
if err := validateEvents(events, 1); err != nil {
@ -1536,7 +1536,7 @@ func TestRepricingDynamicFee(t *testing.T) {
pool.addRemotesSync(txs)
pool.addLocal(ltx)
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 7 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7)
}
@ -1552,7 +1552,7 @@ func TestRepricingDynamicFee(t *testing.T) {
// Reprice the pool and check that underpriced transactions get dropped
pool.SetGasTip(big.NewInt(2))
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@ -1589,7 +1589,7 @@ func TestRepricingDynamicFee(t *testing.T) {
if err := pool.addLocal(tx); err != nil {
t.Fatalf("failed to add underpriced local transaction: %v", err)
}
if pending, _ = pool.Stats(); pending != 3 {
if pending, _, _, _ = pool.Stats(); pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
if err := validateEvents(events, 1); err != nil {
@ -1662,10 +1662,10 @@ func TestRepricingKeepsLocals(t *testing.T) {
t.Fatal(err)
}
}
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
expPending, expQueued := 1000, 1000
validate := func() {
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != expPending {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending)
}
@ -1735,7 +1735,7 @@ func TestUnderpricing(t *testing.T) {
pool.addRemotes(txs)
pool.addLocal(ltx)
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
@ -1770,7 +1770,7 @@ func TestUnderpricing(t *testing.T) {
if err := pool.addRemote(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != txpool.ErrFutureReplacePending {
t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, txpool.ErrFutureReplacePending)
}
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@ -1792,7 +1792,7 @@ func TestUnderpricing(t *testing.T) {
if err := pool.addLocal(ltx); err != nil {
t.Fatalf("failed to add new underpriced local transaction: %v", err)
}
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
@ -1843,7 +1843,7 @@ func TestStableUnderpricing(t *testing.T) {
}
pool.addRemotesSync(txs)
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != int(config.GlobalSlots) {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.GlobalSlots)
}
@ -1860,7 +1860,7 @@ func TestStableUnderpricing(t *testing.T) {
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil {
t.Fatalf("failed to add well priced transaction: %v", err)
}
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != int(config.GlobalSlots) {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.GlobalSlots)
}
@ -1914,7 +1914,7 @@ func TestUnderpricingDynamicFee(t *testing.T) {
pool.addRemotes(txs) // Pend K0:0, K0:1; Que K1:1
pool.addLocal(ltx) // +K2:0 => Pend K0:0, K0:1, K2:0; Que K1:1
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
@ -1948,7 +1948,7 @@ func TestUnderpricingDynamicFee(t *testing.T) {
if err := pool.addRemoteSync(tx); err != nil { // +K1:3, -K1:0 => Pend K0:0 K2:0; Que K1:2 K1:3
t.Fatalf("failed to add well priced transaction: %v", err)
}
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}
@ -1970,7 +1970,7 @@ func TestUnderpricingDynamicFee(t *testing.T) {
if err := pool.addLocal(ltx); err != nil {
t.Fatalf("failed to add new underpriced local transaction: %v", err)
}
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 3 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
}
@ -2022,7 +2022,7 @@ func TestDualHeapEviction(t *testing.T) {
}
pool.addRemotesSync([]*types.Transaction{tx})
}
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending+queued != 20 {
t.Fatalf("transaction count mismatch: have %d, want %d", pending+queued, 10)
}
@ -2076,7 +2076,7 @@ func TestDeduplication(t *testing.T) {
t.Errorf("add %d failed: %v", i, err)
}
}
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 1 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1)
}
@ -2096,7 +2096,7 @@ func TestDeduplication(t *testing.T) {
t.Errorf("add %d failed: %v", i, err)
}
}
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != len(txs) {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, len(txs))
}
@ -2351,7 +2351,7 @@ func testJournaling(t *testing.T, nolocals bool) {
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil {
t.Fatalf("failed to add remote transaction: %v", err)
}
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 4 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
}
@ -2369,7 +2369,7 @@ func testJournaling(t *testing.T, nolocals bool) {
pool = New(config, blockchain)
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if queued != 0 {
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
}
@ -2396,7 +2396,7 @@ func testJournaling(t *testing.T, nolocals bool) {
pool = New(config, blockchain)
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
pending, queued = pool.Stats()
pending, queued, _, _ = pool.Stats()
if pending != 0 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
}
@ -2445,7 +2445,7 @@ func TestStatusCheck(t *testing.T) {
// Import the transaction and ensure they are correctly added
pool.addRemotesSync(txs)
pending, queued := pool.Stats()
pending, queued, _, _ := pool.Stats()
if pending != 2 {
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
}

View file

@ -53,10 +53,11 @@ func (h *nonceHeap) Pop() interface{} {
// sortedMap is a nonce->transaction hash map with a heap based index to allow
// iterating over the contents in a nonce-incrementing way.
type sortedMap struct {
items map[uint64]*types.Transaction // Hash map storing the transaction data
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
cache types.Transactions // Cache of the transactions already sorted
cacheMu sync.Mutex // Mutex covering the cache
items map[uint64]*types.Transaction // Hash map storing the transaction data
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
cache types.Transactions // Cache of the transactions already sorted
cacheMu sync.Mutex // Mutex covering the cache
totalslots int // Total number of slots of all transactions in the list
}
// newSortedMap creates a new nonce-sorted transaction map.
@ -78,7 +79,11 @@ func (m *sortedMap) Put(tx *types.Transaction) {
nonce := tx.Nonce()
if m.items[nonce] == nil {
heap.Push(m.index, nonce)
} else {
m.totalslots -= numSlots(m.items[nonce])
}
m.totalslots += numSlots(tx)
m.cacheMu.Lock()
m.items[nonce], m.cache = tx, nil
m.cacheMu.Unlock()
@ -94,6 +99,7 @@ func (m *sortedMap) Forward(threshold uint64) types.Transactions {
for m.index.Len() > 0 && (*m.index)[0] < threshold {
nonce := heap.Pop(m.index).(uint64)
removed = append(removed, m.items[nonce])
m.totalslots -= numSlots(m.items[nonce])
delete(m.items, nonce)
}
// If we had a cached order, shift the front
@ -139,6 +145,7 @@ func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transacti
for nonce, tx := range m.items {
if filter(tx) {
removed = append(removed, tx)
m.totalslots -= numSlots(m.items[nonce])
delete(m.items, nonce)
}
}
@ -192,6 +199,7 @@ func (m *sortedMap) Remove(nonce uint64) bool {
break
}
}
m.totalslots -= numSlots(m.items[nonce])
delete(m.items, nonce)
m.cacheMu.Lock()
m.cache = nil
@ -216,6 +224,7 @@ func (m *sortedMap) Ready(start uint64) types.Transactions {
var ready types.Transactions
for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
ready = append(ready, m.items[next])
m.totalslots -= numSlots(m.items[next])
delete(m.items, next)
heap.Pop(m.index)
}
@ -452,6 +461,11 @@ func (l *list) LastElement() *types.Transaction {
return l.txs.LastElement()
}
// TotalSlots returns total slots of transaction list.
func (l *list) TotalSlots() int {
return l.txs.totalslots
}
// subTotalCost subtracts the cost of the given transactions from the
// total cost of all transactions.
func (l *list) subTotalCost(txs []*types.Transaction) {

View file

@ -107,8 +107,8 @@ type SubPool interface {
Nonce(addr common.Address) uint64
// Stats retrieves the current pool stats, namely the number of pending and the
// number of queued (non-executable) transactions.
Stats() (int, int)
// number of queued (non-executable) transactions, slots.
Stats() (pending, queued, pendingSlots, queuedSlots int)
// Content retrieves the data content of the transaction pool, returning all the
// pending as well as queued transactions, grouped by account and sorted by nonce.

View file

@ -342,16 +342,18 @@ func (p *TxPool) Nonce(addr common.Address) uint64 {
}
// Stats retrieves the current pool stats, namely the number of pending and the
// number of queued (non-executable) transactions.
func (p *TxPool) Stats() (int, int) {
var runnable, blocked int
// number of queued (non-executable) transactions, slots.
func (p *TxPool) Stats() (int, int, int, int) {
var runnable, blocked, runnableSlots, blockedSlots int
for _, subpool := range p.subpools {
run, block := subpool.Stats()
run, block, runSlots, blockSlots := subpool.Stats()
runnable += run
blocked += block
runnableSlots += runSlots
blockedSlots += blockSlots
}
return runnable, blocked
return runnable, blocked, runnableSlots, blockedSlots
}
// Content retrieves the data content of the transaction pool, returning all the

View file

@ -311,7 +311,7 @@ func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (
return b.eth.txPool.Nonce(addr), nil
}
func (b *EthAPIBackend) Stats() (runnable int, blocked int) {
func (b *EthAPIBackend) Stats() (pending, queued, pendingSlots, queuedSlots int) {
return b.eth.txPool.Stats()
}

View file

@ -68,7 +68,7 @@ type backend interface {
CurrentHeader() *types.Header
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int
Stats() (pending int, queued int)
Stats() (pending, queued, pendingSlots, pendingQueued int)
SyncProgress() ethereum.SyncProgress
}
@ -741,7 +741,7 @@ type pendStats struct {
// it to the stats server.
func (s *Service) reportPending(conn *connWrapper) error {
// Retrieve the pending count from the local blockchain
pending, _ := s.backend.Stats()
pending, _, _, _ := s.backend.Stats()
// Assemble the transaction stats and send it to the server
log.Trace("Sending pending transactions to ethstats", "count", pending)

View file

@ -211,10 +211,12 @@ func (s *TxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCT
// Status returns the number of pending and queued transaction in the pool.
func (s *TxPoolAPI) Status() map[string]hexutil.Uint {
pending, queue := s.b.Stats()
pending, queue, pendingSlots, queuedSlots := s.b.Stats()
return map[string]hexutil.Uint{
"pending": hexutil.Uint(pending),
"queued": hexutil.Uint(queue),
"pending": hexutil.Uint(pending),
"queued": hexutil.Uint(queue),
"pending slots": hexutil.Uint(pendingSlots),
"queued slots": hexutil.Uint(queuedSlots),
}
}

View file

@ -569,7 +569,7 @@ func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction {
func (b testBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
panic("implement me")
}
func (b testBackend) Stats() (pending int, queued int) { panic("implement me") }
func (b testBackend) Stats() (pending, queued, pendingSlots, queuedSlots int) { panic("implement me") }
func (b testBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
panic("implement me")
}

View file

@ -79,7 +79,7 @@ type Backend interface {
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
Stats() (pending int, queued int)
Stats() (pending, queued, pendingSlots, queuedSlots int)
TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction)
TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction)
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription

View file

@ -324,7 +324,7 @@ func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction
func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
return 0, nil
}
func (b *backendMock) Stats() (pending int, queued int) { return 0, 0 }
func (b *backendMock) Stats() (pending, queued, pendingSlots, queuedSlots int) { return 0, 0, 0, 0 }
func (b *backendMock) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
return nil, nil
}

View file

@ -219,8 +219,13 @@ func (b *LesApiBackend) GetPoolNonce(ctx context.Context, addr common.Address) (
return b.eth.txPool.GetNonce(ctx, addr)
}
func (b *LesApiBackend) Stats() (pending int, queued int) {
return b.eth.txPool.Stats(), 0
func (b *LesApiBackend) Stats() (pending, queued, pendingSlots, queuedSlots int) {
pending = b.eth.txPool.Stats()
// For simplicity, just return number of pending transactions in pending slots
// without calculating the exact number of slots here
pendingSlots = pending
return pending, 0, pendingSlots, 0
}
func (b *LesApiBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {

View file

@ -652,12 +652,12 @@ func testTransactionStatus(t *testing.T, protocol int) {
}
// wait until TxPool processes the inserted block
for i := 0; i < 10; i++ {
if pending, _ := server.handler.txpool.Stats(); pending == 1 {
if pending, _, _, _ := server.handler.txpool.Stats(); pending == 1 {
break
}
time.Sleep(100 * time.Millisecond)
}
if pending, _ := server.handler.txpool.Stats(); pending != 1 {
if pending, _, _, _ := server.handler.txpool.Stats(); pending != 1 {
t.Fatalf("pending count mismatch: have %d, want 1", pending)
}
// Discard new block announcement
@ -677,12 +677,12 @@ func testTransactionStatus(t *testing.T, protocol int) {
}
// wait until TxPool processes the reorg
for i := 0; i < 10; i++ {
if pending, _ := server.handler.txpool.Stats(); pending == 3 {
if pending, _, _, _ := server.handler.txpool.Stats(); pending == 3 {
break
}
time.Sleep(100 * time.Millisecond)
}
if pending, _ := server.handler.txpool.Stats(); pending != 3 {
if pending, _, _, _ := server.handler.txpool.Stats(); pending != 3 {
t.Fatalf("pending count mismatch: have %d, want 3", pending)
}
// Discard new block announcement

View file

@ -138,7 +138,7 @@ func main() {
nonces[index]++
// Wait if we're too saturated
if pend, _ := backend.TxPool().Stats(); pend > 2048 {
if pend, _, _, _ := backend.TxPool().Stats(); pend > 2048 {
time.Sleep(100 * time.Millisecond)
}
}