mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-13 11:36:37 +00:00
eth/fetcher: fix announcement drop logic (#32210)
This PR fixes an issue in the tx_fetcher DoS prevention logic where the code keeps the overflow amount (`want - maxTxAnnounces`) instead of the allowed amount (`maxTxAnnounces - used`). The specific changes are: - Correct slice indexing in the announcement drop logic - Extend the overflow test case to cover the inversion scenario
This commit is contained in:
parent
a327ffe9b3
commit
e9e12a97d2
2 changed files with 29 additions and 2 deletions
|
|
@ -439,8 +439,8 @@ func (f *TxFetcher) loop() {
|
||||||
if want > maxTxAnnounces {
|
if want > maxTxAnnounces {
|
||||||
txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces))
|
txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces))
|
||||||
|
|
||||||
ann.hashes = ann.hashes[:want-maxTxAnnounces]
|
ann.hashes = ann.hashes[:maxTxAnnounces-used]
|
||||||
ann.metas = ann.metas[:want-maxTxAnnounces]
|
ann.metas = ann.metas[:maxTxAnnounces-used]
|
||||||
}
|
}
|
||||||
// All is well, schedule the remainder of the transactions
|
// All is well, schedule the remainder of the transactions
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -1179,6 +1179,24 @@ func TestTransactionFetcherDoSProtection(t *testing.T) {
|
||||||
size: 111,
|
size: 111,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
|
hashesC []common.Hash
|
||||||
|
typesC []byte
|
||||||
|
sizesC []uint32
|
||||||
|
announceC []announce
|
||||||
|
)
|
||||||
|
for i := 0; i < maxTxAnnounces+2; i++ {
|
||||||
|
hash := common.Hash{0x03, byte(i / 256), byte(i % 256)}
|
||||||
|
hashesC = append(hashesC, hash)
|
||||||
|
typesC = append(typesC, types.LegacyTxType)
|
||||||
|
sizesC = append(sizesC, 111)
|
||||||
|
|
||||||
|
announceC = append(announceC, announce{
|
||||||
|
hash: hash,
|
||||||
|
kind: types.LegacyTxType,
|
||||||
|
size: 111,
|
||||||
|
})
|
||||||
|
}
|
||||||
testTransactionFetcherParallel(t, txFetcherTest{
|
testTransactionFetcherParallel(t, txFetcherTest{
|
||||||
init: func() *TxFetcher {
|
init: func() *TxFetcher {
|
||||||
return NewTxFetcher(
|
return NewTxFetcher(
|
||||||
|
|
@ -1192,43 +1210,52 @@ func TestTransactionFetcherDoSProtection(t *testing.T) {
|
||||||
// Announce half of the transaction and wait for them to be scheduled
|
// Announce half of the transaction and wait for them to be scheduled
|
||||||
doTxNotify{peer: "A", hashes: hashesA[:maxTxAnnounces/2], types: typesA[:maxTxAnnounces/2], sizes: sizesA[:maxTxAnnounces/2]},
|
doTxNotify{peer: "A", hashes: hashesA[:maxTxAnnounces/2], types: typesA[:maxTxAnnounces/2], sizes: sizesA[:maxTxAnnounces/2]},
|
||||||
doTxNotify{peer: "B", hashes: hashesB[:maxTxAnnounces/2-1], types: typesB[:maxTxAnnounces/2-1], sizes: sizesB[:maxTxAnnounces/2-1]},
|
doTxNotify{peer: "B", hashes: hashesB[:maxTxAnnounces/2-1], types: typesB[:maxTxAnnounces/2-1], sizes: sizesB[:maxTxAnnounces/2-1]},
|
||||||
|
doTxNotify{peer: "C", hashes: hashesC[:maxTxAnnounces/2-1], types: typesC[:maxTxAnnounces/2-1], sizes: sizesC[:maxTxAnnounces/2-1]},
|
||||||
doWait{time: txArriveTimeout, step: true},
|
doWait{time: txArriveTimeout, step: true},
|
||||||
|
|
||||||
// Announce the second half and keep them in the wait list
|
// Announce the second half and keep them in the wait list
|
||||||
doTxNotify{peer: "A", hashes: hashesA[maxTxAnnounces/2 : maxTxAnnounces], types: typesA[maxTxAnnounces/2 : maxTxAnnounces], sizes: sizesA[maxTxAnnounces/2 : maxTxAnnounces]},
|
doTxNotify{peer: "A", hashes: hashesA[maxTxAnnounces/2 : maxTxAnnounces], types: typesA[maxTxAnnounces/2 : maxTxAnnounces], sizes: sizesA[maxTxAnnounces/2 : maxTxAnnounces]},
|
||||||
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], types: typesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], sizes: sizesB[maxTxAnnounces/2-1 : maxTxAnnounces-1]},
|
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], types: typesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], sizes: sizesB[maxTxAnnounces/2-1 : maxTxAnnounces-1]},
|
||||||
|
doTxNotify{peer: "C", hashes: hashesC[maxTxAnnounces/2-1 : maxTxAnnounces-1], types: typesC[maxTxAnnounces/2-1 : maxTxAnnounces-1], sizes: sizesC[maxTxAnnounces/2-1 : maxTxAnnounces-1]},
|
||||||
|
|
||||||
// Ensure the hashes are split half and half
|
// Ensure the hashes are split half and half
|
||||||
isWaiting(map[string][]announce{
|
isWaiting(map[string][]announce{
|
||||||
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
||||||
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces-1],
|
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces-1],
|
||||||
|
"C": announceC[maxTxAnnounces/2-1 : maxTxAnnounces-1],
|
||||||
}),
|
}),
|
||||||
isScheduled{
|
isScheduled{
|
||||||
tracking: map[string][]announce{
|
tracking: map[string][]announce{
|
||||||
"A": announceA[:maxTxAnnounces/2],
|
"A": announceA[:maxTxAnnounces/2],
|
||||||
"B": announceB[:maxTxAnnounces/2-1],
|
"B": announceB[:maxTxAnnounces/2-1],
|
||||||
|
"C": announceC[:maxTxAnnounces/2-1],
|
||||||
},
|
},
|
||||||
fetching: map[string][]common.Hash{
|
fetching: map[string][]common.Hash{
|
||||||
"A": hashesA[:maxTxRetrievals],
|
"A": hashesA[:maxTxRetrievals],
|
||||||
"B": hashesB[:maxTxRetrievals],
|
"B": hashesB[:maxTxRetrievals],
|
||||||
|
"C": hashesC[:maxTxRetrievals],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Ensure that adding even one more hash results in dropping the hash
|
// Ensure that adding even one more hash results in dropping the hash
|
||||||
doTxNotify{peer: "A", hashes: []common.Hash{hashesA[maxTxAnnounces]}, types: []byte{typesA[maxTxAnnounces]}, sizes: []uint32{sizesA[maxTxAnnounces]}},
|
doTxNotify{peer: "A", hashes: []common.Hash{hashesA[maxTxAnnounces]}, types: []byte{typesA[maxTxAnnounces]}, sizes: []uint32{sizesA[maxTxAnnounces]}},
|
||||||
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces-1 : maxTxAnnounces+1], types: typesB[maxTxAnnounces-1 : maxTxAnnounces+1], sizes: sizesB[maxTxAnnounces-1 : maxTxAnnounces+1]},
|
doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces-1 : maxTxAnnounces+1], types: typesB[maxTxAnnounces-1 : maxTxAnnounces+1], sizes: sizesB[maxTxAnnounces-1 : maxTxAnnounces+1]},
|
||||||
|
doTxNotify{peer: "C", hashes: hashesC[maxTxAnnounces-1 : maxTxAnnounces+2], types: typesC[maxTxAnnounces-1 : maxTxAnnounces+2], sizes: sizesC[maxTxAnnounces-1 : maxTxAnnounces+2]},
|
||||||
|
|
||||||
isWaiting(map[string][]announce{
|
isWaiting(map[string][]announce{
|
||||||
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
"A": announceA[maxTxAnnounces/2 : maxTxAnnounces],
|
||||||
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces],
|
"B": announceB[maxTxAnnounces/2-1 : maxTxAnnounces],
|
||||||
|
"C": announceC[maxTxAnnounces/2-1 : maxTxAnnounces],
|
||||||
}),
|
}),
|
||||||
isScheduled{
|
isScheduled{
|
||||||
tracking: map[string][]announce{
|
tracking: map[string][]announce{
|
||||||
"A": announceA[:maxTxAnnounces/2],
|
"A": announceA[:maxTxAnnounces/2],
|
||||||
"B": announceB[:maxTxAnnounces/2-1],
|
"B": announceB[:maxTxAnnounces/2-1],
|
||||||
|
"C": announceC[:maxTxAnnounces/2-1],
|
||||||
},
|
},
|
||||||
fetching: map[string][]common.Hash{
|
fetching: map[string][]common.Hash{
|
||||||
"A": hashesA[:maxTxRetrievals],
|
"A": hashesA[:maxTxRetrievals],
|
||||||
"B": hashesB[:maxTxRetrievals],
|
"B": hashesB[:maxTxRetrievals],
|
||||||
|
"C": hashesC[:maxTxRetrievals],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue