Skip to content
This repository was archived by the owner on Jun 6, 2025. It is now read-only.

Commit f0935e6

Browse files
p2p/discover: apply enr filtering in discovery phase, fix minor logic in doRevalidate (#480)
* p2p/discover: implement ENR node filtering (#1320) * p2p/discovery: add filter ENR counter metrics * p2p/discover: avoid adding node to table when ENR failed request * Limit number of goroutines for addSeenNode and addVerifiedNode for avoiding DDOS * closeWorkerTask Chan before closing table --------- Co-authored-by: Matus Kysel <[email protected]>
1 parent c5b128f commit f0935e6

File tree

12 files changed

+290
-73
lines changed

12 files changed

+290
-73
lines changed

cmd/bootnode/main.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,21 @@ import (
3535

3636
func main() {
3737
var (
38-
listenAddr = flag.String("addr", ":30301", "listen address")
39-
genKey = flag.String("genkey", "", "generate a node key")
40-
writeAddr = flag.Bool("writeaddress", false, "write out the node's public key and quit")
41-
nodeKeyFile = flag.String("nodekey", "", "private key filename")
42-
nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)")
43-
natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
44-
netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)")
45-
runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode")
46-
verbosity = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-5)")
47-
vmodule = flag.String("vmodule", "", "log verbosity pattern")
48-
49-
nodeKey *ecdsa.PrivateKey
50-
err error
38+
listenAddr = flag.String("addr", ":30301", "listen address")
39+
genKey = flag.String("genkey", "", "generate a node key")
40+
writeAddr = flag.Bool("writeaddress", false, "write out the node's public key and quit")
41+
nodeKeyFile = flag.String("nodekey", "", "private key filename")
42+
nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)")
43+
natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
44+
netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)")
45+
runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode")
46+
verbosity = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-5)")
47+
vmodule = flag.String("vmodule", "", "log verbosity pattern")
48+
networkFilter = flag.String("network", "", "<ronin-mainnet/ronin-testnet> filters nodes by eth ENR entry")
49+
50+
nodeKey *ecdsa.PrivateKey
51+
filterFunction discover.NodeFilterFunc
52+
err error
5153
)
5254
flag.Parse()
5355

@@ -86,6 +88,12 @@ func main() {
8688
}
8789
}
8890

