protocol.go 10 KB

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