Skip to content

Commit 9edfc58

Browse files
anacrolixclaude
andauthored
Sync p2p code with go-ethereum to fix netrestrict issues in v5 discovery (#18933)
Fixes #18195. This started as an attempt to carefully pull fixes for possible issues with netrestrict to discovering the upstream changes are quite significant. ## Packages synced from go-ethereum The following packages are forked in-tree from `go-ethereum` (synced to v1.16.8): | Erigon package | go-ethereum package | |---|---| | `p2p/` | `p2p/` | | `p2p/discover/` | `p2p/discover/` | | `p2p/discover/v4wire/` | `p2p/discover/v4wire/` | | `p2p/discover/v5wire/` | `p2p/discover/v5wire/` | | `p2p/dnsdisc/` | `p2p/dnsdisc/` | | `p2p/enode/` | `p2p/enode/` | | `p2p/enr/` | `p2p/enr/` | | `p2p/event/` | `event/` | | `p2p/netutil/` | `p2p/netutil/` | | `p2p/rlpx/` | `p2p/rlpx/` | | `common/mclock/` | `common/mclock/` | | `common/lru/` | `common/lru/` | All packages are vendored locally with no `github.com/ethereum/go-ethereum` module dependency. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 093be96 commit 9edfc58

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+6999
-4188
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
- uses: actions/setup-go@v6
6262
with:
6363
go-version: '1.25'
64-
cache: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') }}
64+
cache: true
6565

6666
- name: Install dependencies on Linux runner
6767
if: runner.os == 'Linux'
@@ -112,7 +112,7 @@ jobs:
112112
- uses: actions/setup-go@v6
113113
with:
114114
go-version: '1.25'
115-
cache: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') }}
115+
cache: true
116116

117117
- name: Install make
118118
run: choco install make -y

.github/workflows/test-all-erigon.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ jobs:
8989
uses: actions/setup-go@v6
9090
with:
9191
go-version: '1.25'
92-
cache: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') }}
93-
92+
cache: true
93+
9494
- name: Install dependencies on Linux
9595
if: runner.os == 'Linux' && needs.source-of-changes.outputs.changed_files != 'true'
9696
run: sudo apt update -y && sudo apt install -y build-essential
@@ -149,7 +149,7 @@ jobs:
149149
uses: actions/setup-go@v6
150150
with:
151151
go-version: '1.25'
152-
cache: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') }}
152+
cache: true
153153

154154
- name: Install make
155155
run: choco install make -y

cl/p2p/p2p_localnode.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ func newLocalNode(
2020
tmpDir string,
2121
logger log.Logger,
2222
) (*enode.LocalNode, error) {
23-
db, err := enode.OpenDB(ctx, "", tmpDir, logger)
23+
db, err := enode.OpenDBEx(ctx, "", tmpDir, logger)
2424
if err != nil {
2525
return nil, fmt.Errorf("could not open node's peer database: %w", err)
2626
}
27-
localNode := enode.NewLocalNode(db, privKey, logger)
27+
localNode := enode.NewLocalNode(db, privKey)
2828

2929
ipEntry := enr.IP(ipAddr)
3030
udpEntry := enr.UDP(udpPort)
@@ -75,7 +75,7 @@ func NewUDPv5Listener(ctx context.Context, cfg *P2PConfig, discCfg discover.Conf
7575
}
7676

7777
// Start stream handlers
78-
net, err := discover.ListenV5(ctx, "any", conn, localNode, discCfg)
78+
net, err := discover.ListenV5(conn, localNode, discCfg)
7979
if err != nil {
8080
return nil, err
8181
}

cl/sentinel/handlers/heartbeats_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ func newkey() *ecdsa.PrivateKey {
5959
}
6060

6161
func testLocalNode() *enode.LocalNode {
62-
db, err := enode.OpenDB(context.TODO(), "", "", log.Root())
62+
db, err := enode.OpenDBEx(context.TODO(), "", "", log.Root())
6363
if err != nil {
6464
panic(err)
6565
}
66-
ln := enode.NewLocalNode(db, newkey(), log.Root())
66+
ln := enode.NewLocalNode(db, newkey())
6767
ln.Set(enr.WithEntry("attnets", attnetsTestVal))
6868
ln.Set(enr.WithEntry("syncnets", syncnetsTestVal))
6969
return ln

cmd/bootnode/main.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,22 @@ func main() {
122122
ctx, cancel := common.RootContext()
123123
defer cancel()
124124

125-
db, err := enode.OpenDB(ctx, "" /* path */, "" /* tmpDir */, logger)
125+
db, err := enode.OpenDBEx(ctx, "" /* path */, "" /* tmpDir */, logger)
126126
if err != nil {
127127
panic(err)
128128
}
129-
ln := enode.NewLocalNode(db, nodeKey, logger)
129+
ln := enode.NewLocalNode(db, nodeKey)
130130
cfg := discover.Config{
131131
PrivateKey: nodeKey,
132132
NetRestrict: restrictList,
133133
}
134134

135135
if *runv5 {
136-
if _, err := discover.ListenV5(ctx, "any", conn, ln, cfg); err != nil {
136+
if _, err := discover.ListenV5(conn, ln, cfg); err != nil {
137137
utils.Fatalf("%v", err)
138138
}
139139
} else {
140-
if _, err := discover.ListenUDP(ctx, "any", conn, ln, cfg); err != nil {
140+
if _, err := discover.ListenUDP(conn, ln, cfg); err != nil {
141141
utils.Fatalf("%v", err)
142142
}
143143
}

cmd/integration/commands/commitment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ func benchHistoryLookup(ctx context.Context, logger log.Logger) error {
673673

674674
// benchSnapshotsHistoryLookup benchmarks history lookups across snapshot files
675675
func benchSnapshotsHistoryLookup(ctx context.Context, tx kv.TemporalTx, historyFiles []dbstate.VisibleFile, compactKey []byte, samplePct float64, rng *rand.Rand, logger log.Logger) ([]HistoryBenchStats, error) {
676-
var allFileStats []HistoryBenchStats
676+
allFileStats := make([]HistoryBenchStats, 0, len(historyFiles))
677677

678678
for _, f := range historyFiles {
679679
fpath := f.Fullpath()

cmd/utils/flags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ import (
4444
"github.com/erigontech/erigon/common"
4545
libkzg "github.com/erigontech/erigon/common/crypto/kzg"
4646
"github.com/erigontech/erigon/common/log/v3"
47-
"github.com/erigontech/erigon/common/metrics"
4847
"github.com/erigontech/erigon/db/datadir"
4948
"github.com/erigontech/erigon/db/downloader/downloadercfg"
5049
"github.com/erigontech/erigon/db/snapcfg"
5150
"github.com/erigontech/erigon/db/state/statecfg"
5251
"github.com/erigontech/erigon/db/version"
52+
"github.com/erigontech/erigon/diagnostics/metrics"
5353
"github.com/erigontech/erigon/execution/builder/buildercfg"
5454
"github.com/erigontech/erigon/execution/chain/networkname"
5555
chainspec "github.com/erigontech/erigon/execution/chain/spec"

common/crypto/crypto.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ var (
5858

5959
var errInvalidPubkey = errors.New("invalid secp256k1 public key")
6060

61+
// EllipticCurve contains curve operations.
62+
type EllipticCurve interface {
63+
elliptic.Curve
64+
65+
// Point marshaling/unmarshaing.
66+
Marshal(x, y *big.Int) []byte
67+
Unmarshal(data []byte) (x, y *big.Int)
68+
}
69+
6170
// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports
6271
// Read to get a variable amount of data from the hash state. Read is faster than Sum
6372
// because it doesn't copy the internal state, but also modifies the internal state.
@@ -204,6 +213,16 @@ func MarshalPubkey(pubkey *ecdsa.PublicKey) []byte {
204213
return keyBytes[1:]
205214
}
206215

216+
// FromECDSAPub converts a secp256k1 public key to bytes.
217+
// Note: it does not use the curve from pub, instead it always
218+
// encodes using secp256k1.
219+
func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
220+
if pub == nil || pub.X == nil || pub.Y == nil {
221+
return nil
222+
}
223+
return S256().Marshal(pub.X, pub.Y)
224+
}
225+
207226
// HexToECDSA parses a secp256k1 private key.
208227
func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) {
209228
b, err := hex.DecodeString(hexkey)

common/crypto/signature_cgo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,6 @@ func CompressPubkey(pubkey *ecdsa.PublicKey) []byte {
9292
}
9393

9494
// S256 returns an instance of the secp256k1 curve.
95-
func S256() elliptic.Curve {
95+
func S256() EllipticCurve {
9696
return secp256k1.S256()
9797
}

common/lru/basiclru.go

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// Copyright 2022 The go-ethereum Authors
2+
// (original work)
3+
// Copyright 2024 The Erigon Authors
4+
// (modifications)
5+
// This file is part of Erigon.
6+
//
7+
// Erigon is free software: you can redistribute it and/or modify
8+
// it under the terms of the GNU Lesser General Public License as published by
9+
// the Free Software Foundation, either version 3 of the License, or
10+
// (at your option) any later version.
11+
//
12+
// Erigon is distributed in the hope that it will be useful,
13+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
// GNU Lesser General Public License for more details.
16+
//
17+
// You should have received a copy of the GNU Lesser General Public License
18+
// along with Erigon. If not, see <http://www.gnu.org/licenses/>.
19+
20+
// Package lru implements generically-typed LRU caches.
21+
package lru
22+
23+
// BasicLRU is a simple LRU cache.
24+
//
25+
// This type is not safe for concurrent use.
26+
// The zero value is not valid, instances must be created using NewCache.
27+
type BasicLRU[K comparable, V any] struct {
28+
list *list[K]
29+
items map[K]cacheItem[K, V]
30+
cap int
31+
}
32+
33+
type cacheItem[K any, V any] struct {
34+
elem *listElem[K]
35+
value V
36+
}
37+
38+
// NewBasicLRU creates a new LRU cache.
39+
func NewBasicLRU[K comparable, V any](capacity int) BasicLRU[K, V] {
40+
if capacity <= 0 {
41+
capacity = 1
42+
}
43+
c := BasicLRU[K, V]{
44+
items: make(map[K]cacheItem[K, V]),
45+
list: newList[K](),
46+
cap: capacity,
47+
}
48+
return c
49+
}
50+
51+
// Add adds a value to the cache. Returns true if an item was evicted to store the new item.
52+
func (c *BasicLRU[K, V]) Add(key K, value V) (evicted bool) {
53+
_, _, evicted = c.Add3(key, value)
54+
return evicted
55+
}
56+
57+
// Add3 adds a value to the cache. If an item was evicted to store the new one, it returns the evicted item.
58+
func (c *BasicLRU[K, V]) Add3(key K, value V) (ek K, ev V, evicted bool) {
59+
item, ok := c.items[key]
60+
if ok {
61+
item.value = value
62+
c.items[key] = item
63+
c.list.moveToFront(item.elem)
64+
return ek, ev, false
65+
}
66+
67+
var elem *listElem[K]
68+
if c.Len() >= c.cap {
69+
elem = c.list.removeLast()
70+
evicted = true
71+
ek = elem.v
72+
ev = c.items[ek].value
73+
delete(c.items, ek)
74+
} else {
75+
elem = new(listElem[K])
76+
}
77+
78+
// Store the new item.
79+
// Note that if another item was evicted, we re-use its list element here.
80+
elem.v = key
81+
c.items[key] = cacheItem[K, V]{elem, value}
82+
c.list.pushElem(elem)
83+
return ek, ev, evicted
84+
}
85+
86+
// Contains reports whether the given key exists in the cache.
87+
func (c *BasicLRU[K, V]) Contains(key K) bool {
88+
_, ok := c.items[key]
89+
return ok
90+
}
91+
92+
// Get retrieves a value from the cache. This marks the key as recently used.
93+
func (c *BasicLRU[K, V]) Get(key K) (value V, ok bool) {
94+
item, ok := c.items[key]
95+
if !ok {
96+
return value, false
97+
}
98+
c.list.moveToFront(item.elem)
99+
return item.value, true
100+
}
101+
102+
// GetOldest retrieves the least-recently-used item.
103+
// Note that this does not update the item's recency.
104+
func (c *BasicLRU[K, V]) GetOldest() (key K, value V, ok bool) {
105+
lastElem := c.list.last()
106+
if lastElem == nil {
107+
return key, value, false
108+
}
109+
key = lastElem.v
110+
item := c.items[key]
111+
return key, item.value, true
112+
}
113+
114+
// Len returns the current number of items in the cache.
115+
func (c *BasicLRU[K, V]) Len() int {
116+
return len(c.items)
117+
}
118+
119+
// Peek retrieves a value from the cache, but does not mark the key as recently used.
120+
func (c *BasicLRU[K, V]) Peek(key K) (value V, ok bool) {
121+
item, ok := c.items[key]
122+
return item.value, ok
123+
}
124+
125+
// Purge empties the cache.
126+
func (c *BasicLRU[K, V]) Purge() {
127+
c.list.init()
128+
clear(c.items)
129+
}
130+
131+
// Remove drops an item from the cache. Returns true if the key was present in cache.
132+
func (c *BasicLRU[K, V]) Remove(key K) bool {
133+
item, ok := c.items[key]
134+
if ok {
135+
delete(c.items, key)
136+
c.list.remove(item.elem)
137+
}
138+
return ok
139+
}
140+
141+
// RemoveOldest drops the least recently used item.
142+
func (c *BasicLRU[K, V]) RemoveOldest() (key K, value V, ok bool) {
143+
lastElem := c.list.last()
144+
if lastElem == nil {
145+
return key, value, false
146+
}
147+
148+
key = lastElem.v
149+
item := c.items[key]
150+
delete(c.items, key)
151+
c.list.remove(lastElem)
152+
return key, item.value, true
153+
}
154+
155+
// Keys returns all keys in the cache.
156+
func (c *BasicLRU[K, V]) Keys() []K {
157+
keys := make([]K, 0, len(c.items))
158+
return c.list.appendTo(keys)
159+
}
160+
161+
// list is a doubly-linked list holding items of type he.
162+
// The zero value is not valid, use newList to create lists.
163+
type list[T any] struct {
164+
root listElem[T]
165+
}
166+
167+
type listElem[T any] struct {
168+
next *listElem[T]
169+
prev *listElem[T]
170+
v T
171+
}
172+
173+
func newList[T any]() *list[T] {
174+
l := new(list[T])
175+
l.init()
176+
return l
177+
}
178+
179+
// init reinitializes the list, making it empty.
180+
func (l *list[T]) init() {
181+
l.root.next = &l.root
182+
l.root.prev = &l.root
183+
}
184+
185+
// pushElem adds an element to the front of the list.
186+
func (l *list[T]) pushElem(e *listElem[T]) {
187+
e.prev = &l.root
188+
e.next = l.root.next
189+
l.root.next = e
190+
e.next.prev = e
191+
}
192+
193+
// moveToFront makes 'node' the head of the list.
194+
func (l *list[T]) moveToFront(e *listElem[T]) {
195+
e.prev.next = e.next
196+
e.next.prev = e.prev
197+
l.pushElem(e)
198+
}
199+
200+
// remove removes an element from the list.
201+
func (l *list[T]) remove(e *listElem[T]) {
202+
e.prev.next = e.next
203+
e.next.prev = e.prev
204+
e.next, e.prev = nil, nil
205+
}
206+
207+
// removeLast removes the last element of the list.
208+
func (l *list[T]) removeLast() *listElem[T] {
209+
last := l.last()
210+
if last != nil {
211+
l.remove(last)
212+
}
213+
return last
214+
}
215+
216+
// last returns the last element of the list, or nil if the list is empty.
217+
func (l *list[T]) last() *listElem[T] {
218+
e := l.root.prev
219+
if e == &l.root {
220+
return nil
221+
}
222+
return e
223+
}
224+
225+
// appendTo appends all list elements to a slice.
226+
func (l *list[T]) appendTo(slice []T) []T {
227+
for e := l.root.prev; e != &l.root; e = e.prev {
228+
slice = append(slice, e.v)
229+
}
230+
return slice
231+
}

0 commit comments

Comments
 (0)