enr.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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. "errors"
  31. "fmt"
  32. "io"
  33. "sort"
  34. "github.com/ethereum/go-ethereum/rlp"
  35. )
  36. const SizeLimit = 300 // maximum encoded size of a node record in bytes
  37. var (
  38. errNoID = errors.New("unknown or unspecified identity scheme")
  39. errInvalidSig = errors.New("invalid signature")
  40. errNotSorted = errors.New("record key/value pairs are not sorted by key")
  41. errDuplicateKey = errors.New("record contains duplicate key")
  42. errIncompletePair = errors.New("record contains incomplete k/v pair")
  43. errTooBig = fmt.Errorf("record bigger than %d bytes", SizeLimit)
  44. errEncodeUnsigned = errors.New("can't encode unsigned record")
  45. errNotFound = errors.New("no such key in record")
  46. )
  47. // Record represents a node record. The zero value is an empty record.
  48. type Record struct {
  49. seq uint64 // sequence number
  50. signature []byte // the signature
  51. raw []byte // RLP encoded record
  52. pairs []pair // sorted list of all key/value pairs
  53. }
  54. // pair is a key/value pair in a record.
  55. type pair struct {
  56. k string
  57. v rlp.RawValue
  58. }
  59. // Signed reports whether the record has a valid signature.
  60. func (r *Record) Signed() bool {
  61. return r.signature != nil
  62. }
  63. // Seq returns the sequence number.
  64. func (r *Record) Seq() uint64 {
  65. return r.seq
  66. }
  67. // SetSeq updates the record sequence number. This invalidates any signature on the record.
  68. // Calling SetSeq is usually not required because setting any key in a signed record
  69. // increments the sequence number.
  70. func (r *Record) SetSeq(s uint64) {
  71. r.signature = nil
  72. r.raw = nil
  73. r.seq = s
  74. }
  75. // Load retrieves the value of a key/value pair. The given Entry must be a pointer and will
  76. // be set to the value of the entry in the record.
  77. //
  78. // Errors returned by Load are wrapped in KeyError. You can distinguish decoding errors
  79. // from missing keys using the IsNotFound function.
  80. func (r *Record) Load(e Entry) error {
  81. i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= e.ENRKey() })
  82. if i < len(r.pairs) && r.pairs[i].k == e.ENRKey() {
  83. if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil {
  84. return &KeyError{Key: e.ENRKey(), Err: err}
  85. }
  86. return nil
  87. }
  88. return &KeyError{Key: e.ENRKey(), Err: errNotFound}
  89. }
  90. // Set adds or updates the given entry in the record. It panics if the value can't be
  91. // encoded. If the record is signed, Set increments the sequence number and invalidates
  92. // the sequence number.
  93. func (r *Record) Set(e Entry) {
  94. blob, err := rlp.EncodeToBytes(e)
  95. if err != nil {
  96. panic(fmt.Errorf("enr: can't encode %s: %v", e.ENRKey(), err))
  97. }
  98. r.invalidate()
  99. pairs := make([]pair, len(r.pairs))
  100. copy(pairs, r.pairs)
  101. i := sort.Search(len(pairs), func(i int) bool { return pairs[i].k >= e.ENRKey() })
  102. switch {
  103. case i < len(pairs) && pairs[i].k == e.ENRKey():
  104. // element is present at r.pairs[i]
  105. pairs[i].v = blob
  106. case i < len(r.pairs):
  107. // insert pair before i-th elem
  108. el := pair{e.ENRKey(), blob}
  109. pairs = append(pairs, pair{})
  110. copy(pairs[i+1:], pairs[i:])
  111. pairs[i] = el
  112. default:
  113. // element should be placed at the end of r.pairs
  114. pairs = append(pairs, pair{e.ENRKey(), blob})
  115. }
  116. r.pairs = pairs
  117. }
  118. func (r *Record) invalidate() {
  119. if r.signature == nil {
  120. r.seq++
  121. }
  122. r.signature = nil
  123. r.raw = nil
  124. }
  125. // EncodeRLP implements rlp.Encoder. Encoding fails if
  126. // the record is unsigned.
  127. func (r Record) EncodeRLP(w io.Writer) error {
  128. if !r.Signed() {
  129. return errEncodeUnsigned
  130. }
  131. _, err := w.Write(r.raw)
  132. return err
  133. }
  134. // DecodeRLP implements rlp.Decoder. Decoding verifies the signature.
  135. func (r *Record) DecodeRLP(s *rlp.Stream) error {
  136. raw, err := s.Raw()
  137. if err != nil {
  138. return err
  139. }
  140. if len(raw) > SizeLimit {
  141. return errTooBig
  142. }
  143. // Decode the RLP container.
  144. dec := Record{raw: raw}
  145. s = rlp.NewStream(bytes.NewReader(raw), 0)
  146. if _, err := s.List(); err != nil {
  147. return err
  148. }
  149. if err = s.Decode(&dec.signature); err != nil {
  150. return err
  151. }
  152. if err = s.Decode(&dec.seq); err != nil {
  153. return err
  154. }
  155. // The rest of the record contains sorted k/v pairs.
  156. var prevkey string
  157. for i := 0; ; i++ {
  158. var kv pair
  159. if err := s.Decode(&kv.k); err != nil {
  160. if err == rlp.EOL {
  161. break
  162. }
  163. return err
  164. }
  165. if err := s.Decode(&kv.v); err != nil {
  166. if err == rlp.EOL {
  167. return errIncompletePair
  168. }
  169. return err
  170. }
  171. if i > 0 {
  172. if kv.k == prevkey {
  173. return errDuplicateKey
  174. }
  175. if kv.k < prevkey {
  176. return errNotSorted
  177. }
  178. }
  179. dec.pairs = append(dec.pairs, kv)
  180. prevkey = kv.k
  181. }
  182. if err := s.ListEnd(); err != nil {
  183. return err
  184. }
  185. _, scheme := dec.idScheme()
  186. if scheme == nil {
  187. return errNoID
  188. }
  189. if err := scheme.Verify(&dec, dec.signature); err != nil {
  190. return err
  191. }
  192. *r = dec
  193. return nil
  194. }
  195. // NodeAddr returns the node address. The return value will be nil if the record is
  196. // unsigned or uses an unknown identity scheme.
  197. func (r *Record) NodeAddr() []byte {
  198. _, scheme := r.idScheme()
  199. if scheme == nil {
  200. return nil
  201. }
  202. return scheme.NodeAddr(r)
  203. }
  204. // SetSig sets the record signature. It returns an error if the encoded record is larger
  205. // than the size limit or if the signature is invalid according to the passed scheme.
  206. func (r *Record) SetSig(idscheme string, sig []byte) error {
  207. // Check that "id" is set and matches the given scheme. This panics because
  208. // inconsitencies here are always implementation bugs in the signing function calling
  209. // this method.
  210. id, s := r.idScheme()
  211. if s == nil {
  212. panic(errNoID)
  213. }
  214. if id != idscheme {
  215. panic(fmt.Errorf("identity scheme mismatch in Sign: record has %s, want %s", id, idscheme))
  216. }
  217. // Verify against the scheme.
  218. if err := s.Verify(r, sig); err != nil {
  219. return err
  220. }
  221. raw, err := r.encode(sig)
  222. if err != nil {
  223. return err
  224. }
  225. r.signature, r.raw = sig, raw
  226. return nil
  227. }
  228. // AppendElements appends the sequence number and entries to the given slice.
  229. func (r *Record) AppendElements(list []interface{}) []interface{} {
  230. list = append(list, r.seq)
  231. for _, p := range r.pairs {
  232. list = append(list, p.k, p.v)
  233. }
  234. return list
  235. }
  236. func (r *Record) encode(sig []byte) (raw []byte, err error) {
  237. list := make([]interface{}, 1, 2*len(r.pairs)+1)
  238. list[0] = sig
  239. list = r.AppendElements(list)
  240. if raw, err = rlp.EncodeToBytes(list); err != nil {
  241. return nil, err
  242. }
  243. if len(raw) > SizeLimit {
  244. return nil, errTooBig
  245. }
  246. return raw, nil
  247. }
  248. func (r *Record) idScheme() (string, IdentityScheme) {
  249. var id ID
  250. if err := r.Load(&id); err != nil {
  251. return "", nil
  252. }
  253. return string(id), FindIdentityScheme(string(id))
  254. }