mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 13:44:31 +00:00
core: dedup known transactions without global lock, track metrics (#20081)
This commit is contained in:
parent
656f2a6167
commit
bef2c34e44
1 changed files with 12 additions and 9 deletions
|
|
@ -106,7 +106,8 @@ var (
|
|||
queuedNofundsMeter = metrics.NewRegisteredMeter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds
|
||||
|
||||
// General tx metrics
|
||||
validMeter = metrics.NewRegisteredMeter("txpool/valid", nil)
|
||||
knownTxMeter = metrics.NewRegisteredMeter("txpool/known", nil)
|
||||
validTxMeter = metrics.NewRegisteredMeter("txpool/valid", nil)
|
||||
invalidTxMeter = metrics.NewRegisteredMeter("txpool/invalid", nil)
|
||||
underpricedTxMeter = metrics.NewRegisteredMeter("txpool/underpriced", nil)
|
||||
|
||||
|
|
@ -659,21 +660,19 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e
|
|||
hash := tx.Hash()
|
||||
if pool.all.Get(hash) != nil {
|
||||
log.Trace("Discarding already known transaction", "hash", hash)
|
||||
knownTxMeter.Mark(1)
|
||||
return false, fmt.Errorf("known transaction: %x", hash)
|
||||
}
|
||||
|
||||
// If the transaction fails basic validation, discard it
|
||||
if err := pool.validateTx(tx, local); err != nil {
|
||||
log.Trace("Discarding invalid transaction", "hash", hash, "err", err)
|
||||
invalidTxMeter.Mark(1)
|
||||
return false, err
|
||||
}
|
||||
|
||||
from, _ := types.Sender(pool.signer, tx) // already validated
|
||||
if tx.IsSpecialTransaction() && pool.IsSigner != nil && pool.IsSigner(from) && pool.pendingNonces.get(from) == tx.Nonce() {
|
||||
return pool.promoteSpecialTx(from, tx)
|
||||
}
|
||||
|
||||
// If the transaction pool is full, discard underpriced transactions
|
||||
if uint64(pool.all.Count()) >= pool.config.GlobalSlots+pool.config.GlobalQueue {
|
||||
log.Debug("Add transaction to pool full", "hash", hash, "nonce", tx.Nonce())
|
||||
|
|
@ -691,7 +690,6 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e
|
|||
pool.removeTx(tx.Hash(), false)
|
||||
}
|
||||
}
|
||||
|
||||
// Try to replace an existing transaction in the pending pool
|
||||
if list := pool.pending[from]; list != nil && list.Overlaps(tx) {
|
||||
// Nonce already pending, check if required price bump is met
|
||||
|
|
@ -713,13 +711,11 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err e
|
|||
log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To())
|
||||
return old != nil, nil
|
||||
}
|
||||
|
||||
// New transaction isn't replacing a pending one, push into queue
|
||||
replaced, err = pool.enqueueTx(hash, tx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Mark local addresses and journal local transactions
|
||||
if local {
|
||||
if !pool.locals.contains(from) {
|
||||
|
|
@ -905,11 +901,18 @@ func (pool *TxPool) AddRemote(tx *types.Transaction) error {
|
|||
|
||||
// addTxs attempts to queue a batch of transactions if they are valid.
|
||||
func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
|
||||
// Filter out known ones without obtaining the pool lock or recovering signatures
|
||||
for i := 0; i < len(txs); i++ {
|
||||
if pool.all.Get(txs[i].Hash()) != nil {
|
||||
knownTxMeter.Mark(1)
|
||||
txs = append(txs[:i], txs[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
// Cache senders in transactions before obtaining lock (pool.signer is immutable)
|
||||
for _, tx := range txs {
|
||||
types.Sender(pool.signer, tx)
|
||||
}
|
||||
|
||||
pool.mu.Lock()
|
||||
errs, dirtyAddrs := pool.addTxsLocked(txs, local)
|
||||
pool.mu.Unlock()
|
||||
|
|
@ -933,7 +936,7 @@ func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error,
|
|||
dirty.addTx(tx)
|
||||
}
|
||||
}
|
||||
validMeter.Mark(int64(len(dirty.accounts)))
|
||||
validTxMeter.Mark(int64(len(dirty.accounts)))
|
||||
return errs, dirty
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue