github.com/ethereum/go-ethereum@v1.16.1/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 "errors" 21 "fmt" 22 "io" 23 "net" 24 "net/netip" 25 26 "github.com/ethereum/go-ethereum/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 // TCP6 is the "tcp6" key, which holds the IPv6-specific tcp6 port of the node. 66 type TCP6 uint16 67 68 func (v TCP6) ENRKey() string { return "tcp6" } 69 70 // UDP is the "udp" key, which holds the UDP port of the node. 71 type UDP uint16 72 73 func (v UDP) ENRKey() string { return "udp" } 74 75 // UDP6 is the "udp6" key, which holds the IPv6-specific UDP port of the node. 76 type UDP6 uint16 77 78 func (v UDP6) ENRKey() string { return "udp6" } 79 80 // QUIC is the "quic" key, which holds the QUIC port of the node. 81 type QUIC uint16 82 83 func (v QUIC) ENRKey() string { return "quic" } 84 85 // QUIC6 is the "quic6" key, which holds the IPv6-specific quic6 port of the node. 86 type QUIC6 uint16 87 88 func (v QUIC6) ENRKey() string { return "quic6" } 89 90 // ID is the "id" key, which holds the name of the identity scheme. 91 type ID string 92 93 const IDv4 = ID("v4") // the default identity scheme 94 95 func (v ID) ENRKey() string { return "id" } 96 97 // IP is either the "ip" or "ip6" key, depending on the value. 98 // Use this value to encode IP addresses that can be either v4 or v6. 99 // To load an address from a record use the IPv4 or IPv6 types. 100 type IP net.IP 101 102 func (v IP) ENRKey() string { 103 if net.IP(v).To4() == nil { 104 return "ip6" 105 } 106 return "ip" 107 } 108 109 // EncodeRLP implements rlp.Encoder. 110 func (v IP) EncodeRLP(w io.Writer) error { 111 if ip4 := net.IP(v).To4(); ip4 != nil { 112 return rlp.Encode(w, ip4) 113 } 114 if ip6 := net.IP(v).To16(); ip6 != nil { 115 return rlp.Encode(w, ip6) 116 } 117 return fmt.Errorf("invalid IP address: %v", net.IP(v)) 118 } 119 120 // DecodeRLP implements rlp.Decoder. 121 func (v *IP) DecodeRLP(s *rlp.Stream) error { 122 if err := s.Decode((*net.IP)(v)); err != nil { 123 return err 124 } 125 if len(*v) != 4 && len(*v) != 16 { 126 return fmt.Errorf("invalid IP address, want 4 or 16 bytes: %v", *v) 127 } 128 return nil 129 } 130 131 // IPv4 is the "ip" key, which holds the IP address of the node. 132 type IPv4 net.IP 133 134 func (v IPv4) ENRKey() string { return "ip" } 135 136 // EncodeRLP implements rlp.Encoder. 137 func (v IPv4) EncodeRLP(w io.Writer) error { 138 ip4 := net.IP(v).To4() 139 if ip4 == nil { 140 return fmt.Errorf("invalid IPv4 address: %v", net.IP(v)) 141 } 142 return rlp.Encode(w, ip4) 143 } 144 145 // DecodeRLP implements rlp.Decoder. 146 func (v *IPv4) DecodeRLP(s *rlp.Stream) error { 147 if err := s.Decode((*net.IP)(v)); err != nil { 148 return err 149 } 150 if len(*v) != 4 { 151 return fmt.Errorf("invalid IPv4 address, want 4 bytes: %v", *v) 152 } 153 return nil 154 } 155 156 // IPv6 is the "ip6" key, which holds the IP address of the node. 157 type IPv6 net.IP 158 159 func (v IPv6) ENRKey() string { return "ip6" } 160 161 // EncodeRLP implements rlp.Encoder. 162 func (v IPv6) EncodeRLP(w io.Writer) error { 163 ip6 := net.IP(v).To16() 164 if ip6 == nil { 165 return fmt.Errorf("invalid IPv6 address: %v", net.IP(v)) 166 } 167 return rlp.Encode(w, ip6) 168 } 169 170 // DecodeRLP implements rlp.Decoder. 171 func (v *IPv6) DecodeRLP(s *rlp.Stream) error { 172 if err := s.Decode((*net.IP)(v)); err != nil { 173 return err 174 } 175 if len(*v) != 16 { 176 return fmt.Errorf("invalid IPv6 address, want 16 bytes: %v", *v) 177 } 178 return nil 179 } 180 181 // IPv4Addr is the "ip" key, which holds the IP address of the node. 182 type IPv4Addr netip.Addr 183 184 func (v IPv4Addr) ENRKey() string { return "ip" } 185 186 // EncodeRLP implements rlp.Encoder. 187 func (v IPv4Addr) EncodeRLP(w io.Writer) error { 188 addr := netip.Addr(v) 189 if !addr.Is4() { 190 return errors.New("address is not IPv4") 191 } 192 enc := rlp.NewEncoderBuffer(w) 193 bytes := addr.As4() 194 enc.WriteBytes(bytes[:]) 195 return enc.Flush() 196 } 197 198 // DecodeRLP implements rlp.Decoder. 199 func (v *IPv4Addr) DecodeRLP(s *rlp.Stream) error { 200 var bytes [4]byte 201 if err := s.ReadBytes(bytes[:]); err != nil { 202 return err 203 } 204 *v = IPv4Addr(netip.AddrFrom4(bytes)) 205 return nil 206 } 207 208 // IPv6Addr is the "ip6" key, which holds the IP address of the node. 209 type IPv6Addr netip.Addr 210 211 func (v IPv6Addr) ENRKey() string { return "ip6" } 212 213 // EncodeRLP implements rlp.Encoder. 214 func (v IPv6Addr) EncodeRLP(w io.Writer) error { 215 addr := netip.Addr(v) 216 if !addr.Is6() { 217 return errors.New("address is not IPv6") 218 } 219 enc := rlp.NewEncoderBuffer(w) 220 bytes := addr.As16() 221 enc.WriteBytes(bytes[:]) 222 return enc.Flush() 223 } 224 225 // DecodeRLP implements rlp.Decoder. 226 func (v *IPv6Addr) DecodeRLP(s *rlp.Stream) error { 227 var bytes [16]byte 228 if err := s.ReadBytes(bytes[:]); err != nil { 229 return err 230 } 231 *v = IPv6Addr(netip.AddrFrom16(bytes)) 232 return nil 233 } 234 235 // KeyError is an error related to a key. 236 type KeyError struct { 237 Key string 238 Err error 239 } 240 241 // Error implements error. 242 func (err *KeyError) Error() string { 243 if err.Err == errNotFound { 244 return fmt.Sprintf("missing ENR key %q", err.Key) 245 } 246 return fmt.Sprintf("ENR key %q: %v", err.Key, err.Err) 247 } 248 249 func (err *KeyError) Unwrap() error { 250 return err.Err 251 } 252 253 // IsNotFound reports whether the given error means that a key/value pair is 254 // missing from a record. 255 func IsNotFound(err error) bool { 256 var ke *KeyError 257 if errors.As(err, &ke) { 258 return ke.Err == errNotFound 259 } 260 return false 261 }