protocol.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright 2016 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 les
  17. import (
  18. "crypto/ecdsa"
  19. "errors"
  20. "fmt"
  21. "io"
  22. "math/big"
  23. "github.com/ethereum/go-ethereum/common"
  24. "github.com/ethereum/go-ethereum/crypto"
  25. lpc "github.com/ethereum/go-ethereum/les/lespay/client"
  26. "github.com/ethereum/go-ethereum/p2p/enode"
  27. "github.com/ethereum/go-ethereum/rlp"
  28. )
  29. // Constants to match up protocol versions and messages
  30. const (
  31. lpv2 = 2
  32. lpv3 = 3
  33. lpv4 = 4
  34. )
  35. // Supported versions of the les protocol (first is primary)
  36. var (
  37. ClientProtocolVersions = []uint{lpv2, lpv3}
  38. ServerProtocolVersions = []uint{lpv2, lpv3}
  39. AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
  40. )
  41. // Number of implemented message corresponding to different protocol versions.
  42. var ProtocolLengths = map[uint]uint64{lpv2: 22, lpv3: 24, lpv4: 24}
  43. const (
  44. NetworkId = 1
  45. ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
  46. blockSafetyMargin = 4 // safety margin applied to block ranges specified relative to head block
  47. txIndexUnlimited = 0 // this value in the "recentTxLookup" handshake field means the entire tx index history is served
  48. txIndexDisabled = 1 // this value means tx index is not served at all
  49. txIndexRecentOffset = 1 // txIndexRecentOffset + N in the handshake field means then tx index of the last N blocks is supported
  50. )
  51. // les protocol message codes
  52. const (
  53. // Protocol messages inherited from LPV1
  54. StatusMsg = 0x00
  55. AnnounceMsg = 0x01
  56. GetBlockHeadersMsg = 0x02
  57. BlockHeadersMsg = 0x03
  58. GetBlockBodiesMsg = 0x04
  59. BlockBodiesMsg = 0x05
  60. GetReceiptsMsg = 0x06
  61. ReceiptsMsg = 0x07
  62. GetCodeMsg = 0x0a
  63. CodeMsg = 0x0b
  64. // Protocol messages introduced in LPV2
  65. GetProofsV2Msg = 0x0f
  66. ProofsV2Msg = 0x10
  67. GetHelperTrieProofsMsg = 0x11
  68. HelperTrieProofsMsg = 0x12
  69. SendTxV2Msg = 0x13
  70. GetTxStatusMsg = 0x14
  71. TxStatusMsg = 0x15
  72. // Protocol messages introduced in LPV3
  73. StopMsg = 0x16
  74. ResumeMsg = 0x17
  75. )
  76. type requestInfo struct {
  77. name string
  78. maxCount uint64
  79. refBasketFirst, refBasketRest float64
  80. }
  81. // reqMapping maps an LES request to one or two lespay service vector entries.
  82. // If rest != -1 and the request type is used with amounts larger than one then the
  83. // first one of the multi-request is mapped to first while the rest is mapped to rest.
  84. type reqMapping struct {
  85. first, rest int
  86. }
  87. var (
  88. // requests describes the available LES request types and their initializing amounts
  89. // in the lespay/client.ValueTracker reference basket. Initial values are estimates
  90. // based on the same values as the server's default cost estimates (reqAvgTimeCost).
  91. requests = map[uint64]requestInfo{
  92. GetBlockHeadersMsg: {"GetBlockHeaders", MaxHeaderFetch, 10, 1000},
  93. GetBlockBodiesMsg: {"GetBlockBodies", MaxBodyFetch, 1, 0},
  94. GetReceiptsMsg: {"GetReceipts", MaxReceiptFetch, 1, 0},
  95. GetCodeMsg: {"GetCode", MaxCodeFetch, 1, 0},
  96. GetProofsV2Msg: {"GetProofsV2", MaxProofsFetch, 10, 0},
  97. GetHelperTrieProofsMsg: {"GetHelperTrieProofs", MaxHelperTrieProofsFetch, 10, 100},
  98. SendTxV2Msg: {"SendTxV2", MaxTxSend, 1, 0},
  99. GetTxStatusMsg: {"GetTxStatus", MaxTxStatus, 10, 0},
  100. }
  101. requestList []lpc.RequestInfo
  102. requestMapping map[uint32]reqMapping
  103. )
  104. // init creates a request list and mapping between protocol message codes and lespay
  105. // service vector indices.
  106. func init() {
  107. requestMapping = make(map[uint32]reqMapping)
  108. for code, req := range requests {
  109. cost := reqAvgTimeCost[code]
  110. rm := reqMapping{len(requestList), -1}
  111. requestList = append(requestList, lpc.RequestInfo{
  112. Name: req.name + ".first",
  113. InitAmount: req.refBasketFirst,
  114. InitValue: float64(cost.baseCost + cost.reqCost),
  115. })
  116. if req.refBasketRest != 0 {
  117. rm.rest = len(requestList)
  118. requestList = append(requestList, lpc.RequestInfo{
  119. Name: req.name + ".rest",
  120. InitAmount: req.refBasketRest,
  121. InitValue: float64(cost.reqCost),
  122. })
  123. }
  124. requestMapping[uint32(code)] = rm
  125. }
  126. }
  127. type errCode int
  128. const (
  129. ErrMsgTooLarge = iota
  130. ErrDecode
  131. ErrInvalidMsgCode
  132. ErrProtocolVersionMismatch
  133. ErrNetworkIdMismatch
  134. ErrGenesisBlockMismatch
  135. ErrNoStatusMsg
  136. ErrExtraStatusMsg
  137. ErrSuspendedPeer
  138. ErrUselessPeer
  139. ErrRequestRejected
  140. ErrUnexpectedResponse
  141. ErrInvalidResponse
  142. ErrTooManyTimeouts
  143. ErrMissingKey
  144. ErrForkIDRejected
  145. )
  146. func (e errCode) String() string {
  147. return errorToString[int(e)]
  148. }
  149. // XXX change once legacy code is out
  150. var errorToString = map[int]string{
  151. ErrMsgTooLarge: "Message too long",
  152. ErrDecode: "Invalid message",
  153. ErrInvalidMsgCode: "Invalid message code",
  154. ErrProtocolVersionMismatch: "Protocol version mismatch",
  155. ErrNetworkIdMismatch: "NetworkId mismatch",
  156. ErrGenesisBlockMismatch: "Genesis block mismatch",
  157. ErrNoStatusMsg: "No status message",
  158. ErrExtraStatusMsg: "Extra status message",
  159. ErrSuspendedPeer: "Suspended peer",
  160. ErrRequestRejected: "Request rejected",
  161. ErrUnexpectedResponse: "Unexpected response",
  162. ErrInvalidResponse: "Invalid response",
  163. ErrTooManyTimeouts: "Too many request timeouts",
  164. ErrMissingKey: "Key missing from list",
  165. ErrForkIDRejected: "ForkID rejected",
  166. }
  167. // announceData is the network packet for the block announcements.
  168. type announceData struct {
  169. Hash common.Hash // Hash of one particular block being announced
  170. Number uint64 // Number of one particular block being announced
  171. Td *big.Int // Total difficulty of one particular block being announced
  172. ReorgDepth uint64
  173. Update keyValueList
  174. }
  175. // sanityCheck verifies that the values are reasonable, as a DoS protection
  176. func (a *announceData) sanityCheck() error {
  177. if tdlen := a.Td.BitLen(); tdlen > 100 {
  178. return fmt.Errorf("too large block TD: bitlen %d", tdlen)
  179. }
  180. return nil
  181. }
  182. // sign adds a signature to the block announcement by the given privKey
  183. func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
  184. rlp, _ := rlp.EncodeToBytes(blockInfo{a.Hash, a.Number, a.Td})
  185. sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
  186. a.Update = a.Update.add("sign", sig)
  187. }
  188. // checkSignature verifies if the block announcement has a valid signature by the given pubKey
  189. func (a *announceData) checkSignature(id enode.ID, update keyValueMap) error {
  190. var sig []byte
  191. if err := update.get("sign", &sig); err != nil {
  192. return err
  193. }
  194. rlp, _ := rlp.EncodeToBytes(blockInfo{a.Hash, a.Number, a.Td})
  195. recPubkey, err := crypto.SigToPub(crypto.Keccak256(rlp), sig)
  196. if err != nil {
  197. return err
  198. }
  199. if id == enode.PubkeyToIDV4(recPubkey) {
  200. return nil
  201. }
  202. return errors.New("wrong signature")
  203. }
  204. type blockInfo struct {
  205. Hash common.Hash // Hash of one particular block being announced
  206. Number uint64 // Number of one particular block being announced
  207. Td *big.Int // Total difficulty of one particular block being announced
  208. }
  209. // getBlockHeadersData represents a block header query.
  210. type getBlockHeadersData struct {
  211. Origin hashOrNumber // Block from which to retrieve headers
  212. Amount uint64 // Maximum number of headers to retrieve
  213. Skip uint64 // Blocks to skip between consecutive headers
  214. Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis)
  215. }
  216. // hashOrNumber is a combined field for specifying an origin block.
  217. type hashOrNumber struct {
  218. Hash common.Hash // Block hash from which to retrieve headers (excludes Number)
  219. Number uint64 // Block hash from which to retrieve headers (excludes Hash)
  220. }
  221. // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
  222. // two contained union fields.
  223. func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
  224. if hn.Hash == (common.Hash{}) {
  225. return rlp.Encode(w, hn.Number)
  226. }
  227. if hn.Number != 0 {
  228. return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
  229. }
  230. return rlp.Encode(w, hn.Hash)
  231. }
  232. // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
  233. // into either a block hash or a block number.
  234. func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
  235. _, size, _ := s.Kind()
  236. origin, err := s.Raw()
  237. if err == nil {
  238. switch {
  239. case size == 32:
  240. err = rlp.DecodeBytes(origin, &hn.Hash)
  241. case size <= 8:
  242. err = rlp.DecodeBytes(origin, &hn.Number)
  243. default:
  244. err = fmt.Errorf("invalid input size %d for origin", size)
  245. }
  246. }
  247. return err
  248. }
  249. // CodeData is the network response packet for a node data retrieval.
  250. type CodeData []struct {
  251. Value []byte
  252. }