p2p/dnsdisc: update to latest EIP-1459 spec (#20168)

This updates the DNS TXT record format to the latest
changes in ethereum/EIPs#2313.
This commit is contained in:
Felix Lange
2019-10-16 13:35:24 +02:00
committed by Péter Szilágyi
parent c476460cb2
commit 7300365956
5 changed files with 92 additions and 81 deletions

View File

@ -49,7 +49,7 @@ func (t *Tree) Sign(key *ecdsa.PrivateKey, domain string) (url string, err error
root.sig = sig
t.root = &root
link := &linkEntry{domain, &key.PublicKey}
return link.url(), nil
return link.String(), nil
}
// SetSignature verifies the given signature and assigns it as the tree's current
@ -96,7 +96,7 @@ func (t *Tree) Links() []string {
var links []string
for _, e := range t.entries {
if le, ok := e.(*linkEntry); ok {
links = append(links, le.url())
links = append(links, le.String())
}
}
return links
@ -115,15 +115,15 @@ func (t *Tree) Nodes() []*enode.Node {
const (
hashAbbrev = 16
maxChildren = 300 / (hashAbbrev * (13 / 8))
maxChildren = 300 / hashAbbrev * (13 / 8)
minHashLength = 12
rootPrefix = "enrtree-root=v1"
)
// MakeTree creates a tree containing the given nodes and links.
func MakeTree(seq uint, nodes []*enode.Node, links []string) (*Tree, error) {
// Sort records by ID and ensure all nodes have a valid record.
records := make([]*enode.Node, len(nodes))
copy(records, nodes)
sortByID(records)
for _, n := range records {
@ -139,7 +139,7 @@ func MakeTree(seq uint, nodes []*enode.Node, links []string) (*Tree, error) {
}
linkEntries := make([]entry, len(links))
for i, l := range links {
le, err := parseURL(l)
le, err := parseLink(l)
if err != nil {
return nil, err
}
@ -166,7 +166,7 @@ func (t *Tree) build(entries []entry) entry {
hashes[i] = subdomain(e)
t.entries[hashes[i]] = e
}
return &subtreeEntry{hashes}
return &branchEntry{hashes}
}
var subtrees []entry
for len(entries) > 0 {
@ -202,7 +202,7 @@ type (
seq uint
sig []byte
}
subtreeEntry struct {
branchEntry struct {
children []string
}
enrEntry struct {
@ -218,7 +218,14 @@ type (
var (
b32format = base32.StdEncoding.WithPadding(base32.NoPadding)
b64format = base64.URLEncoding
b64format = base64.RawURLEncoding
)
const (
rootPrefix = "enrtree-root:v1"
linkPrefix = "enrtree://"
branchPrefix = "enrtree-branch:"
enrPrefix = "enr:"
)
func subdomain(e entry) string {
@ -242,37 +249,29 @@ func (e *rootEntry) verifySignature(pubkey *ecdsa.PublicKey) bool {
return crypto.VerifySignature(crypto.FromECDSAPub(pubkey), e.sigHash(), sig)
}
func (e *subtreeEntry) String() string {
return "enrtree=" + strings.Join(e.children, ",")
func (e *branchEntry) String() string {
return branchPrefix + strings.Join(e.children, ",")
}
func (e *enrEntry) String() string {
enc, _ := rlp.EncodeToBytes(e.node.Record())
return "enr=" + b64format.EncodeToString(enc)
return e.node.String()
}
func (e *linkEntry) String() string {
return "enrtree-link=" + e.link()
}
func (e *linkEntry) url() string {
return "enrtree://" + e.link()
}
func (e *linkEntry) link() string {
return fmt.Sprintf("%s@%s", b32format.EncodeToString(crypto.CompressPubkey(e.pubkey)), e.domain)
pubkey := b32format.EncodeToString(crypto.CompressPubkey(e.pubkey))
return fmt.Sprintf("%s%s@%s", linkPrefix, pubkey, e.domain)
}
// Entry Parsing
func parseEntry(e string, validSchemes enr.IdentityScheme) (entry, error) {
switch {
case strings.HasPrefix(e, "enrtree-link="):
return parseLink(e[13:])
case strings.HasPrefix(e, "enrtree="):
return parseSubtree(e[8:])
case strings.HasPrefix(e, "enr="):
return parseENR(e[4:], validSchemes)
case strings.HasPrefix(e, linkPrefix):
return parseLinkEntry(e)
case strings.HasPrefix(e, branchPrefix):
return parseBranch(e)
case strings.HasPrefix(e, enrPrefix):
return parseENR(e, validSchemes)
default:
return nil, errUnknownEntry
}
@ -294,7 +293,19 @@ func parseRoot(e string) (rootEntry, error) {
return rootEntry{eroot, lroot, seq, sigb}, nil
}
func parseLink(e string) (entry, error) {
func parseLinkEntry(e string) (entry, error) {
le, err := parseLink(e)
if err != nil {
return nil, err
}
return le, nil
}
func parseLink(e string) (*linkEntry, error) {
if !strings.HasPrefix(e, linkPrefix) {
return nil, fmt.Errorf("wrong/missing scheme 'enrtree' in URL")
}
e = e[len(linkPrefix):]
pos := strings.IndexByte(e, '@')
if pos == -1 {
return nil, entryError{"link", errNoPubkey}
@ -311,21 +322,23 @@ func parseLink(e string) (entry, error) {
return &linkEntry{domain, key}, nil
}
func parseSubtree(e string) (entry, error) {
func parseBranch(e string) (entry, error) {
e = e[len(branchPrefix):]
if e == "" {
return &subtreeEntry{}, nil // empty entry is OK
return &branchEntry{}, nil // empty entry is OK
}
hashes := make([]string, 0, strings.Count(e, ","))
for _, c := range strings.Split(e, ",") {
if !isValidHash(c) {
return nil, entryError{"subtree", errInvalidChild}
return nil, entryError{"branch", errInvalidChild}
}
hashes = append(hashes, c)
}
return &subtreeEntry{hashes}, nil
return &branchEntry{hashes}, nil
}
func parseENR(e string, validSchemes enr.IdentityScheme) (entry, error) {
e = e[len(enrPrefix):]
enc, err := b64format.DecodeString(e)
if err != nil {
return nil, entryError{"enr", errInvalidENR}
@ -364,21 +377,9 @@ func truncateHash(hash string) string {
// ParseURL parses an enrtree:// URL and returns its components.
func ParseURL(url string) (domain string, pubkey *ecdsa.PublicKey, err error) {
le, err := parseURL(url)
le, err := parseLink(url)
if err != nil {
return "", nil, err
}
return le.domain, le.pubkey, nil
}
func parseURL(url string) (*linkEntry, error) {
const scheme = "enrtree://"
if !strings.HasPrefix(url, scheme) {
return nil, fmt.Errorf("wrong/missing scheme 'enrtree' in URL")
}
le, err := parseLink(url[len(scheme):])
if err != nil {
return nil, err.(entryError).err
}
return le.(*linkEntry), nil
}