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