Skip to content

Commit 1aa5520

Browse files
authored
core/txpool/legacypool: protect cache with mutex (#27898)
This change fixes the a potential race by using mutexes when the m.cache is read or modified.
1 parent 32fde3f commit 1aa5520

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

core/txpool/legacypool/list.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ func (h *nonceHeap) Pop() interface{} {
5353
// sortedMap is a nonce->transaction hash map with a heap based index to allow
5454
// iterating over the contents in a nonce-incrementing way.
5555
type sortedMap struct {
56-
items map[uint64]*types.Transaction // Hash map storing the transaction data
57-
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
58-
cache types.Transactions // Cache of the transactions already sorted
56+
items map[uint64]*types.Transaction // Hash map storing the transaction data
57+
index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
58+
cache types.Transactions // Cache of the transactions already sorted
59+
cacheMu sync.Mutex // Mutex covering the cache
5960
}
6061

6162
// newSortedMap creates a new nonce-sorted transaction map.
@@ -78,7 +79,9 @@ func (m *sortedMap) Put(tx *types.Transaction) {
7879
if m.items[nonce] == nil {
7980
heap.Push(m.index, nonce)
8081
}
82+
m.cacheMu.Lock()
8183
m.items[nonce], m.cache = tx, nil
84+
m.cacheMu.Unlock()
8285
}
8386

8487
// Forward removes all transactions from the map with a nonce lower than the
@@ -94,9 +97,11 @@ func (m *sortedMap) Forward(threshold uint64) types.Transactions {
9497
delete(m.items, nonce)
9598
}
9699
// If we had a cached order, shift the front
100+
m.cacheMu.Lock()
97101
if m.cache != nil {
98102
m.cache = m.cache[len(removed):]
99103
}
104+
m.cacheMu.Unlock()
100105
return removed
101106
}
102107

@@ -120,7 +125,9 @@ func (m *sortedMap) reheap() {
120125
*m.index = append(*m.index, nonce)
121126
}
122127
heap.Init(m.index)
128+
m.cacheMu.Lock()
123129
m.cache = nil
130+
m.cacheMu.Unlock()
124131
}
125132

126133
// filter is identical to Filter, but **does not** regenerate the heap. This method
@@ -136,7 +143,9 @@ func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transacti
136143
}
137144
}
138145
if len(removed) > 0 {
146+
m.cacheMu.Lock()
139147
m.cache = nil
148+
m.cacheMu.Unlock()
140149
}
141150
return removed
142151
}
@@ -160,9 +169,11 @@ func (m *sortedMap) Cap(threshold int) types.Transactions {
160169
heap.Init(m.index)
161170

162171
// If we had a cache, shift the back
172+
m.cacheMu.Lock()
163173
if m.cache != nil {
164174
m.cache = m.cache[:len(m.cache)-len(drops)]
165175
}
176+
m.cacheMu.Unlock()
166177
return drops
167178
}
168179

@@ -182,7 +193,9 @@ func (m *sortedMap) Remove(nonce uint64) bool {
182193
}
183194
}
184195
delete(m.items, nonce)
196+
m.cacheMu.Lock()
185197
m.cache = nil
198+
m.cacheMu.Unlock()
186199

187200
return true
188201
}
@@ -206,7 +219,9 @@ func (m *sortedMap) Ready(start uint64) types.Transactions {
206219
delete(m.items, next)
207220
heap.Pop(m.index)
208221
}
222+
m.cacheMu.Lock()
209223
m.cache = nil
224+
m.cacheMu.Unlock()
210225

211226
return ready
212227
}
@@ -217,6 +232,8 @@ func (m *sortedMap) Len() int {
217232
}
218233

219234
func (m *sortedMap) flatten() types.Transactions {
235+
m.cacheMu.Lock()
236+
defer m.cacheMu.Unlock()
220237
// If the sorting was not cached yet, create and cache it
221238
if m.cache == nil {
222239
m.cache = make(types.Transactions, 0, len(m.items))
@@ -232,8 +249,8 @@ func (m *sortedMap) flatten() types.Transactions {
232249
// sorted internal representation. The result of the sorting is cached in case
233250
// it's requested again before any modifications are made to the contents.
234251
func (m *sortedMap) Flatten() types.Transactions {
235-
// Copy the cache to prevent accidental modifications
236252
cache := m.flatten()
253+
// Copy the cache to prevent accidental modification
237254
txs := make(types.Transactions, len(cache))
238255
copy(txs, cache)
239256
return txs

0 commit comments

Comments
 (0)