91+
if *networkFilter != "" {
92+
if filterFunction, err = discover.ParseEthFilter(*networkFilter); err != nil {
93+
utils.Fatalf("-network: %v", err)
94+
}
95+
}
96+
8997
if *writeAddr {
9098
fmt.Printf("%x\n", crypto.FromECDSAPub(&nodeKey.PublicKey)[1:])
9199
os.Exit(0)
@@ -123,8 +131,9 @@ func main() {
123131
db, _ := enode.OpenDB("")
124132
ln := enode.NewLocalNode(db, nodeKey)
125133
cfg := discover.Config{
126-
PrivateKey: nodeKey,
127-
NetRestrict: restrictList,
134+
PrivateKey: nodeKey,
135+
NetRestrict: restrictList,
136+
FilterFunction: filterFunction,
128137
}
129138
if *runv5 {
130139
if _, err := discover.ListenV5(conn, ln, cfg); err != nil {

eth/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
639639
// Start implements node.Lifecycle, starting all internal goroutines needed by the
640640
// Ethereum protocol implementation.
641641
func (s *Ethereum) Start() error {
642+
eth.StartENRFilter(s.blockchain, s.p2pServer)
642643
eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode())
643644

644645
// Start the bloom bits servicing goroutines

eth/protocols/eth/discovery.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package eth
1919
import (
2020
"github.com/ethereum/go-ethereum/core"
2121
"github.com/ethereum/go-ethereum/core/forkid"
22+
"github.com/ethereum/go-ethereum/p2p"
2223
"github.com/ethereum/go-ethereum/p2p/enode"
2324
"github.com/ethereum/go-ethereum/rlp"
2425
)
@@ -57,6 +58,11 @@ func StartENRUpdater(chain *core.BlockChain, ln *enode.LocalNode) {
5758
}()
5859
}
5960

61+
func StartENRFilter(chain *core.BlockChain, p2p *p2p.Server) {
62+
forkFilter := forkid.NewFilter(chain)
63+
p2p.SetFilter(forkFilter)
64+
}
65+
6066
// currentENREntry constructs an `eth` ENR entry based on the current state of the chain.
6167
func currentENREntry(chain *core.BlockChain) *enrEntry {
6268
return &enrEntry{

p2p/discover/common.go

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ package discover
1818

1919
import (
2020
"crypto/ecdsa"
21+
"fmt"
2122
"net"
2223

2324
"github.com/ethereum/go-ethereum/common/mclock"
25+
"github.com/ethereum/go-ethereum/core/forkid"
2426
"github.com/ethereum/go-ethereum/log"
2527
"github.com/ethereum/go-ethereum/p2p/enode"
2628
"github.com/ethereum/go-ethereum/p2p/enr"
2729
"github.com/ethereum/go-ethereum/p2p/netutil"
30+
"github.com/ethereum/go-ethereum/params"
31+
"github.com/ethereum/go-ethereum/rlp"
2832
)
2933

3034
// UDPConn is a network connection on which discovery can operate.
@@ -35,18 +39,45 @@ type UDPConn interface {
3539
LocalAddr() net.Addr
3640
}
3741

42+
type NodeFilterFunc func(*enr.Record) bool
43+
44+
func ParseEthFilter(chain string) (NodeFilterFunc, error) {
45+
var filter forkid.Filter
46+
switch chain {
47+
case "ronin-mainnet":
48+
filter = forkid.NewStaticFilter(params.RoninMainnetChainConfig, params.RoninMainnetGenesisHash)
49+
case "ronin-testnet":
50+
filter = forkid.NewStaticFilter(params.RoninTestnetChainConfig, params.RoninTestnetGenesisHash)
51+
default:
52+
return nil, fmt.Errorf("unknown network %q", chain)
53+
}
54+
55+
f := func(r *enr.Record) bool {
56+
var eth struct {
57+
ForkID forkid.ID
58+
Tail []rlp.RawValue `rlp:"tail"`
59+
}
60+
if r.Load(enr.WithEntry("eth", &eth)) != nil {
61+
return false
62+
}
63+
return filter(eth.ForkID) == nil
64+
}
65+
return f, nil
66+
}
67+
3868
// Config holds settings for the discovery listener.
3969
type Config struct {
4070
// These settings are required and configure the UDP listener:
4171
PrivateKey *ecdsa.PrivateKey
4272

4373
// These settings are optional:
44-
NetRestrict *netutil.Netlist // list of allowed IP networks
45-
Bootnodes []*enode.Node // list of bootstrap nodes
46-
Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
47-
Log log.Logger // if set, log messages go here
48-
ValidSchemes enr.IdentityScheme // allowed identity schemes
49-
Clock mclock.Clock
74+
NetRestrict *netutil.Netlist // list of allowed IP networks
75+
Bootnodes []*enode.Node // list of bootstrap nodes
76+
Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
77+
Log log.Logger // if set, log messages go here
78+
ValidSchemes enr.IdentityScheme // allowed identity schemes
79+
Clock mclock.Clock
80+
FilterFunction NodeFilterFunc // function for filtering ENR entries
5081
}
5182

5283
func (cfg Config) withDefaults() Config {

p2p/discover/metrics.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,17 @@ const (
3030

3131
// egressMeterName is the prefix of the per-packet outbound metrics.
3232
egressMeterName = moduleName + "/egress"
33+
34+
// filterENRName is the prefix of the per-packet filter ENR metrics.
35+
filterEnrName = moduleName + "/filter/enr"
3336
)
3437

3538
var (
36-
bucketsCounter []metrics.Counter
37-
ingressTrafficMeter = metrics.NewRegisteredMeter(ingressMeterName, nil)
38-
egressTrafficMeter = metrics.NewRegisteredMeter(egressMeterName, nil)
39+
bucketsCounter []metrics.Counter
40+
ingressTrafficMeter = metrics.NewRegisteredMeter(ingressMeterName, nil)
41+
egressTrafficMeter = metrics.NewRegisteredMeter(egressMeterName, nil)
42+
filterEnrTotalCounter = metrics.NewRegisteredCounter(fmt.Sprintf("%s/total", filterEnrName), nil)
43+
filterEnrSuccessCounter = metrics.NewRegisteredCounter(fmt.Sprintf("%s/success", filterEnrName), nil)
3944
)
4045

4146
func init() {

0 commit comments

Comments
 (0)