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