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