Skip to content

Commit 7a41bad

Browse files
MariusVanDerWijdenholiman
authored andcommitted
eth/fetcher: fix fetcher timeout (#28220)
This changes fixes a bug in the fetcher, where the timeout for how long to remember underpriced transaction was erroneously compared, and the timeout never hit. --------- Co-authored-by: Martin Holst Swende <martin@swende.se>
1 parent 89f5ac3 commit 7a41bad

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

eth/fetcher/tx_fetcher.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const (
6161
maxTxUnderpricedSetSize = 32768
6262

6363
// maxTxUnderpricedTimeout is the max time a transaction should be stuck in the underpriced set.
64-
maxTxUnderpricedTimeout = int64(5 * time.Minute)
64+
maxTxUnderpricedTimeout = 5 * time.Minute
6565

6666
// txArriveTimeout is the time allowance before an announced transaction is
6767
// explicitly requested.
@@ -167,7 +167,7 @@ type TxFetcher struct {
167167
drop chan *txDrop
168168
quit chan struct{}
169169

170-
underpriced *lru.Cache[common.Hash, int64] // Transactions discarded as too cheap (don't re-fetch)
170+
underpriced *lru.Cache[common.Hash, time.Time] // Transactions discarded as too cheap (don't re-fetch)
171171

172172
// Stage 1: Waiting lists for newly discovered transactions that might be
173173
// broadcast without needing explicit request/reply round trips.
@@ -222,7 +222,7 @@ func NewTxFetcherForTests(
222222
fetching: make(map[common.Hash]string),
223223
requests: make(map[string]*txRequest),
224224
alternates: make(map[common.Hash]map[string]struct{}),
225-
underpriced: lru.NewCache[common.Hash, int64](maxTxUnderpricedSetSize),
225+
underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize),
226226
hasTx: hasTx,
227227
addTxs: addTxs,
228228
fetchTxs: fetchTxs,
@@ -284,7 +284,7 @@ func (f *TxFetcher) Notify(peer string, types []byte, sizes []uint32, hashes []c
284284
// isKnownUnderpriced reports whether a transaction hash was recently found to be underpriced.
285285
func (f *TxFetcher) isKnownUnderpriced(hash common.Hash) bool {
286286
prevTime, ok := f.underpriced.Peek(hash)
287-
if ok && prevTime+maxTxUnderpricedTimeout < time.Now().Unix() {
287+
if ok && prevTime.Before(time.Now().Add(-maxTxUnderpricedTimeout)) {
288288
f.underpriced.Remove(hash)
289289
return false
290290
}
@@ -335,7 +335,7 @@ func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool)
335335
// Avoid re-request this transaction when we receive another
336336
// announcement.
337337
if errors.Is(err, txpool.ErrUnderpriced) || errors.Is(err, txpool.ErrReplaceUnderpriced) {
338-
f.underpriced.Add(batch[j].Hash(), batch[j].Time().Unix())
338+
f.underpriced.Add(batch[j].Hash(), batch[j].Time())
339339
}
340340
// Track a few interesting failure types
341341
switch {

eth/fetcher/tx_fetcher_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -1993,3 +1993,38 @@ func containsHash(slice []common.Hash, hash common.Hash) bool {
19931993
}
19941994
return false
19951995
}
1996+
1997+
// Tests that a transaction is forgotten after the timeout.
1998+
func TestTransactionForgotten(t *testing.T) {
1999+
fetcher := NewTxFetcher(
2000+
func(common.Hash) bool { return false },
2001+
func(txs []*types.Transaction) []error {
2002+
errs := make([]error, len(txs))
2003+
for i := 0; i < len(errs); i++ {
2004+
errs[i] = txpool.ErrUnderpriced
2005+
}
2006+
return errs
2007+
},
2008+
func(string, []common.Hash) error { return nil },
2009+
func(string) {},
2010+
)
2011+
fetcher.Start()
2012+
defer fetcher.Stop()
2013+
// Create one TX which is 5 minutes old, and one which is recent
2014+
tx1 := types.NewTx(&types.LegacyTx{Nonce: 0})
2015+
tx1.SetTime(time.Now().Add(-maxTxUnderpricedTimeout - 1*time.Second))
2016+
tx2 := types.NewTx(&types.LegacyTx{Nonce: 1})
2017+
2018+
// Enqueue both in the fetcher. They will be immediately tagged as underpriced
2019+
if err := fetcher.Enqueue("asdf", []*types.Transaction{tx1, tx2}, false); err != nil {
2020+
t.Fatal(err)
2021+
}
2022+
// isKnownUnderpriced should trigger removal of the first tx (no longer be known underpriced)
2023+
if fetcher.isKnownUnderpriced(tx1.Hash()) {
2024+
t.Fatal("transaction should be forgotten by now")
2025+
}
2026+
// isKnownUnderpriced should not trigger removal of the second
2027+
if !fetcher.isKnownUnderpriced(tx2.Hash()) {
2028+
t.Fatal("transaction should be known underpriced")
2029+
}
2030+
}

0 commit comments

Comments
 (0)