github.com/theQRL/go-zond@v0.1.1/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. Node information is 19 // stored in key/value pairs. To store and retrieve key/values in a record, use the Entry 20 // interface. 21 // 22 // # Signature Handling 23 // 24 // Records must be signed before transmitting them to another node. 25 // 26 // Decoding a record doesn't check its signature. Code working with records from an 27 // untrusted source must always verify two things: that the record uses an identity scheme 28 // deemed secure, and that the signature is valid according to the declared scheme. 29 // 30 // When creating a record, set the entries you want and use a signing function provided by 31 // the identity scheme to add the signature. Modifying a record invalidates the signature. 32 // 33 // Package enr supports the "secp256k1-keccak" identity scheme. 34 package enr 35 36 import ( 37 "bytes" 38 "errors" 39 "fmt" 40 "io" 41 "sort" 42 43 "github.com/theQRL/go-zond/rlp" 44 ) 45 46 const SizeLimit = 300 // maximum encoded size of a node record in bytes 47 48 var ( 49 ErrInvalidSig = errors.New("invalid signature on node record") 50 errNotSorted = errors.New("record key/value pairs are not sorted by key") 51 errDuplicateKey = errors.New("record contains duplicate key") 52 errIncompletePair = errors.New("record contains incomplete k/v pair") 53 errIncompleteList = errors.New("record contains less than two list elements") 54 errTooBig = fmt.Errorf("record bigger than %d bytes", SizeLimit) 55 errEncodeUnsigned = errors.New("can't encode unsigned record") 56 errNotFound = errors.New("no such key in record") 57 ) 58 59 // An IdentityScheme is capable of verifying record signatures and 60 // deriving node addresses. 61 type IdentityScheme interface { 62 Verify(r *Record, sig []byte) error 63 NodeAddr(r *Record) []byte 64 } 65 66 // SchemeMap is a registry of named identity schemes. 67 type SchemeMap map[string]IdentityScheme 68 69 func (m SchemeMap) Verify(r *Record, sig []byte) error { 70 s := m[r.IdentityScheme()] 71 if s == nil { 72 return ErrInvalidSig 73 } 74 return s.Verify(r, sig) 75 } 76 77 func (m SchemeMap) NodeAddr(r *Record) []byte { 78 s := m[r.IdentityScheme()] 79 if s == nil { 80 return nil 81 } 82 return s.NodeAddr(r) 83 } 84 85 // Record represents a node record. The zero value is an empty record. 86 type Record struct { 87 seq uint64 // sequence number 88 signature []byte // the signature 89 raw []byte // RLP encoded record 90 pairs []pair // sorted list of all key/value pairs 91 } 92 93 // pair is a key/value pair in a record. 94 type pair struct { 95 k string 96 v rlp.RawValue 97 } 98 99 // Size returns the encoded size of the record. 100 func (r *Record) Size() uint64 { 101 if r.raw != nil { 102 return uint64(len(r.raw)) 103 } 104 return computeSize(r) 105 } 106 107 func computeSize(r *Record) uint64 { 108 size := uint64(rlp.IntSize(r.seq)) 109 size += rlp.BytesSize(r.signature) 110 for _, p := range r.pairs { 111 size += rlp.StringSize(p.k) 112 size += uint64(len(p.v)) 113 } 114 return rlp.ListSize(size) 115 } 116 117 // Seq returns the sequence number. 118 func (r *Record) Seq() uint64 { 119 return r.seq 120 } 121 122 // SetSeq updates the record sequence number. This invalidates any signature on the record. 123 // Calling SetSeq is usually not required because setting any key in a signed record 124 // increments the sequence number. 125 func (r *Record) SetSeq(s uint64) { 126 r.signature = nil 127 r.raw = nil 128 r.seq = s 129 } 130 131 // Load retrieves the value of a key/value pair. The given Entry must be a pointer and will 132 // be set to the value of the entry in the record. 133 // 134 // Errors returned by Load are wrapped in KeyError. You can distinguish decoding errors 135 // from missing keys using the IsNotFound function. 136 func (r *Record) Load(e Entry) error { 137 i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() }) 138 if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() { 139 if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil { 140 return &KeyError{Key: e.ENRKey(), Err: err} 141 } 142 return nil 143 } 144 return &KeyError{Key: e.ENRKey(), Err: errNotFound} 145 } 146 147 // Set adds or updates the given entry in the record. It panics if the value can't be 148 // encoded. If the record is signed, Set increments the sequence number and invalidates 149 // the sequence number. 150 func (r *Record) Set(e Entry) { 151 blob, err := rlp.EncodeToBytes(e) 152 if err != nil { 153 panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err)) 154 } 155 r.invalidate() 156 157 pairs := make([]pair, len(r.pairs)) 158 copy(pairs, r.pairs) 159 i := sort.Search(len(pairs), func(i int) bool { return pairs[i].k >= e.ENRKey() }) 160 switch { 161 case i < len(pairs) && pairs[i].k == e.ENRKey(): 162 // element is present at r.pairs[i] 163 pairs[i].v = blob 164 case i < len(r.pairs): 165 // insert pair before i-th elem 166 el := pair{e.ENRKey(), blob} 167 pairs = append(pairs, pair{}) 168 copy(pairs[i+1:], pairs[i:]) 169 pairs[i] = el 170 default: 171 // element should be placed at the end of r.pairs 172 pairs = append(pairs, pair{e.ENRKey(), blob}) 173 } 174 r.pairs = pairs 175 } 176 177 func (r *Record) invalidate() { 178 if r.signature != nil { 179 r.seq++ 180 } 181 r.signature = nil 182 r.raw = nil 183 } 184 185 // Signature returns the signature of the record. 186 func (r *Record) Signature() []byte { 187 if r.signature == nil { 188 return nil 189 } 190 cpy := make([]byte, len(r.signature)) 191 copy(cpy, r.signature) 192 return cpy 193 } 194 195 // EncodeRLP implements rlp.Encoder. Encoding fails if 196 // the record is unsigned. 197 func (r Record) EncodeRLP(w io.Writer) error { 198 if r.signature == nil { 199 return errEncodeUnsigned 200 } 201 _, err := w.Write(r.raw) 202 return err 203 } 204 205 // DecodeRLP implements rlp.Decoder. Decoding doesn't verify the signature. 206 func (r *Record) DecodeRLP(s *rlp.Stream) error { 207 dec, raw, err := decodeRecord(s) 208 if err != nil { 209 return err 210 } 211 *r = dec 212 r.raw = raw 213 return nil 214 } 215 216 func decodeRecord(s *rlp.Stream) (dec Record, raw []byte, err error) { 217 raw, err = s.Raw() 218 if err != nil { 219 return dec, raw, err 220 } 221 if len(raw) > SizeLimit { 222 return dec, raw, errTooBig 223 } 224 225 // Decode the RLP container. 226 s = rlp.NewStream(bytes.NewReader(raw), 0) 227 if _, err := s.List(); err != nil { 228 return dec, raw, err 229 } 230 if err = s.Decode(&dec.signature); err != nil { 231 if err == rlp.EOL { 232 err = errIncompleteList 233 } 234 return dec, raw, err 235 } 236 if err = s.Decode(&dec.seq); err != nil { 237 if err == rlp.EOL { 238 err = errIncompleteList 239 } 240 return dec, raw, err 241 } 242 // The rest of the record contains sorted k/v pairs. 243 var prevkey string 244 for i := 0; ; i++ { 245 var kv pair 246 if err := s.Decode(&kv.k); err != nil { 247 if err == rlp.EOL { 248 break 249 } 250 return dec, raw, err 251 } 252 if err := s.Decode(&kv.v); err != nil { 253 if err == rlp.EOL { 254 return dec, raw, errIncompletePair 255 } 256 return dec, raw, err 257 } 258 if i > 0 { 259 if kv.k == prevkey { 260 return dec, raw, errDuplicateKey 261 } 262 if kv.k < prevkey { 263 return dec, raw, errNotSorted 264 } 265 } 266 dec.pairs = append(dec.pairs, kv) 267 prevkey = kv.k 268 } 269 return dec, raw, s.ListEnd() 270 } 271 272 // IdentityScheme returns the name of the identity scheme in the record. 273 func (r *Record) IdentityScheme() string { 274 var id ID 275 r.Load(&id) 276 return string(id) 277 } 278 279 // VerifySignature checks whether the record is signed using the given identity scheme. 280 func (r *Record) VerifySignature(s IdentityScheme) error { 281 return s.Verify(r, r.signature) 282 } 283 284 // SetSig sets the record signature. It returns an error if the encoded record is larger 285 // than the size limit or if the signature is invalid according to the passed scheme. 286 // 287 // You can also use SetSig to remove the signature explicitly by passing a nil scheme 288 // and signature. 289 // 290 // SetSig panics when either the scheme or the signature (but not both) are nil. 291 func (r *Record) SetSig(s IdentityScheme, sig []byte) error { 292 switch { 293 // Prevent storing invalid data. 294 case s == nil && sig != nil: 295 panic("enr: invalid call to SetSig with non-nil signature but nil scheme") 296 case s != nil && sig == nil: 297 panic("enr: invalid call to SetSig with nil signature but non-nil scheme") 298 // Verify if we have a scheme. 299 case s != nil: 300 if err := s.Verify(r, sig); err != nil { 301 return err 302 } 303 raw, err := r.encode(sig) 304 if err != nil { 305 return err 306 } 307 r.signature, r.raw = sig, raw 308 // Reset otherwise. 309 default: 310 r.signature, r.raw = nil, nil 311 } 312 return nil 313 } 314 315 // AppendElements appends the sequence number and entries to the given slice. 316 func (r *Record) AppendElements(list []interface{}) []interface{} { 317 list = append(list, r.seq) 318 for _, p := range r.pairs { 319 list = append(list, p.k, p.v) 320 } 321 return list 322 } 323 324 func (r *Record) encode(sig []byte) (raw []byte, err error) { 325 list := make([]interface{}, 1, 2*len(r.pairs)+2) 326 list[0] = sig 327 list = r.AppendElements(list) 328 if raw, err = rlp.EncodeToBytes(list); err != nil { 329 return nil, err 330 } 331 if len(raw) > SizeLimit { 332 return nil, errTooBig 333 } 334 return raw, nil 335 }