github.com/luckypickle/go-ethereum-vet@v1.14.2/p2p/enr/enr.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 implements Ethereum Node Records as defined in EIP-778. A node record holds 18 // arbitrary information about a node on the peer-to-peer network. 19 // 20 // Records contain named keys. To store and retrieve key/values in a record, use the Entry 21 // interface. 22 // 23 // Records must be signed before transmitting them to another node. Decoding a record verifies 24 // its signature. When creating a record, set the entries you want, then call Sign to add the 25 // signature. Modifying a record invalidates the signature. 26 // 27 // Package enr supports the "secp256k1-keccak" identity scheme. 28 package enr 29 30 import ( 31 "bytes" 32 "errors" 33 "fmt" 34 "io" 35 "sort" 36 37 "github.com/luckypickle/go-ethereum-vet/rlp" 38 ) 39 40 const SizeLimit = 300 // maximum encoded size of a node record in bytes 41 42 var ( 43 errNoID = errors.New("unknown or unspecified identity scheme") 44 errInvalidSig = errors.New("invalid signature") 45 errNotSorted = errors.New("record key/value pairs are not sorted by key") 46 errDuplicateKey = errors.New("record contains duplicate key") 47 errIncompletePair = errors.New("record contains incomplete k/v pair") 48 errTooBig = fmt.Errorf("record bigger than %d bytes", SizeLimit) 49 errEncodeUnsigned = errors.New("can't encode unsigned record") 50 errNotFound = errors.New("no such key in record") 51 ) 52 53 // Record represents a node record. The zero value is an empty record. 54 type Record struct { 55 seq uint64 // sequence number 56 signature []byte // the signature 57 raw []byte // RLP encoded record 58 pairs []pair // sorted list of all key/value pairs 59 } 60 61 // pair is a key/value pair in a record. 62 type pair struct { 63 k string 64 v rlp.RawValue 65 } 66 67 // Signed reports whether the record has a valid signature. 68 func (r *Record) Signed() bool { 69 return r.signature != nil 70 } 71 72 // Seq returns the sequence number. 73 func (r *Record) Seq() uint64 { 74 return r.seq 75 } 76 77 // SetSeq updates the record sequence number. This invalidates any signature on the record. 78 // Calling SetSeq is usually not required because setting any key in a signed record 79 // increments the sequence number. 80 func (r *Record) SetSeq(s uint64) { 81 r.signature = nil 82 r.raw = nil 83 r.seq = s 84 } 85 86 // Load retrieves the value of a key/value pair. The given Entry must be a pointer and will 87 // be set to the value of the entry in the record. 88 // 89 // Errors returned by Load are wrapped in KeyError. You can distinguish decoding errors 90 // from missing keys using the IsNotFound function. 91 func (r *Record) Load(e Entry) error { 92 i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() }) 93 if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() { 94 if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil { 95 return &KeyError{Key: e.ENRKey(), Err: err} 96 } 97 return nil 98 } 99 return &KeyError{Key: e.ENRKey(), Err: errNotFound} 100 } 101 102 // Set adds or updates the given entry in the record. It panics if the value can't be 103 // encoded. If the record is signed, Set increments the sequence number and invalidates 104 // the sequence number. 105 func (r *Record) Set(e Entry) { 106 blob, err := rlp.EncodeToBytes(e) 107 if err != nil { 108 panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err)) 109 } 110 r.invalidate() 111 112 pairs := make([]pair, len(r.pairs)) 113 copy(pairs, r.pairs) 114 i := sort.Search(len(pairs), func(i int) bool { return pairs[i].k >= e.ENRKey() }) 115 switch { 116 case i < len(pairs) && pairs[i].k == e.ENRKey(): 117 // element is present at r.pairs[i] 118 pairs[i].v = blob 119 case i < len(r.pairs): 120 // insert pair before i-th elem 121 el := pair{e.ENRKey(), blob} 122 pairs = append(pairs, pair{}) 123 copy(pairs[i+1:], pairs[i:]) 124 pairs[i] = el 125 default: 126 // element should be placed at the end of r.pairs 127 pairs = append(pairs, pair{e.ENRKey(), blob}) 128 } 129 r.pairs = pairs 130 } 131 132 func (r *Record) invalidate() { 133 if r.signature == nil { 134 r.seq++ 135 } 136 r.signature = nil 137 r.raw = nil 138 } 139 140 // EncodeRLP implements rlp.Encoder. Encoding fails if 141 // the record is unsigned. 142 func (r Record) EncodeRLP(w io.Writer) error { 143 if !r.Signed() { 144 return errEncodeUnsigned 145 } 146 _, err := w.Write(r.raw) 147 return err 148 } 149 150 // DecodeRLP implements rlp.Decoder. Decoding verifies the signature. 151 func (r *Record) DecodeRLP(s *rlp.Stream) error { 152 raw, err := s.Raw() 153 if err != nil { 154 return err 155 } 156 if len(raw) > SizeLimit { 157 return errTooBig 158 } 159 160 // Decode the RLP container. 161 dec := Record{raw: raw} 162 s = rlp.NewStream(bytes.NewReader(raw), 0) 163 if _, err := s.List(); err != nil { 164 return err 165 } 166 if err = s.Decode(&dec.signature); err != nil { 167 return err 168 } 169 if err = s.Decode(&dec.seq); err != nil { 170 return err 171 } 172 // The rest of the record contains sorted k/v pairs. 173 var prevkey string 174 for i := 0; ; i++ { 175 var kv pair 176 if err := s.Decode(&kv.k); err != nil { 177 if err == rlp.EOL { 178 break 179 } 180 return err 181 } 182 if err := s.Decode(&kv.v); err != nil { 183 if err == rlp.EOL { 184 return errIncompletePair 185 } 186 return err 187 } 188 if i > 0 { 189 if kv.k == prevkey { 190 return errDuplicateKey 191 } 192 if kv.k < prevkey { 193 return errNotSorted 194 } 195 } 196 dec.pairs = append(dec.pairs, kv) 197 prevkey = kv.k 198 } 199 if err := s.ListEnd(); err != nil { 200 return err 201 } 202 203 _, scheme := dec.idScheme() 204 if scheme == nil { 205 return errNoID 206 } 207 if err := scheme.Verify(&dec, dec.signature); err != nil { 208 return err 209 } 210 *r = dec 211 return nil 212 } 213 214 // NodeAddr returns the node address. The return value will be nil if the record is 215 // unsigned or uses an unknown identity scheme. 216 func (r *Record) NodeAddr() []byte { 217 _, scheme := r.idScheme() 218 if scheme == nil { 219 return nil 220 } 221 return scheme.NodeAddr(r) 222 } 223 224 // SetSig sets the record signature. It returns an error if the encoded record is larger 225 // than the size limit or if the signature is invalid according to the passed scheme. 226 func (r *Record) SetSig(idscheme string, sig []byte) error { 227 // Check that "id" is set and matches the given scheme. This panics because 228 // inconsitencies here are always implementation bugs in the signing function calling 229 // this method. 230 id, s := r.idScheme() 231 if s == nil { 232 panic(errNoID) 233 } 234 if id != idscheme { 235 panic(fmt.Errorf("identity scheme mismatch in Sign: record has %s, want %s", id, idscheme)) 236 } 237 238 // Verify against the scheme. 239 if err := s.Verify(r, sig); err != nil { 240 return err 241 } 242 raw, err := r.encode(sig) 243 if err != nil { 244 return err 245 } 246 r.signature, r.raw = sig, raw 247 return nil 248 } 249 250 // AppendElements appends the sequence number and entries to the given slice. 251 func (r *Record) AppendElements(list []interface{}) []interface{} { 252 list = append(list, r.seq) 253 for _, p := range r.pairs { 254 list = append(list, p.k, p.v) 255 } 256 return list 257 } 258 259 func (r *Record) encode(sig []byte) (raw []byte, err error) { 260 list := make([]interface{}, 1, 2*len(r.pairs)+1) 261 list[0] = sig 262 list = r.AppendElements(list) 263 if raw, err = rlp.EncodeToBytes(list); err != nil { 264 return nil, err 265 } 266 if len(raw) > SizeLimit { 267 return nil, errTooBig 268 } 269 return raw, nil 270 } 271 272 func (r *Record) idScheme() (string, IdentityScheme) { 273 var id ID 274 if err := r.Load(&id); err != nil { 275 return "", nil 276 } 277 return string(id), FindIdentityScheme(string(id)) 278 }