eth: use salted hash function for tx broadcast

This commit is contained in:
Felix Lange 2025-08-28 12:17:24 +02:00
parent 3da045cccf
commit b9bd4509b6
2 changed files with 20 additions and 10 deletions

View file

@ -18,8 +18,8 @@ package eth
import ( import (
"cmp" "cmp"
crand "crypto/rand"
"errors" "errors"
"hash/fnv"
"maps" "maps"
"math" "math"
"slices" "slices"
@ -27,6 +27,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/dchest/siphash"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
@ -119,9 +120,10 @@ type handler struct {
chain *core.BlockChain chain *core.BlockChain
maxPeers int maxPeers int
downloader *downloader.Downloader downloader *downloader.Downloader
txFetcher *fetcher.TxFetcher txFetcher *fetcher.TxFetcher
peers *peerSet peers *peerSet
txBroadcastKey [16]byte
eventMux *event.TypeMux eventMux *event.TypeMux
txsCh chan core.NewTxsEvent txsCh chan core.NewTxsEvent
@ -203,6 +205,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
addTxs := func(txs []*types.Transaction) []error { addTxs := func(txs []*types.Transaction) []error {
return h.txpool.Add(txs, false) return h.txpool.Add(txs, false)
} }
h.txBroadcastKey = newBroadcastChoiceKey()
h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx, h.removePeer) h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx, h.removePeer)
return h, nil return h, nil
} }
@ -482,7 +485,7 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce
signer = types.LatestSigner(h.chain.Config()) signer = types.LatestSigner(h.chain.Config())
choice = newBroadcastChoice(h.nodeID) choice = newBroadcastChoice(h.nodeID, h.txBroadcastKey)
peers = h.peers.all() peers = h.peers.all()
) )
@ -689,6 +692,7 @@ func (st *blockRangeState) currentRange() eth.BlockRangeUpdatePacket {
type broadcastChoice struct { type broadcastChoice struct {
self enode.ID self enode.ID
key [16]byte
buffer map[*ethPeer]struct{} buffer map[*ethPeer]struct{}
tmp []broadcastPeer tmp []broadcastPeer
} }
@ -698,9 +702,15 @@ type broadcastPeer struct {
score uint64 score uint64
} }
func newBroadcastChoice(self enode.ID) *broadcastChoice { func newBroadcastChoiceKey() (k [16]byte) {
crand.Read(k[:])
return k
}
func newBroadcastChoice(self enode.ID, key [16]byte) *broadcastChoice {
return &broadcastChoice{ return &broadcastChoice{
self: self, self: self,
key: key,
buffer: make(map[*ethPeer]struct{}), buffer: make(map[*ethPeer]struct{}),
} }
} }
@ -710,7 +720,7 @@ func newBroadcastChoice(self enode.ID) *broadcastChoice {
func (bc *broadcastChoice) choosePeers(peers []*ethPeer, txSender common.Address) map[*ethPeer]struct{} { func (bc *broadcastChoice) choosePeers(peers []*ethPeer, txSender common.Address) map[*ethPeer]struct{} {
// Compute scores. // Compute scores.
bc.tmp = slices.Grow(bc.tmp[:0], len(peers))[:len(peers)] bc.tmp = slices.Grow(bc.tmp[:0], len(peers))[:len(peers)]
hash := fnv.New64() hash := siphash.New(bc.key[:])
for i, peer := range peers { for i, peer := range peers {
hash.Reset() hash.Reset()
hash.Write(bc.self[:]) hash.Write(bc.self[:])

View file

@ -221,8 +221,8 @@ func (b *testHandler) close() {
func TestBroadcastChoice(t *testing.T) { func TestBroadcastChoice(t *testing.T) {
self := enode.HexID("1111111111111111111111111111111111111111111111111111111111111111") self := enode.HexID("1111111111111111111111111111111111111111111111111111111111111111")
choice49 := newBroadcastChoice(self) choice49 := newBroadcastChoice(self, [16]byte{1})
choice50 := newBroadcastChoice(self) choice50 := newBroadcastChoice(self, [16]byte{1})
// Create test peers and random tx sender addresses. // Create test peers and random tx sender addresses.
rand := rand.New(rand.NewSource(33)) rand := rand.New(rand.NewSource(33))
@ -289,7 +289,7 @@ func benchmarkBroadcastChoice(b *testing.B, npeers int) {
} }
self := enode.HexID("1111111111111111111111111111111111111111111111111111111111111111") self := enode.HexID("1111111111111111111111111111111111111111111111111111111111111111")
choice := newBroadcastChoice(self) choice := newBroadcastChoice(self, [16]byte{1})
b.ResetTimer() b.ResetTimer()
for i := range b.N { for i := range b.N {