@@ -49,7 +49,7 @@ func (t *Tree) Sign(key *ecdsa.PrivateKey, domain string) (url string, err error
4949 root .sig = sig
5050 t .root = & root
5151 link := & linkEntry {domain , & key .PublicKey }
52- return link .url (), nil
52+ return link .String (), nil
5353}
5454
5555// SetSignature verifies the given signature and assigns it as the tree's current
@@ -96,7 +96,7 @@ func (t *Tree) Links() []string {
9696 var links []string
9797 for _ , e := range t .entries {
9898 if le , ok := e .(* linkEntry ); ok {
99- links = append (links , le .url ())
99+ links = append (links , le .String ())
100100 }
101101 }
102102 return links
@@ -115,15 +115,15 @@ func (t *Tree) Nodes() []*enode.Node {
115115
116116const (
117117 hashAbbrev = 16
118- maxChildren = 300 / ( hashAbbrev * (13 / 8 ) )
118+ maxChildren = 300 / hashAbbrev * (13 / 8 )
119119 minHashLength = 12
120- rootPrefix = "enrtree-root=v1"
121120)
122121
123122// MakeTree creates a tree containing the given nodes and links.
124123func MakeTree (seq uint , nodes []* enode.Node , links []string ) (* Tree , error ) {
125124 // Sort records by ID and ensure all nodes have a valid record.
126125 records := make ([]* enode.Node , len (nodes ))
126+
127127 copy (records , nodes )
128128 sortByID (records )
129129 for _ , n := range records {
@@ -139,7 +139,7 @@ func MakeTree(seq uint, nodes []*enode.Node, links []string) (*Tree, error) {
139139 }
140140 linkEntries := make ([]entry , len (links ))
141141 for i , l := range links {
142- le , err := parseURL (l )
142+ le , err := parseLink (l )
143143 if err != nil {
144144 return nil , err
145145 }
@@ -166,7 +166,7 @@ func (t *Tree) build(entries []entry) entry {
166166 hashes [i ] = subdomain (e )
167167 t.entries [hashes [i ]] = e
168168 }
169- return & subtreeEntry {hashes }
169+ return & branchEntry {hashes }
170170 }
171171 var subtrees []entry
172172 for len (entries ) > 0 {
@@ -202,7 +202,7 @@ type (
202202 seq uint
203203 sig []byte
204204 }
205- subtreeEntry struct {
205+ branchEntry struct {
206206 children []string
207207 }
208208 enrEntry struct {
@@ -218,7 +218,14 @@ type (
218218
219219var (
220220 b32format = base32 .StdEncoding .WithPadding (base32 .NoPadding )
221- b64format = base64 .URLEncoding
221+ b64format = base64 .RawURLEncoding
222+ )
223+
224+ const (
225+ rootPrefix = "enrtree-root:v1"
226+ linkPrefix = "enrtree://"
227+ branchPrefix = "enrtree-branch:"
228+ enrPrefix = "enr:"
222229)
223230
224231func subdomain (e entry ) string {
@@ -242,37 +249,29 @@ func (e *rootEntry) verifySignature(pubkey *ecdsa.PublicKey) bool {
242249 return crypto .VerifySignature (crypto .FromECDSAPub (pubkey ), e .sigHash (), sig )
243250}
244251
245- func (e * subtreeEntry ) String () string {
246- return "enrtree=" + strings .Join (e .children , "," )
252+ func (e * branchEntry ) String () string {
253+ return branchPrefix + strings .Join (e .children , "," )
247254}
248255
249256func (e * enrEntry ) String () string {
250- enc , _ := rlp .EncodeToBytes (e .node .Record ())
251- return "enr=" + b64format .EncodeToString (enc )
257+ return e .node .String ()
252258}
253259
254260func (e * linkEntry ) String () string {
255- return "enrtree-link=" + e .link ()
256- }
257-
258- func (e * linkEntry ) url () string {
259- return "enrtree://" + e .link ()
260- }
261-
262- func (e * linkEntry ) link () string {
263- return fmt .Sprintf ("%s@%s" , b32format .EncodeToString (crypto .CompressPubkey (e .pubkey )), e .domain )
261+ pubkey := b32format .EncodeToString (crypto .CompressPubkey (e .pubkey ))
262+ return fmt .Sprintf ("%s%s@%s" , linkPrefix , pubkey , e .domain )
264263}
265264
266265// Entry Parsing
267266
268267func parseEntry (e string , validSchemes enr.IdentityScheme ) (entry , error ) {
269268 switch {
270- case strings .HasPrefix (e , "enrtree-link=" ):
271- return parseLink ( e [ 13 :] )
272- case strings .HasPrefix (e , "enrtree=" ):
273- return parseSubtree ( e [ 8 :] )
274- case strings .HasPrefix (e , "enr=" ):
275- return parseENR (e [ 4 :] , validSchemes )
269+ case strings .HasPrefix (e , linkPrefix ):
270+ return parseLinkEntry ( e )
271+ case strings .HasPrefix (e , branchPrefix ):
272+ return parseBranch ( e )
273+ case strings .HasPrefix (e , enrPrefix ):
274+ return parseENR (e , validSchemes )
276275 default :
277276 return nil , errUnknownEntry
278277 }
@@ -294,7 +293,19 @@ func parseRoot(e string) (rootEntry, error) {
294293 return rootEntry {eroot , lroot , seq , sigb }, nil
295294}
296295
297- func parseLink (e string ) (entry , error ) {
296+ func parseLinkEntry (e string ) (entry , error ) {
297+ le , err := parseLink (e )
298+ if err != nil {
299+ return nil , err
300+ }
301+ return le , nil
302+ }
303+
304+ func parseLink (e string ) (* linkEntry , error ) {
305+ if ! strings .HasPrefix (e , linkPrefix ) {
306+ return nil , fmt .Errorf ("wrong/missing scheme 'enrtree' in URL" )
307+ }
308+ e = e [len (linkPrefix ):]
298309 pos := strings .IndexByte (e , '@' )
299310 if pos == - 1 {
300311 return nil , entryError {"link" , errNoPubkey }
@@ -311,21 +322,23 @@ func parseLink(e string) (entry, error) {
311322 return & linkEntry {domain , key }, nil
312323}
313324
314- func parseSubtree (e string ) (entry , error ) {
325+ func parseBranch (e string ) (entry , error ) {
326+ e = e [len (branchPrefix ):]
315327 if e == "" {
316- return & subtreeEntry {}, nil // empty entry is OK
328+ return & branchEntry {}, nil // empty entry is OK
317329 }
318330 hashes := make ([]string , 0 , strings .Count (e , "," ))
319331 for _ , c := range strings .Split (e , "," ) {
320332 if ! isValidHash (c ) {
321- return nil , entryError {"subtree " , errInvalidChild }
333+ return nil , entryError {"branch " , errInvalidChild }
322334 }
323335 hashes = append (hashes , c )
324336 }
325- return & subtreeEntry {hashes }, nil
337+ return & branchEntry {hashes }, nil
326338}
327339
328340func parseENR (e string , validSchemes enr.IdentityScheme ) (entry , error ) {
341+ e = e [len (enrPrefix ):]
329342 enc , err := b64format .DecodeString (e )
330343 if err != nil {
331344 return nil , entryError {"enr" , errInvalidENR }
@@ -364,21 +377,9 @@ func truncateHash(hash string) string {
364377
365378// ParseURL parses an enrtree:// URL and returns its components.
366379func ParseURL (url string ) (domain string , pubkey * ecdsa.PublicKey , err error ) {
367- le , err := parseURL (url )
380+ le , err := parseLink (url )
368381 if err != nil {
369382 return "" , nil , err
370383 }
371384 return le .domain , le .pubkey , nil
372385}
373-
374- func parseURL (url string ) (* linkEntry , error ) {
375- const scheme = "enrtree://"
376- if ! strings .HasPrefix (url , scheme ) {
377- return nil , fmt .Errorf ("wrong/missing scheme 'enrtree' in URL" )
378- }
379- le , err := parseLink (url [len (scheme ):])
380- if err != nil {
381- return nil , err .(entryError ).err
382- }
383- return le .(* linkEntry ), nil
384- }
0 commit comments