v4wire.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // Copyright 2019 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 v4wire implements the Discovery v4 Wire Protocol.
  17. package v4wire
  18. import (
  19. "bytes"
  20. "crypto/ecdsa"
  21. "crypto/elliptic"
  22. "errors"
  23. "fmt"
  24. "math/big"
  25. "net"
  26. "time"
  27. "github.com/ethereum/go-ethereum/common/math"
  28. "github.com/ethereum/go-ethereum/crypto"
  29. "github.com/ethereum/go-ethereum/p2p/enode"
  30. "github.com/ethereum/go-ethereum/p2p/enr"
  31. "github.com/ethereum/go-ethereum/rlp"
  32. )
  33. // RPC packet types
  34. const (
  35. PingPacket = iota + 1 // zero is 'reserved'
  36. PongPacket
  37. FindnodePacket
  38. NeighborsPacket
  39. ENRRequestPacket
  40. ENRResponsePacket
  41. )
  42. // RPC request structures
  43. type (
  44. Ping struct {
  45. Version uint
  46. From, To Endpoint
  47. Expiration uint64
  48. // Ignore additional fields (for forward compatibility).
  49. Rest []rlp.RawValue `rlp:"tail"`
  50. }
  51. // Pong is the reply to ping.
  52. Pong struct {
  53. // This field should mirror the UDP envelope address
  54. // of the ping packet, which provides a way to discover the
  55. // the external address (after NAT).
  56. To Endpoint
  57. ReplyTok []byte // This contains the hash of the ping packet.
  58. Expiration uint64 // Absolute timestamp at which the packet becomes invalid.
  59. // Ignore additional fields (for forward compatibility).
  60. Rest []rlp.RawValue `rlp:"tail"`
  61. }
  62. // Findnode is a query for nodes close to the given target.
  63. Findnode struct {
  64. Target Pubkey
  65. Expiration uint64
  66. // Ignore additional fields (for forward compatibility).
  67. Rest []rlp.RawValue `rlp:"tail"`
  68. }
  69. // Neighbors is the reply to findnode.
  70. Neighbors struct {
  71. Nodes []Node
  72. Expiration uint64
  73. // Ignore additional fields (for forward compatibility).
  74. Rest []rlp.RawValue `rlp:"tail"`
  75. }
  76. // enrRequest queries for the remote node's record.
  77. ENRRequest struct {
  78. Expiration uint64
  79. // Ignore additional fields (for forward compatibility).
  80. Rest []rlp.RawValue `rlp:"tail"`
  81. }
  82. // enrResponse is the reply to enrRequest.
  83. ENRResponse struct {
  84. ReplyTok []byte // Hash of the enrRequest packet.
  85. Record enr.Record
  86. // Ignore additional fields (for forward compatibility).
  87. Rest []rlp.RawValue `rlp:"tail"`
  88. }
  89. )
  90. // This number is the maximum number of neighbor nodes in a Neigbors packet.
  91. const MaxNeighbors = 12
  92. // This code computes the MaxNeighbors constant value.
  93. // func init() {
  94. // var maxNeighbors int
  95. // p := Neighbors{Expiration: ^uint64(0)}
  96. // maxSizeNode := Node{IP: make(net.IP, 16), UDP: ^uint16(0), TCP: ^uint16(0)}
  97. // for n := 0; ; n++ {
  98. // p.Nodes = append(p.Nodes, maxSizeNode)
  99. // size, _, err := rlp.EncodeToReader(p)
  100. // if err != nil {
  101. // // If this ever happens, it will be caught by the unit tests.
  102. // panic("cannot encode: " + err.Error())
  103. // }
  104. // if headSize+size+1 >= 1280 {
  105. // maxNeighbors = n
  106. // break
  107. // }
  108. // }
  109. // fmt.Println("maxNeighbors", maxNeighbors)
  110. // }
  111. // Pubkey represents an encoded 64-byte secp256k1 public key.
  112. type Pubkey [64]byte
  113. // ID returns the node ID corresponding to the public key.
  114. func (e Pubkey) ID() enode.ID {
  115. return enode.ID(crypto.Keccak256Hash(e[:]))
  116. }
  117. // Node represents information about a node.
  118. type Node struct {
  119. IP net.IP // len 4 for IPv4 or 16 for IPv6
  120. UDP uint16 // for discovery protocol
  121. TCP uint16 // for RLPx protocol
  122. ID Pubkey
  123. }
  124. // Endpoint represents a network endpoint.
  125. type Endpoint struct {
  126. IP net.IP // len 4 for IPv4 or 16 for IPv6
  127. UDP uint16 // for discovery protocol
  128. TCP uint16 // for RLPx protocol
  129. }
  130. // NewEndpoint creates an endpoint.
  131. func NewEndpoint(addr *net.UDPAddr, tcpPort uint16) Endpoint {
  132. ip := net.IP{}
  133. if ip4 := addr.IP.To4(); ip4 != nil {
  134. ip = ip4
  135. } else if ip6 := addr.IP.To16(); ip6 != nil {
  136. ip = ip6
  137. }
  138. return Endpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort}
  139. }
  140. type Packet interface {
  141. // packet name and type for logging purposes.
  142. Name() string
  143. Kind() byte
  144. }
  145. func (req *Ping) Name() string { return "PING/v4" }
  146. func (req *Ping) Kind() byte { return PingPacket }
  147. func (req *Ping) ENRSeq() uint64 { return seqFromTail(req.Rest) }
  148. func (req *Pong) Name() string { return "PONG/v4" }
  149. func (req *Pong) Kind() byte { return PongPacket }
  150. func (req *Pong) ENRSeq() uint64 { return seqFromTail(req.Rest) }
  151. func (req *Findnode) Name() string { return "FINDNODE/v4" }
  152. func (req *Findnode) Kind() byte { return FindnodePacket }
  153. func (req *Neighbors) Name() string { return "NEIGHBORS/v4" }
  154. func (req *Neighbors) Kind() byte { return NeighborsPacket }
  155. func (req *ENRRequest) Name() string { return "ENRREQUEST/v4" }
  156. func (req *ENRRequest) Kind() byte { return ENRRequestPacket }
  157. func (req *ENRResponse) Name() string { return "ENRRESPONSE/v4" }
  158. func (req *ENRResponse) Kind() byte { return ENRResponsePacket }
  159. // Expired checks whether the given UNIX time stamp is in the past.
  160. func Expired(ts uint64) bool {
  161. return time.Unix(int64(ts), 0).Before(time.Now())
  162. }
  163. func seqFromTail(tail []rlp.RawValue) uint64 {
  164. if len(tail) == 0 {
  165. return 0
  166. }
  167. var seq uint64
  168. rlp.DecodeBytes(tail[0], &seq)
  169. return seq
  170. }
  171. // Encoder/decoder.
  172. const (
  173. macSize = 32
  174. sigSize = crypto.SignatureLength
  175. headSize = macSize + sigSize // space of packet frame data
  176. )
  177. var (
  178. ErrPacketTooSmall = errors.New("too small")
  179. ErrBadHash = errors.New("bad hash")
  180. ErrBadPoint = errors.New("invalid curve point")
  181. )
  182. var headSpace = make([]byte, headSize)
  183. // Decode reads a discovery v4 packet.
  184. func Decode(input []byte) (Packet, Pubkey, []byte, error) {
  185. if len(input) < headSize+1 {
  186. return nil, Pubkey{}, nil, ErrPacketTooSmall
  187. }
  188. hash, sig, sigdata := input[:macSize], input[macSize:headSize], input[headSize:]
  189. shouldhash := crypto.Keccak256(input[macSize:])
  190. if !bytes.Equal(hash, shouldhash) {
  191. return nil, Pubkey{}, nil, ErrBadHash
  192. }
  193. fromKey, err := recoverNodeKey(crypto.Keccak256(input[headSize:]), sig)
  194. if err != nil {
  195. return nil, fromKey, hash, err
  196. }
  197. var req Packet
  198. switch ptype := sigdata[0]; ptype {
  199. case PingPacket:
  200. req = new(Ping)
  201. case PongPacket:
  202. req = new(Pong)
  203. case FindnodePacket:
  204. req = new(Findnode)
  205. case NeighborsPacket:
  206. req = new(Neighbors)
  207. case ENRRequestPacket:
  208. req = new(ENRRequest)
  209. case ENRResponsePacket:
  210. req = new(ENRResponse)
  211. default:
  212. return nil, fromKey, hash, fmt.Errorf("unknown type: %d", ptype)
  213. }
  214. s := rlp.NewStream(bytes.NewReader(sigdata[1:]), 0)
  215. err = s.Decode(req)
  216. return req, fromKey, hash, err
  217. }
  218. // Encode encodes a discovery packet.
  219. func Encode(priv *ecdsa.PrivateKey, req Packet) (packet, hash []byte, err error) {
  220. b := new(bytes.Buffer)
  221. b.Write(headSpace)
  222. b.WriteByte(req.Kind())
  223. if err := rlp.Encode(b, req); err != nil {
  224. return nil, nil, err
  225. }
  226. packet = b.Bytes()
  227. sig, err := crypto.Sign(crypto.Keccak256(packet[headSize:]), priv)
  228. if err != nil {
  229. return nil, nil, err
  230. }
  231. copy(packet[macSize:], sig)
  232. // Add the hash to the front. Note: this doesn't protect the packet in any way.
  233. hash = crypto.Keccak256(packet[macSize:])
  234. copy(packet, hash)
  235. return packet, hash, nil
  236. }
  237. // recoverNodeKey computes the public key used to sign the given hash from the signature.
  238. func recoverNodeKey(hash, sig []byte) (key Pubkey, err error) {
  239. pubkey, err := crypto.Ecrecover(hash, sig)
  240. if err != nil {
  241. return key, err
  242. }
  243. copy(key[:], pubkey[1:])
  244. return key, nil
  245. }
  246. // EncodePubkey encodes a secp256k1 public key.
  247. func EncodePubkey(key *ecdsa.PublicKey) Pubkey {
  248. var e Pubkey
  249. math.ReadBits(key.X, e[:len(e)/2])
  250. math.ReadBits(key.Y, e[len(e)/2:])
  251. return e
  252. }
  253. // DecodePubkey reads an encoded secp256k1 public key.
  254. func DecodePubkey(curve elliptic.Curve, e Pubkey) (*ecdsa.PublicKey, error) {
  255. p := &ecdsa.PublicKey{Curve: curve, X: new(big.Int), Y: new(big.Int)}
  256. half := len(e) / 2
  257. p.X.SetBytes(e[:half])
  258. p.Y.SetBytes(e[half:])
  259. if !p.Curve.IsOnCurve(p.X, p.Y) {
  260. return nil, ErrBadPoint
  261. }
  262. return p, nil
  263. }