-
Notifications
You must be signed in to change notification settings - Fork 20.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/utils: use eth DNS tree for snap discovery #22808
Changes from all commits
d460c68
e2c8716
c6ff4cd
29fed45
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,15 +32,17 @@ import ( | |
"github.com/ethereum/go-ethereum/p2p/enode" | ||
"github.com/ethereum/go-ethereum/p2p/enr" | ||
lru "github.com/hashicorp/golang-lru" | ||
"golang.org/x/sync/singleflight" | ||
"golang.org/x/time/rate" | ||
) | ||
|
||
// Client discovers nodes by querying DNS servers. | ||
type Client struct { | ||
cfg Config | ||
clock mclock.Clock | ||
entries *lru.Cache | ||
ratelimit *rate.Limiter | ||
cfg Config | ||
clock mclock.Clock | ||
entries *lru.Cache | ||
ratelimit *rate.Limiter | ||
singleflight singleflight.Group | ||
} | ||
|
||
// Config holds configuration options for the client. | ||
|
@@ -135,17 +137,20 @@ func (c *Client) NewIterator(urls ...string) (enode.Iterator, error) { | |
|
||
// resolveRoot retrieves a root entry via DNS. | ||
func (c *Client) resolveRoot(ctx context.Context, loc *linkEntry) (rootEntry, error) { | ||
txts, err := c.cfg.Resolver.LookupTXT(ctx, loc.domain) | ||
c.cfg.Logger.Trace("Updating DNS discovery root", "tree", loc.domain, "err", err) | ||
if err != nil { | ||
return rootEntry{}, err | ||
} | ||
for _, txt := range txts { | ||
if strings.HasPrefix(txt, rootPrefix) { | ||
return parseAndVerifyRoot(txt, loc) | ||
e, err, _ := c.singleflight.Do(loc.str, func() (interface{}, error) { | ||
txts, err := c.cfg.Resolver.LookupTXT(ctx, loc.domain) | ||
c.cfg.Logger.Trace("Updating DNS discovery root", "tree", loc.domain, "err", err) | ||
if err != nil { | ||
return rootEntry{}, err | ||
} | ||
} | ||
return rootEntry{}, nameError{loc.domain, errNoRoot} | ||
for _, txt := range txts { | ||
if strings.HasPrefix(txt, rootPrefix) { | ||
return parseAndVerifyRoot(txt, loc) | ||
} | ||
} | ||
return rootEntry{}, nameError{loc.domain, errNoRoot} | ||
}) | ||
return e.(rootEntry), err | ||
} | ||
|
||
func parseAndVerifyRoot(txt string, loc *linkEntry) (rootEntry, error) { | ||
|
@@ -168,17 +173,21 @@ func (c *Client) resolveEntry(ctx context.Context, domain, hash string) (entry, | |
if err := c.ratelimit.Wait(ctx); err != nil { | ||
return nil, err | ||
} | ||
|
||
cacheKey := truncateHash(hash) | ||
if e, ok := c.entries.Get(cacheKey); ok { | ||
return e.(entry), nil | ||
} | ||
e, err := c.doResolveEntry(ctx, domain, hash) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c.entries.Add(cacheKey, e) | ||
return e, nil | ||
|
||
ei, err, _ := c.singleflight.Do(cacheKey, func() (interface{}, error) { | ||
e, err := c.doResolveEntry(ctx, domain, hash) | ||
if err != nil { | ||
return nil, err | ||
} | ||
c.entries.Add(cacheKey, e) | ||
return e, nil | ||
}) | ||
e, _ := ei.(entry) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't this crash if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is why it uses the two-value type assertion. It would crash with |
||
return e, err | ||
} | ||
|
||
// doResolveEntry fetches an entry via DNS. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, is this safe if
eth.config.EthDiscoveryURLs
==[]
? Previously we had a special clause that returnednil, nil
for that, but here we're instantiating a random iterator even for no-urls. Just want a confirm that we won't spin loop shomewhere.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should be safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But let me try it anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested it, and there is no problem with empty list. The iterator is basically closed immediately.