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