github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/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 INT Chain 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/intfoundation/intchain/crypto" 39 "github.com/intfoundation/intchain/rlp" 40 "golang.org/x/crypto/sha3" 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 if _, err := s.List(); err != nil { 161 return err 162 } 163 if err = s.Decode(&dec.signature); err != nil { 164 return err 165 } 166 if err = s.Decode(&dec.seq); err != nil { 167 return err 168 } 169 // The rest of the record contains sorted k/v pairs. 170 var prevkey string 171 for i := 0; ; i++ { 172 var kv pair 173 if err := s.Decode(&kv.k); err != nil { 174 if err == rlp.EOL { 175 break 176 } 177 return err 178 } 179 if err := s.Decode(&kv.v); err != nil { 180 if err == rlp.EOL { 181 return errIncompletePair 182 } 183 return err 184 } 185 if i > 0 { 186 if kv.k == prevkey { 187 return errDuplicateKey 188 } 189 if kv.k < prevkey { 190 return errNotSorted 191 } 192 } 193 dec.pairs = append(dec.pairs, kv) 194 prevkey = kv.k 195 } 196 if err := s.ListEnd(); err != nil { 197 return err 198 } 199 200 // Verify signature. 201 if err = dec.verifySignature(); err != nil { 202 return err 203 } 204 *r = dec 205 return nil 206 } 207 208 type s256raw []byte 209 210 func (s256raw) ENRKey() string { return "secp256k1" } 211 212 // NodeAddr returns the node address. The return value will be nil if the record is 213 // unsigned. 214 func (r *Record) NodeAddr() []byte { 215 var entry s256raw 216 if r.Load(&entry) != nil { 217 return nil 218 } 219 return crypto.Keccak256(entry) 220 } 221 222 // Sign signs the record with the given private key. It updates the record's identity 223 // scheme, public key and increments the sequence number. Sign returns an error if the 224 // encoded record is larger than the size limit. 225 func (r *Record) Sign(privkey *ecdsa.PrivateKey) error { 226 r.seq = r.seq + 1 227 r.Set(ID_SECP256k1_KECCAK) 228 r.Set(Secp256k1(privkey.PublicKey)) 229 return r.signAndEncode(privkey) 230 } 231 232 func (r *Record) appendPairs(list []interface{}) []interface{} { 233 list = append(list, r.seq) 234 for _, p := range r.pairs { 235 list = append(list, p.k, p.v) 236 } 237 return list 238 } 239 240 func (r *Record) signAndEncode(privkey *ecdsa.PrivateKey) error { 241 // Put record elements into a flat list. Leave room for the signature. 242 list := make([]interface{}, 1, len(r.pairs)*2+2) 243 list = r.appendPairs(list) 244 245 // Sign the tail of the list. 246 h := sha3.NewLegacyKeccak256() 247 rlp.Encode(h, list[1:]) 248 sig, err := crypto.Sign(h.Sum(nil), privkey) 249 if err != nil { 250 return err 251 } 252 sig = sig[:len(sig)-1] // remove v 253 254 // Put signature in front. 255 r.signature, list[0] = sig, sig 256 r.raw, err = rlp.EncodeToBytes(list) 257 if err != nil { 258 return err 259 } 260 if len(r.raw) > SizeLimit { 261 return errTooBig 262 } 263 return nil 264 } 265 266 func (r *Record) verifySignature() error { 267 // Get identity scheme, public key, signature. 268 var id ID 269 var entry s256raw 270 if err := r.Load(&id); err != nil { 271 return err 272 } else if id != ID_SECP256k1_KECCAK { 273 return errNoID 274 } 275 if err := r.Load(&entry); err != nil { 276 return err 277 } else if len(entry) != 33 { 278 return fmt.Errorf("invalid public key") 279 } 280 281 // Verify the signature. 282 list := make([]interface{}, 0, len(r.pairs)*2+1) 283 list = r.appendPairs(list) 284 h := sha3.NewLegacyKeccak256() 285 rlp.Encode(h, list) 286 if !crypto.VerifySignature(entry, h.Sum(nil), r.signature) { 287 return errInvalidSig 288 } 289 return nil 290 }