github.com/bcnmy/go-ethereum@v1.10.27/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 25 "github.com/ethereum/go-ethereum/rlp" 26 ) 27 28 // Entry is implemented by known node record entry types. 29 // 30 // To define a new entry that is to be included in a node record, 31 // create a Go type that satisfies this interface. The type should 32 // also implement rlp.Decoder if additional checks are needed on the value. 33 type Entry interface { 34 ENRKey() string 35 } 36 37 type generic struct { 38 key string 39 value interface{} 40 } 41 42 func (g generic) ENRKey() string { return g.key } 43 44 func (g generic) EncodeRLP(w io.Writer) error { 45 return rlp.Encode(w, g.value) 46 } 47 48 func (g *generic) DecodeRLP(s *rlp.Stream) error { 49 return s.Decode(g.value) 50 } 51 52 // WithEntry wraps any value with a key name. It can be used to set and load arbitrary values 53 // in a record. The value v must be supported by rlp. To use WithEntry with Load, the value 54 // must be a pointer. 55 func WithEntry(k string, v interface{}) Entry { 56 return &generic{key: k, value: v} 57 } 58 59 // TCP is the "tcp" key, which holds the TCP port of the node. 60 type TCP uint16 61 62 func (v TCP) ENRKey() string { return "tcp" } 63 64 // UDP is the "udp" key, which holds the IPv6-specific UDP port of the node. 65 type TCP6 uint16 66 67 func (v TCP6) ENRKey() string { return "tcp6" } 68 69 // UDP is the "udp" key, which holds the UDP port of the node. 70 type UDP uint16 71 72 func (v UDP) ENRKey() string { return "udp" } 73 74 // UDP is the "udp" key, which holds the IPv6-specific UDP port of the node. 75 type UDP6 uint16 76 77 func (v UDP6) ENRKey() string { return "udp6" } 78 79 // ID is the "id" key, which holds the name of the identity scheme. 80 type ID string 81 82 const IDv4 = ID("v4") // the default identity scheme 83 84 func (v ID) ENRKey() string { return "id" } 85 86 // IP is either the "ip" or "ip6" key, depending on the value. 87 // Use this value to encode IP addresses that can be either v4 or v6. 88 // To load an address from a record use the IPv4 or IPv6 types. 89 type IP net.IP 90 91 func (v IP) ENRKey() string { 92 if net.IP(v).To4() == nil { 93 return "ip6" 94 } 95 return "ip" 96 } 97 98 // EncodeRLP implements rlp.Encoder. 99 func (v IP) EncodeRLP(w io.Writer) error { 100 if ip4 := net.IP(v).To4(); ip4 != nil { 101 return rlp.Encode(w, ip4) 102 } 103 if ip6 := net.IP(v).To16(); ip6 != nil { 104 return rlp.Encode(w, ip6) 105 } 106 return fmt.Errorf("invalid IP address: %v", net.IP(v)) 107 } 108 109 // DecodeRLP implements rlp.Decoder. 110 func (v *IP) DecodeRLP(s *rlp.Stream) error { 111 if err := s.Decode((*net.IP)(v)); err != nil { 112 return err 113 } 114 if len(*v) != 4 && len(*v) != 16 { 115 return fmt.Errorf("invalid IP address, want 4 or 16 bytes: %v", *v) 116 } 117 return nil 118 } 119 120 // IPv4 is the "ip" key, which holds the IP address of the node. 121 type IPv4 net.IP 122 123 func (v IPv4) ENRKey() string { return "ip" } 124 125 // EncodeRLP implements rlp.Encoder. 126 func (v IPv4) EncodeRLP(w io.Writer) error { 127 ip4 := net.IP(v).To4() 128 if ip4 == nil { 129 return fmt.Errorf("invalid IPv4 address: %v", net.IP(v)) 130 } 131 return rlp.Encode(w, ip4) 132 } 133 134 // DecodeRLP implements rlp.Decoder. 135 func (v *IPv4) DecodeRLP(s *rlp.Stream) error { 136 if err := s.Decode((*net.IP)(v)); err != nil { 137 return err 138 } 139 if len(*v) != 4 { 140 return fmt.Errorf("invalid IPv4 address, want 4 bytes: %v", *v) 141 } 142 return nil 143 } 144 145 // IPv6 is the "ip6" key, which holds the IP address of the node. 146 type IPv6 net.IP 147 148 func (v IPv6) ENRKey() string { return "ip6" } 149 150 // EncodeRLP implements rlp.Encoder. 151 func (v IPv6) EncodeRLP(w io.Writer) error { 152 ip6 := net.IP(v).To16() 153 if ip6 == nil { 154 return fmt.Errorf("invalid IPv6 address: %v", net.IP(v)) 155 } 156 return rlp.Encode(w, ip6) 157 } 158 159 // DecodeRLP implements rlp.Decoder. 160 func (v *IPv6) DecodeRLP(s *rlp.Stream) error { 161 if err := s.Decode((*net.IP)(v)); err != nil { 162 return err 163 } 164 if len(*v) != 16 { 165 return fmt.Errorf("invalid IPv6 address, want 16 bytes: %v", *v) 166 } 167 return nil 168 } 169 170 // KeyError is an error related to a key. 171 type KeyError struct { 172 Key string 173 Err error 174 } 175 176 // Error implements error. 177 func (err *KeyError) Error() string { 178 if err.Err == errNotFound { 179 return fmt.Sprintf("missing ENR key %q", err.Key) 180 } 181 return fmt.Sprintf("ENR key %q: %v", err.Key, err.Err) 182 } 183 184 func (err *KeyError) Unwrap() error { 185 return err.Err 186 } 187 188 // IsNotFound reports whether the given error means that a key/value pair is 189 // missing from a record. 190 func IsNotFound(err error) bool { 191 var ke *KeyError 192 if errors.As(err, &ke) { 193 return ke.Err == errNotFound 194 } 195 return false 196 }