github.com/clem109/go-ethereum@v1.8.3-0.20180316121352-fe6cf00f480a/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/ethereum/go-ethereum/crypto" 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 // DiscPort is the "discv5" key, which holds the UDP port for discovery v5. 61 type DiscPort uint16 62 63 func (v DiscPort) ENRKey() string { return "discv5" } 64 65 // ID is the "id" key, which holds the name of the identity scheme. 66 type ID string 67 68 func (v ID) ENRKey() string { return "id" } 69 70 // IP4 is the "ip4" key, which holds a 4-byte IPv4 address. 71 type IP4 net.IP 72 73 func (v IP4) ENRKey() string { return "ip4" } 74 75 // EncodeRLP implements rlp.Encoder. 76 func (v IP4) EncodeRLP(w io.Writer) error { 77 ip4 := net.IP(v).To4() 78 if ip4 == nil { 79 return fmt.Errorf("invalid IPv4 address: %v", v) 80 } 81 return rlp.Encode(w, ip4) 82 } 83 84 // DecodeRLP implements rlp.Decoder. 85 func (v *IP4) DecodeRLP(s *rlp.Stream) error { 86 if err := s.Decode((*net.IP)(v)); err != nil { 87 return err 88 } 89 if len(*v) != 4 { 90 return fmt.Errorf("invalid IPv4 address, want 4 bytes: %v", *v) 91 } 92 return nil 93 } 94 95 // IP6 is the "ip6" key, which holds a 16-byte IPv6 address. 96 type IP6 net.IP 97 98 func (v IP6) ENRKey() string { return "ip6" } 99 100 // EncodeRLP implements rlp.Encoder. 101 func (v IP6) EncodeRLP(w io.Writer) error { 102 ip6 := net.IP(v) 103 return rlp.Encode(w, ip6) 104 } 105 106 // DecodeRLP implements rlp.Decoder. 107 func (v *IP6) DecodeRLP(s *rlp.Stream) error { 108 if err := s.Decode((*net.IP)(v)); err != nil { 109 return err 110 } 111 if len(*v) != 16 { 112 return fmt.Errorf("invalid IPv6 address, want 16 bytes: %v", *v) 113 } 114 return nil 115 } 116 117 // Secp256k1 is the "secp256k1" key, which holds a public key. 118 type Secp256k1 ecdsa.PublicKey 119 120 func (v Secp256k1) ENRKey() string { return "secp256k1" } 121 122 // EncodeRLP implements rlp.Encoder. 123 func (v Secp256k1) EncodeRLP(w io.Writer) error { 124 return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v))) 125 } 126 127 // DecodeRLP implements rlp.Decoder. 128 func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { 129 buf, err := s.Bytes() 130 if err != nil { 131 return err 132 } 133 pk, err := crypto.DecompressPubkey(buf) 134 if err != nil { 135 return err 136 } 137 *v = (Secp256k1)(*pk) 138 return nil 139 } 140 141 // KeyError is an error related to a key. 142 type KeyError struct { 143 Key string 144 Err error 145 } 146 147 // Error implements error. 148 func (err *KeyError) Error() string { 149 if err.Err == errNotFound { 150 return fmt.Sprintf("missing ENR key %q", err.Key) 151 } 152 return fmt.Sprintf("ENR key %q: %v", err.Key, err.Err) 153 } 154 155 // IsNotFound reports whether the given error means that a key/value pair is 156 // missing from a record. 157 func IsNotFound(err error) bool { 158 kerr, ok := err.(*KeyError) 159 return ok && kerr.Err == errNotFound 160 }