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