github.com/luckypickle/go-ethereum-vet@v1.14.2/p2p/enr/entries.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package enr 18 19 import ( 20 "crypto/ecdsa" 21 "fmt" 22 "io" 23 "net" 24 25 "github.com/luckypickle/go-ethereum-vet/crypto" 26 "github.com/luckypickle/go-ethereum-vet/rlp" 27 ) 28 29 // Entry is implemented by known node record entry types. 30 // 31 // To define a new entry that is to be included in a node record, 32 // create a Go type that satisfies this interface. The type should 33 // also implement rlp.Decoder if additional checks are needed on the value. 34 type Entry interface { 35 ENRKey() string 36 } 37 38 type generic struct { 39 key string 40 value interface{} 41 } 42 43 func (g generic) ENRKey() string { return g.key } 44 45 func (g generic) EncodeRLP(w io.Writer) error { 46 return rlp.Encode(w, g.value) 47 } 48 49 func (g *generic) DecodeRLP(s *rlp.Stream) error { 50 return s.Decode(g.value) 51 } 52 53 // WithEntry wraps any value with a key name. It can be used to set and load arbitrary values 54 // in a record. The value v must be supported by rlp. To use WithEntry with Load, the value 55 // must be a pointer. 56 func WithEntry(k string, v interface{}) Entry { 57 return &generic{key: k, value: v} 58 } 59 60 // TCP is the "tcp" key, which holds the TCP port of the node. 61 type TCP uint16 62 63 func (v TCP) ENRKey() string { return "tcp" } 64 65 // UDP is the "udp" key, which holds the UDP port of the node. 66 type UDP uint16 67 68 func (v UDP) ENRKey() string { return "udp" } 69 70 // ID is the "id" key, which holds the name of the identity scheme. 71 type ID string 72 73 const IDv4 = ID("v4") // the default identity scheme 74 75 func (v ID) ENRKey() string { return "id" } 76 77 // IP is the "ip" key, which holds the IP address of the node. 78 type IP net.IP 79 80 func (v IP) ENRKey() string { return "ip" } 81 82 // EncodeRLP implements rlp.Encoder. 83 func (v IP) EncodeRLP(w io.Writer) error { 84 if ip4 := net.IP(v).To4(); ip4 != nil { 85 return rlp.Encode(w, ip4) 86 } 87 return rlp.Encode(w, net.IP(v)) 88 } 89 90 // DecodeRLP implements rlp.Decoder. 91 func (v *IP) DecodeRLP(s *rlp.Stream) error { 92 if err := s.Decode((*net.IP)(v)); err != nil { 93 return err 94 } 95 if len(*v) != 4 && len(*v) != 16 { 96 return fmt.Errorf("invalid IP address, want 4 or 16 bytes: %v", *v) 97 } 98 return nil 99 } 100 101 // Secp256k1 is the "secp256k1" key, which holds a public key. 102 type Secp256k1 ecdsa.PublicKey 103 104 func (v Secp256k1) ENRKey() string { return "secp256k1" } 105 106 // EncodeRLP implements rlp.Encoder. 107 func (v Secp256k1) EncodeRLP(w io.Writer) error { 108 return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v))) 109 } 110 111 // DecodeRLP implements rlp.Decoder. 112 func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { 113 buf, err := s.Bytes() 114 if err != nil { 115 return err 116 } 117 pk, err := crypto.DecompressPubkey(buf) 118 if err != nil { 119 return err 120 } 121 *v = (Secp256k1)(*pk) 122 return nil 123 } 124 125 // KeyError is an error related to a key. 126 type KeyError struct { 127 Key string 128 Err error 129 } 130 131 // Error implements error. 132 func (err *KeyError) Error() string { 133 if err.Err == errNotFound { 134 return fmt.Sprintf("missing ENR key %q", err.Key) 135 } 136 return fmt.Sprintf("ENR key %q: %v", err.Key, err.Err) 137 } 138 139 // IsNotFound reports whether the given error means that a key/value pair is 140 // missing from a record. 141 func IsNotFound(err error) bool { 142 kerr, ok := err.(*KeyError) 143 return ok && kerr.Err == errNotFound 144 }