protocol.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. "github.com/ethereum/go-ethereum/p2p/enode"
  26. "github.com/ethereum/go-ethereum/rlp"
  27. )
  28. // Constants to match up protocol versions and messages
  29. const (
  30. lpv2 = 2
  31. lpv3 = 3
  32. )
  33. // Supported versions of the les protocol (first is primary)
  34. var (
  35. ClientProtocolVersions = []uint{lpv2, lpv3}
  36. ServerProtocolVersions = []uint{lpv2, lpv3}
  37. AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
  38. )
  39. // Number of implemented message corresponding to different protocol versions.
  40. var ProtocolLengths = map[uint]uint64{lpv2: 22, lpv3: 24}
  41. const (
  42. NetworkId = 1
  43. ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
  44. )
  45. // les protocol message codes
  46. const (
  47. // Protocol messages inherited from LPV1
  48. StatusMsg = 0x00
  49. AnnounceMsg = 0x01
  50. GetBlockHeadersMsg = 0x02
  51. BlockHeadersMsg = 0x03
  52. GetBlockBodiesMsg = 0x04
  53. BlockBodiesMsg = 0x05
  54. GetReceiptsMsg = 0x06
  55. ReceiptsMsg = 0x07
  56. GetCodeMsg = 0x0a
  57. CodeMsg = 0x0b
  58. // Protocol messages introduced in LPV2
  59. GetProofsV2Msg = 0x0f
  60. ProofsV2Msg = 0x10
  61. GetHelperTrieProofsMsg = 0x11
  62. HelperTrieProofsMsg = 0x12
  63. SendTxV2Msg = 0x13
  64. GetTxStatusMsg = 0x14
  65. TxStatusMsg = 0x15
  66. // Protocol messages introduced in LPV3
  67. StopMsg = 0x16
  68. ResumeMsg = 0x17
  69. )
  70. type requestInfo struct {
  71. name string
  72. maxCount uint64
  73. }
  74. var requests = map[uint64]requestInfo{
  75. GetBlockHeadersMsg: {"GetBlockHeaders", MaxHeaderFetch},
  76. GetBlockBodiesMsg: {"GetBlockBodies", MaxBodyFetch},
  77. GetReceiptsMsg: {"GetReceipts", MaxReceiptFetch},
  78. GetCodeMsg: {"GetCode", MaxCodeFetch},
  79. GetProofsV2Msg: {"GetProofsV2", MaxProofsFetch},
  80. GetHelperTrieProofsMsg: {"GetHelperTrieProofs", MaxHelperTrieProofsFetch},
  81. SendTxV2Msg: {"SendTxV2", MaxTxSend},
  82. GetTxStatusMsg: {"GetTxStatus", MaxTxStatus},
  83. }
  84. type errCode int
  85. const (
  86. ErrMsgTooLarge = iota
  87. ErrDecode
  88. ErrInvalidMsgCode
  89. ErrProtocolVersionMismatch
  90. ErrNetworkIdMismatch
  91. ErrGenesisBlockMismatch
  92. ErrNoStatusMsg
  93. ErrExtraStatusMsg
  94. ErrSuspendedPeer
  95. ErrUselessPeer
  96. ErrRequestRejected
  97. ErrUnexpectedResponse
  98. ErrInvalidResponse
  99. ErrTooManyTimeouts
  100. ErrMissingKey
  101. )
  102. func (e errCode) String() string {
  103. return errorToString[int(e)]
  104. }
  105. // XXX change once legacy code is out
  106. var errorToString = map[int]string{
  107. ErrMsgTooLarge: "Message too long",
  108. ErrDecode: "Invalid message",
  109. ErrInvalidMsgCode: "Invalid message code",
  110. ErrProtocolVersionMismatch: "Protocol version mismatch",
  111. ErrNetworkIdMismatch: "NetworkId mismatch",
  112. ErrGenesisBlockMismatch: "Genesis block mismatch",
  113. ErrNoStatusMsg: "No status message",
  114. ErrExtraStatusMsg: "Extra status message",
  115. ErrSuspendedPeer: "Suspended peer",
  116. ErrRequestRejected: "Request rejected",
  117. ErrUnexpectedResponse: "Unexpected response",
  118. ErrInvalidResponse: "Invalid response",
  119. ErrTooManyTimeouts: "Too many request timeouts",
  120. ErrMissingKey: "Key missing from list",
  121. }
  122. type announceBlock struct {
  123. Hash common.Hash // Hash of one particular block being announced
  124. Number uint64 // Number of one particular block being announced
  125. Td *big.Int // Total difficulty of one particular block being announced
  126. }
  127. // announceData is the network packet for the block announcements.
  128. type announceData struct {
  129. Hash common.Hash // Hash of one particular block being announced
  130. Number uint64 // Number of one particular block being announced
  131. Td *big.Int // Total difficulty of one particular block being announced
  132. ReorgDepth uint64
  133. Update keyValueList
  134. }
  135. // sanityCheck verifies that the values are reasonable, as a DoS protection
  136. func (a *announceData) sanityCheck() error {
  137. if tdlen := a.Td.BitLen(); tdlen > 100 {
  138. return fmt.Errorf("too large block TD: bitlen %d", tdlen)
  139. }
  140. return nil
  141. }
  142. // sign adds a signature to the block announcement by the given privKey
  143. func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
  144. rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
  145. sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
  146. a.Update = a.Update.add("sign", sig)
  147. }
  148. // checkSignature verifies if the block announcement has a valid signature by the given pubKey
  149. func (a *announceData) checkSignature(id enode.ID, update keyValueMap) error {
  150. var sig []byte
  151. if err := update.get("sign", &sig); err != nil {
  152. return err
  153. }
  154. rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
  155. recPubkey, err := crypto.SigToPub(crypto.Keccak256(rlp), sig)
  156. if err != nil {
  157. return err
  158. }
  159. if id == enode.PubkeyToIDV4(recPubkey) {
  160. return nil
  161. }
  162. return errors.New("wrong signature")
  163. }
  164. type blockInfo struct {
  165. Hash common.Hash // Hash of one particular block being announced
  166. Number uint64 // Number of one particular block being announced
  167. Td *big.Int // Total difficulty of one particular block being announced
  168. }
  169. // getBlockHeadersData represents a block header query.
  170. type getBlockHeadersData struct {
  171. Origin hashOrNumber // Block from which to retrieve headers
  172. Amount uint64 // Maximum number of headers to retrieve
  173. Skip uint64 // Blocks to skip between consecutive headers
  174. Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis)
  175. }
  176. // hashOrNumber is a combined field for specifying an origin block.
  177. type hashOrNumber struct {
  178. Hash common.Hash // Block hash from which to retrieve headers (excludes Number)
  179. Number uint64 // Block hash from which to retrieve headers (excludes Hash)
  180. }
  181. // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
  182. // two contained union fields.
  183. func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
  184. if hn.Hash == (common.Hash{}) {
  185. return rlp.Encode(w, hn.Number)
  186. }
  187. if hn.Number != 0 {
  188. return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
  189. }
  190. return rlp.Encode(w, hn.Hash)
  191. }
  192. // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
  193. // into either a block hash or a block number.
  194. func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
  195. _, size, _ := s.Kind()
  196. origin, err := s.Raw()
  197. if err == nil {
  198. switch {
  199. case size == 32:
  200. err = rlp.DecodeBytes(origin, &hn.Hash)
  201. case size <= 8:
  202. err = rlp.DecodeBytes(origin, &hn.Number)
  203. default:
  204. err = fmt.Errorf("invalid input size %d for origin", size)
  205. }
  206. }
  207. return err
  208. }
  209. // CodeData is the network response packet for a node data retrieval.
  210. type CodeData []struct {
  211. Value []byte
  212. }
  213. type proofsData [][]rlp.RawValue