odr_requests.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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 light implements on-demand retrieval capable state and chain objects
  17. // for the Ethereum Light Client.
  18. package les
  19. import (
  20. "encoding/binary"
  21. "errors"
  22. "fmt"
  23. "github.com/ethereum/go-ethereum/common"
  24. "github.com/ethereum/go-ethereum/core/rawdb"
  25. "github.com/ethereum/go-ethereum/core/types"
  26. "github.com/ethereum/go-ethereum/crypto"
  27. "github.com/ethereum/go-ethereum/ethdb"
  28. "github.com/ethereum/go-ethereum/light"
  29. "github.com/ethereum/go-ethereum/log"
  30. "github.com/ethereum/go-ethereum/rlp"
  31. "github.com/ethereum/go-ethereum/trie"
  32. )
  33. var (
  34. errInvalidMessageType = errors.New("invalid message type")
  35. errInvalidEntryCount = errors.New("invalid number of response entries")
  36. errHeaderUnavailable = errors.New("header unavailable")
  37. errTxHashMismatch = errors.New("transaction hash mismatch")
  38. errUncleHashMismatch = errors.New("uncle hash mismatch")
  39. errReceiptHashMismatch = errors.New("receipt hash mismatch")
  40. errDataHashMismatch = errors.New("data hash mismatch")
  41. errCHTHashMismatch = errors.New("cht hash mismatch")
  42. errCHTNumberMismatch = errors.New("cht number mismatch")
  43. errUselessNodes = errors.New("useless nodes in merkle proof nodeset")
  44. )
  45. type LesOdrRequest interface {
  46. GetCost(*peer) uint64
  47. CanSend(*peer) bool
  48. Request(uint64, *peer) error
  49. Validate(ethdb.Database, *Msg) error
  50. }
  51. func LesRequest(req light.OdrRequest) LesOdrRequest {
  52. switch r := req.(type) {
  53. case *light.BlockRequest:
  54. return (*BlockRequest)(r)
  55. case *light.ReceiptsRequest:
  56. return (*ReceiptsRequest)(r)
  57. case *light.TrieRequest:
  58. return (*TrieRequest)(r)
  59. case *light.CodeRequest:
  60. return (*CodeRequest)(r)
  61. case *light.ChtRequest:
  62. return (*ChtRequest)(r)
  63. case *light.BloomRequest:
  64. return (*BloomRequest)(r)
  65. default:
  66. return nil
  67. }
  68. }
  69. // BlockRequest is the ODR request type for block bodies
  70. type BlockRequest light.BlockRequest
  71. // GetCost returns the cost of the given ODR request according to the serving
  72. // peer's cost table (implementation of LesOdrRequest)
  73. func (r *BlockRequest) GetCost(peer *peer) uint64 {
  74. return peer.GetRequestCost(GetBlockBodiesMsg, 1)
  75. }
  76. // CanSend tells if a certain peer is suitable for serving the given request
  77. func (r *BlockRequest) CanSend(peer *peer) bool {
  78. return peer.HasBlock(r.Hash, r.Number)
  79. }
  80. // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
  81. func (r *BlockRequest) Request(reqID uint64, peer *peer) error {
  82. peer.Log().Debug("Requesting block body", "hash", r.Hash)
  83. return peer.RequestBodies(reqID, r.GetCost(peer), []common.Hash{r.Hash})
  84. }
  85. // Valid processes an ODR request reply message from the LES network
  86. // returns true and stores results in memory if the message was a valid reply
  87. // to the request (implementation of LesOdrRequest)
  88. func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error {
  89. log.Debug("Validating block body", "hash", r.Hash)
  90. // Ensure we have a correct message with a single block body
  91. if msg.MsgType != MsgBlockBodies {
  92. return errInvalidMessageType
  93. }
  94. bodies := msg.Obj.([]*types.Body)
  95. if len(bodies) != 1 {
  96. return errInvalidEntryCount
  97. }
  98. body := bodies[0]
  99. // Retrieve our stored header and validate block content against it
  100. header := rawdb.ReadHeader(db, r.Hash, r.Number)
  101. if header == nil {
  102. return errHeaderUnavailable
  103. }
  104. if header.TxHash != types.DeriveSha(types.Transactions(body.Transactions)) {
  105. return errTxHashMismatch
  106. }
  107. if header.UncleHash != types.CalcUncleHash(body.Uncles) {
  108. return errUncleHashMismatch
  109. }
  110. // Validations passed, encode and store RLP
  111. data, err := rlp.EncodeToBytes(body)
  112. if err != nil {
  113. return err
  114. }
  115. r.Rlp = data
  116. return nil
  117. }
  118. // ReceiptsRequest is the ODR request type for block receipts by block hash
  119. type ReceiptsRequest light.ReceiptsRequest
  120. // GetCost returns the cost of the given ODR request according to the serving
  121. // peer's cost table (implementation of LesOdrRequest)
  122. func (r *ReceiptsRequest) GetCost(peer *peer) uint64 {
  123. return peer.GetRequestCost(GetReceiptsMsg, 1)
  124. }
  125. // CanSend tells if a certain peer is suitable for serving the given request
  126. func (r *ReceiptsRequest) CanSend(peer *peer) bool {
  127. return peer.HasBlock(r.Hash, r.Number)
  128. }
  129. // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
  130. func (r *ReceiptsRequest) Request(reqID uint64, peer *peer) error {
  131. peer.Log().Debug("Requesting block receipts", "hash", r.Hash)
  132. return peer.RequestReceipts(reqID, r.GetCost(peer), []common.Hash{r.Hash})
  133. }
  134. // Valid processes an ODR request reply message from the LES network
  135. // returns true and stores results in memory if the message was a valid reply
  136. // to the request (implementation of LesOdrRequest)
  137. func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
  138. log.Debug("Validating block receipts", "hash", r.Hash)
  139. // Ensure we have a correct message with a single block receipt
  140. if msg.MsgType != MsgReceipts {
  141. return errInvalidMessageType
  142. }
  143. receipts := msg.Obj.([]types.Receipts)
  144. if len(receipts) != 1 {
  145. return errInvalidEntryCount
  146. }
  147. receipt := receipts[0]
  148. // Retrieve our stored header and validate receipt content against it
  149. header := rawdb.ReadHeader(db, r.Hash, r.Number)
  150. if header == nil {
  151. return errHeaderUnavailable
  152. }
  153. if header.ReceiptHash != types.DeriveSha(receipt) {
  154. return errReceiptHashMismatch
  155. }
  156. // Validations passed, store and return
  157. r.Receipts = receipt
  158. return nil
  159. }
  160. type ProofReq struct {
  161. BHash common.Hash
  162. AccKey, Key []byte
  163. FromLevel uint
  164. }
  165. // ODR request type for state/storage trie entries, see LesOdrRequest interface
  166. type TrieRequest light.TrieRequest
  167. // GetCost returns the cost of the given ODR request according to the serving
  168. // peer's cost table (implementation of LesOdrRequest)
  169. func (r *TrieRequest) GetCost(peer *peer) uint64 {
  170. switch peer.version {
  171. case lpv1:
  172. return peer.GetRequestCost(GetProofsV1Msg, 1)
  173. case lpv2:
  174. return peer.GetRequestCost(GetProofsV2Msg, 1)
  175. default:
  176. panic(nil)
  177. }
  178. }
  179. // CanSend tells if a certain peer is suitable for serving the given request
  180. func (r *TrieRequest) CanSend(peer *peer) bool {
  181. return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber)
  182. }
  183. // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
  184. func (r *TrieRequest) Request(reqID uint64, peer *peer) error {
  185. peer.Log().Debug("Requesting trie proof", "root", r.Id.Root, "key", r.Key)
  186. req := ProofReq{
  187. BHash: r.Id.BlockHash,
  188. AccKey: r.Id.AccKey,
  189. Key: r.Key,
  190. }
  191. return peer.RequestProofs(reqID, r.GetCost(peer), []ProofReq{req})
  192. }
  193. // Valid processes an ODR request reply message from the LES network
  194. // returns true and stores results in memory if the message was a valid reply
  195. // to the request (implementation of LesOdrRequest)
  196. func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error {
  197. log.Debug("Validating trie proof", "root", r.Id.Root, "key", r.Key)
  198. switch msg.MsgType {
  199. case MsgProofsV1:
  200. proofs := msg.Obj.([]light.NodeList)
  201. if len(proofs) != 1 {
  202. return errInvalidEntryCount
  203. }
  204. nodeSet := proofs[0].NodeSet()
  205. // Verify the proof and store if checks out
  206. if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, nodeSet); err != nil {
  207. return fmt.Errorf("merkle proof verification failed: %v", err)
  208. }
  209. r.Proof = nodeSet
  210. return nil
  211. case MsgProofsV2:
  212. proofs := msg.Obj.(light.NodeList)
  213. // Verify the proof and store if checks out
  214. nodeSet := proofs.NodeSet()
  215. reads := &readTraceDB{db: nodeSet}
  216. if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, reads); err != nil {
  217. return fmt.Errorf("merkle proof verification failed: %v", err)
  218. }
  219. // check if all nodes have been read by VerifyProof
  220. if len(reads.reads) != nodeSet.KeyCount() {
  221. return errUselessNodes
  222. }
  223. r.Proof = nodeSet
  224. return nil
  225. default:
  226. return errInvalidMessageType
  227. }
  228. }
  229. type CodeReq struct {
  230. BHash common.Hash
  231. AccKey []byte
  232. }
  233. // ODR request type for node data (used for retrieving contract code), see LesOdrRequest interface
  234. type CodeRequest light.CodeRequest
  235. // GetCost returns the cost of the given ODR request according to the serving
  236. // peer's cost table (implementation of LesOdrRequest)
  237. func (r *CodeRequest) GetCost(peer *peer) uint64 {
  238. return peer.GetRequestCost(GetCodeMsg, 1)
  239. }
  240. // CanSend tells if a certain peer is suitable for serving the given request
  241. func (r *CodeRequest) CanSend(peer *peer) bool {
  242. return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber)
  243. }
  244. // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
  245. func (r *CodeRequest) Request(reqID uint64, peer *peer) error {
  246. peer.Log().Debug("Requesting code data", "hash", r.Hash)
  247. req := CodeReq{
  248. BHash: r.Id.BlockHash,
  249. AccKey: r.Id.AccKey,
  250. }
  251. return peer.RequestCode(reqID, r.GetCost(peer), []CodeReq{req})
  252. }
  253. // Valid processes an ODR request reply message from the LES network
  254. // returns true and stores results in memory if the message was a valid reply
  255. // to the request (implementation of LesOdrRequest)
  256. func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error {
  257. log.Debug("Validating code data", "hash", r.Hash)
  258. // Ensure we have a correct message with a single code element
  259. if msg.MsgType != MsgCode {
  260. return errInvalidMessageType
  261. }
  262. reply := msg.Obj.([][]byte)
  263. if len(reply) != 1 {
  264. return errInvalidEntryCount
  265. }
  266. data := reply[0]
  267. // Verify the data and store if checks out
  268. if hash := crypto.Keccak256Hash(data); r.Hash != hash {
  269. return errDataHashMismatch
  270. }
  271. r.Data = data
  272. return nil
  273. }
  274. const (
  275. // helper trie type constants
  276. htCanonical = iota // Canonical hash trie
  277. htBloomBits // BloomBits trie
  278. // applicable for all helper trie requests
  279. auxRoot = 1
  280. // applicable for htCanonical
  281. auxHeader = 2
  282. )
  283. type HelperTrieReq struct {
  284. Type uint
  285. TrieIdx uint64
  286. Key []byte
  287. FromLevel, AuxReq uint
  288. }
  289. type HelperTrieResps struct { // describes all responses, not just a single one
  290. Proofs light.NodeList
  291. AuxData [][]byte
  292. }
  293. // legacy LES/1
  294. type ChtReq struct {
  295. ChtNum, BlockNum uint64
  296. FromLevel uint
  297. }
  298. // legacy LES/1
  299. type ChtResp struct {
  300. Header *types.Header
  301. Proof []rlp.RawValue
  302. }
  303. // ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
  304. type ChtRequest light.ChtRequest
  305. // GetCost returns the cost of the given ODR request according to the serving
  306. // peer's cost table (implementation of LesOdrRequest)
  307. func (r *ChtRequest) GetCost(peer *peer) uint64 {
  308. switch peer.version {
  309. case lpv1:
  310. return peer.GetRequestCost(GetHeaderProofsMsg, 1)
  311. case lpv2:
  312. return peer.GetRequestCost(GetHelperTrieProofsMsg, 1)
  313. default:
  314. panic(nil)
  315. }
  316. }
  317. // CanSend tells if a certain peer is suitable for serving the given request
  318. func (r *ChtRequest) CanSend(peer *peer) bool {
  319. peer.lock.RLock()
  320. defer peer.lock.RUnlock()
  321. return peer.headInfo.Number >= light.HelperTrieConfirmations && r.ChtNum <= (peer.headInfo.Number-light.HelperTrieConfirmations)/light.CHTFrequencyClient
  322. }
  323. // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
  324. func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
  325. peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.BlockNum)
  326. var encNum [8]byte
  327. binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
  328. req := HelperTrieReq{
  329. Type: htCanonical,
  330. TrieIdx: r.ChtNum,
  331. Key: encNum[:],
  332. AuxReq: auxHeader,
  333. }
  334. return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
  335. }
  336. // Valid processes an ODR request reply message from the LES network
  337. // returns true and stores results in memory if the message was a valid reply
  338. // to the request (implementation of LesOdrRequest)
  339. func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
  340. log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum)
  341. switch msg.MsgType {
  342. case MsgHeaderProofs: // LES/1 backwards compatibility
  343. proofs := msg.Obj.([]ChtResp)
  344. if len(proofs) != 1 {
  345. return errInvalidEntryCount
  346. }
  347. proof := proofs[0]
  348. // Verify the CHT
  349. var encNumber [8]byte
  350. binary.BigEndian.PutUint64(encNumber[:], r.BlockNum)
  351. value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], light.NodeList(proof.Proof).NodeSet())
  352. if err != nil {
  353. return err
  354. }
  355. var node light.ChtNode
  356. if err := rlp.DecodeBytes(value, &node); err != nil {
  357. return err
  358. }
  359. if node.Hash != proof.Header.Hash() {
  360. return errCHTHashMismatch
  361. }
  362. // Verifications passed, store and return
  363. r.Header = proof.Header
  364. r.Proof = light.NodeList(proof.Proof).NodeSet()
  365. r.Td = node.Td
  366. case MsgHelperTrieProofs:
  367. resp := msg.Obj.(HelperTrieResps)
  368. if len(resp.AuxData) != 1 {
  369. return errInvalidEntryCount
  370. }
  371. nodeSet := resp.Proofs.NodeSet()
  372. headerEnc := resp.AuxData[0]
  373. if len(headerEnc) == 0 {
  374. return errHeaderUnavailable
  375. }
  376. header := new(types.Header)
  377. if err := rlp.DecodeBytes(headerEnc, header); err != nil {
  378. return errHeaderUnavailable
  379. }
  380. // Verify the CHT
  381. var encNumber [8]byte
  382. binary.BigEndian.PutUint64(encNumber[:], r.BlockNum)
  383. reads := &readTraceDB{db: nodeSet}
  384. value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], reads)
  385. if err != nil {
  386. return fmt.Errorf("merkle proof verification failed: %v", err)
  387. }
  388. if len(reads.reads) != nodeSet.KeyCount() {
  389. return errUselessNodes
  390. }
  391. var node light.ChtNode
  392. if err := rlp.DecodeBytes(value, &node); err != nil {
  393. return err
  394. }
  395. if node.Hash != header.Hash() {
  396. return errCHTHashMismatch
  397. }
  398. if r.BlockNum != header.Number.Uint64() {
  399. return errCHTNumberMismatch
  400. }
  401. // Verifications passed, store and return
  402. r.Header = header
  403. r.Proof = nodeSet
  404. r.Td = node.Td
  405. default:
  406. return errInvalidMessageType
  407. }
  408. return nil
  409. }
  410. type BloomReq struct {
  411. BloomTrieNum, BitIdx, SectionIdx, FromLevel uint64
  412. }
  413. // ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
  414. type BloomRequest light.BloomRequest
  415. // GetCost returns the cost of the given ODR request according to the serving
  416. // peer's cost table (implementation of LesOdrRequest)
  417. func (r *BloomRequest) GetCost(peer *peer) uint64 {
  418. return peer.GetRequestCost(GetHelperTrieProofsMsg, len(r.SectionIdxList))
  419. }
  420. // CanSend tells if a certain peer is suitable for serving the given request
  421. func (r *BloomRequest) CanSend(peer *peer) bool {
  422. peer.lock.RLock()
  423. defer peer.lock.RUnlock()
  424. if peer.version < lpv2 {
  425. return false
  426. }
  427. return peer.headInfo.Number >= light.HelperTrieConfirmations && r.BloomTrieNum <= (peer.headInfo.Number-light.HelperTrieConfirmations)/light.BloomTrieFrequency
  428. }
  429. // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
  430. func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
  431. peer.Log().Debug("Requesting BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIdxList)
  432. reqs := make([]HelperTrieReq, len(r.SectionIdxList))
  433. var encNumber [10]byte
  434. binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
  435. for i, sectionIdx := range r.SectionIdxList {
  436. binary.BigEndian.PutUint64(encNumber[2:], sectionIdx)
  437. reqs[i] = HelperTrieReq{
  438. Type: htBloomBits,
  439. TrieIdx: r.BloomTrieNum,
  440. Key: common.CopyBytes(encNumber[:]),
  441. }
  442. }
  443. return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
  444. }
  445. // Valid processes an ODR request reply message from the LES network
  446. // returns true and stores results in memory if the message was a valid reply
  447. // to the request (implementation of LesOdrRequest)
  448. func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
  449. log.Debug("Validating BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIdxList)
  450. // Ensure we have a correct message with a single proof element
  451. if msg.MsgType != MsgHelperTrieProofs {
  452. return errInvalidMessageType
  453. }
  454. resps := msg.Obj.(HelperTrieResps)
  455. proofs := resps.Proofs
  456. nodeSet := proofs.NodeSet()
  457. reads := &readTraceDB{db: nodeSet}
  458. r.BloomBits = make([][]byte, len(r.SectionIdxList))
  459. // Verify the proofs
  460. var encNumber [10]byte
  461. binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
  462. for i, idx := range r.SectionIdxList {
  463. binary.BigEndian.PutUint64(encNumber[2:], idx)
  464. value, _, err := trie.VerifyProof(r.BloomTrieRoot, encNumber[:], reads)
  465. if err != nil {
  466. return err
  467. }
  468. r.BloomBits[i] = value
  469. }
  470. if len(reads.reads) != nodeSet.KeyCount() {
  471. return errUselessNodes
  472. }
  473. r.Proofs = nodeSet
  474. return nil
  475. }
  476. // readTraceDB stores the keys of database reads. We use this to check that received node
  477. // sets contain only the trie nodes necessary to make proofs pass.
  478. type readTraceDB struct {
  479. db trie.DatabaseReader
  480. reads map[string]struct{}
  481. }
  482. // Get returns a stored node
  483. func (db *readTraceDB) Get(k []byte) ([]byte, error) {
  484. if db.reads == nil {
  485. db.reads = make(map[string]struct{})
  486. }
  487. db.reads[string(k)] = struct{}{}
  488. return db.db.Get(k)
  489. }
  490. // Has returns true if the node set contains the given key
  491. func (db *readTraceDB) Has(key []byte) (bool, error) {
  492. _, err := db.Get(key)
  493. return err == nil, nil
  494. }