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