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