enr.go 7.9 KB

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