handler_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. "math/rand"
  19. "testing"
  20. "github.com/ethereum/go-ethereum/common"
  21. "github.com/ethereum/go-ethereum/core"
  22. "github.com/ethereum/go-ethereum/core/types"
  23. "github.com/ethereum/go-ethereum/crypto"
  24. "github.com/ethereum/go-ethereum/eth/downloader"
  25. "github.com/ethereum/go-ethereum/p2p"
  26. "github.com/ethereum/go-ethereum/rlp"
  27. "github.com/ethereum/go-ethereum/trie"
  28. )
  29. func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}) error {
  30. type resp struct {
  31. ReqID, BV uint64
  32. Data interface{}
  33. }
  34. return p2p.ExpectMsg(r, msgcode, resp{reqID, bv, data})
  35. }
  36. // Tests that block headers can be retrieved from a remote chain based on user queries.
  37. func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) }
  38. func testGetBlockHeaders(t *testing.T, protocol int) {
  39. pm, _, _ := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil)
  40. bc := pm.blockchain.(*core.BlockChain)
  41. peer, _ := newTestPeer(t, "peer", protocol, pm, true)
  42. defer peer.close()
  43. // Create a "random" unknown hash for testing
  44. var unknown common.Hash
  45. for i, _ := range unknown {
  46. unknown[i] = byte(i)
  47. }
  48. // Create a batch of tests for various scenarios
  49. limit := uint64(MaxHeaderFetch)
  50. tests := []struct {
  51. query *getBlockHeadersData // The query to execute for header retrieval
  52. expect []common.Hash // The hashes of the block whose headers are expected
  53. }{
  54. // A single random block should be retrievable by hash and number too
  55. {
  56. &getBlockHeadersData{Origin: hashOrNumber{Hash: bc.GetBlockByNumber(limit / 2).Hash()}, Amount: 1},
  57. []common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
  58. }, {
  59. &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1},
  60. []common.Hash{bc.GetBlockByNumber(limit / 2).Hash()},
  61. },
  62. // Multiple headers should be retrievable in both directions
  63. {
  64. &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3},
  65. []common.Hash{
  66. bc.GetBlockByNumber(limit / 2).Hash(),
  67. bc.GetBlockByNumber(limit/2 + 1).Hash(),
  68. bc.GetBlockByNumber(limit/2 + 2).Hash(),
  69. },
  70. }, {
  71. &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true},
  72. []common.Hash{
  73. bc.GetBlockByNumber(limit / 2).Hash(),
  74. bc.GetBlockByNumber(limit/2 - 1).Hash(),
  75. bc.GetBlockByNumber(limit/2 - 2).Hash(),
  76. },
  77. },
  78. // Multiple headers with skip lists should be retrievable
  79. {
  80. &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3},
  81. []common.Hash{
  82. bc.GetBlockByNumber(limit / 2).Hash(),
  83. bc.GetBlockByNumber(limit/2 + 4).Hash(),
  84. bc.GetBlockByNumber(limit/2 + 8).Hash(),
  85. },
  86. }, {
  87. &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true},
  88. []common.Hash{
  89. bc.GetBlockByNumber(limit / 2).Hash(),
  90. bc.GetBlockByNumber(limit/2 - 4).Hash(),
  91. bc.GetBlockByNumber(limit/2 - 8).Hash(),
  92. },
  93. },
  94. // The chain endpoints should be retrievable
  95. {
  96. &getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1},
  97. []common.Hash{bc.GetBlockByNumber(0).Hash()},
  98. }, {
  99. &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64()}, Amount: 1},
  100. []common.Hash{bc.CurrentBlock().Hash()},
  101. },
  102. // Ensure protocol limits are honored
  103. /*{
  104. &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true},
  105. bc.GetBlockHashesFromHash(bc.CurrentBlock().Hash(), limit),
  106. },*/
  107. // Check that requesting more than available is handled gracefully
  108. {
  109. &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3},
  110. []common.Hash{
  111. bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
  112. bc.GetBlockByNumber(bc.CurrentBlock().NumberU64()).Hash(),
  113. },
  114. }, {
  115. &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
  116. []common.Hash{
  117. bc.GetBlockByNumber(4).Hash(),
  118. bc.GetBlockByNumber(0).Hash(),
  119. },
  120. },
  121. // Check that requesting more than available is handled gracefully, even if mid skip
  122. {
  123. &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3},
  124. []common.Hash{
  125. bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(),
  126. bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1).Hash(),
  127. },
  128. }, {
  129. &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
  130. []common.Hash{
  131. bc.GetBlockByNumber(4).Hash(),
  132. bc.GetBlockByNumber(1).Hash(),
  133. },
  134. },
  135. // Check that non existing headers aren't returned
  136. {
  137. &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1},
  138. []common.Hash{},
  139. }, {
  140. &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() + 1}, Amount: 1},
  141. []common.Hash{},
  142. },
  143. }
  144. // Run each of the tests and verify the results against the chain
  145. var reqID uint64
  146. for i, tt := range tests {
  147. // Collect the headers to expect in the response
  148. headers := []*types.Header{}
  149. for _, hash := range tt.expect {
  150. headers = append(headers, bc.GetHeaderByHash(hash))
  151. }
  152. // Send the hash request and verify the response
  153. reqID++
  154. cost := peer.GetRequestCost(GetBlockHeadersMsg, int(tt.query.Amount))
  155. sendRequest(peer.app, GetBlockHeadersMsg, reqID, cost, tt.query)
  156. if err := expectResponse(peer.app, BlockHeadersMsg, reqID, testBufLimit, headers); err != nil {
  157. t.Errorf("test %d: headers mismatch: %v", i, err)
  158. }
  159. }
  160. }
  161. // Tests that block contents can be retrieved from a remote chain based on their hashes.
  162. func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) }
  163. func testGetBlockBodies(t *testing.T, protocol int) {
  164. pm, _, _ := newTestProtocolManagerMust(t, false, downloader.MaxBlockFetch+15, nil)
  165. bc := pm.blockchain.(*core.BlockChain)
  166. peer, _ := newTestPeer(t, "peer", protocol, pm, true)
  167. defer peer.close()
  168. // Create a batch of tests for various scenarios
  169. limit := MaxBodyFetch
  170. tests := []struct {
  171. random int // Number of blocks to fetch randomly from the chain
  172. explicit []common.Hash // Explicitly requested blocks
  173. available []bool // Availability of explicitly requested blocks
  174. expected int // Total number of existing blocks to expect
  175. }{
  176. {1, nil, nil, 1}, // A single random block should be retrievable
  177. {10, nil, nil, 10}, // Multiple random blocks should be retrievable
  178. {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable
  179. //{limit + 1, nil, nil, limit}, // No more than the possible block count should be returned
  180. {0, []common.Hash{bc.Genesis().Hash()}, []bool{true}, 1}, // The genesis block should be retrievable
  181. {0, []common.Hash{bc.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable
  182. {0, []common.Hash{common.Hash{}}, []bool{false}, 0}, // A non existent block should not be returned
  183. // Existing and non-existing blocks interleaved should not cause problems
  184. {0, []common.Hash{
  185. common.Hash{},
  186. bc.GetBlockByNumber(1).Hash(),
  187. common.Hash{},
  188. bc.GetBlockByNumber(10).Hash(),
  189. common.Hash{},
  190. bc.GetBlockByNumber(100).Hash(),
  191. common.Hash{},
  192. }, []bool{false, true, false, true, false, true, false}, 3},
  193. }
  194. // Run each of the tests and verify the results against the chain
  195. var reqID uint64
  196. for i, tt := range tests {
  197. // Collect the hashes to request, and the response to expect
  198. hashes, seen := []common.Hash{}, make(map[int64]bool)
  199. bodies := []*types.Body{}
  200. for j := 0; j < tt.random; j++ {
  201. for {
  202. num := rand.Int63n(int64(bc.CurrentBlock().NumberU64()))
  203. if !seen[num] {
  204. seen[num] = true
  205. block := bc.GetBlockByNumber(uint64(num))
  206. hashes = append(hashes, block.Hash())
  207. if len(bodies) < tt.expected {
  208. bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()})
  209. }
  210. break
  211. }
  212. }
  213. }
  214. for j, hash := range tt.explicit {
  215. hashes = append(hashes, hash)
  216. if tt.available[j] && len(bodies) < tt.expected {
  217. block := bc.GetBlockByHash(hash)
  218. bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()})
  219. }
  220. }
  221. reqID++
  222. // Send the hash request and verify the response
  223. cost := peer.GetRequestCost(GetBlockBodiesMsg, len(hashes))
  224. sendRequest(peer.app, GetBlockBodiesMsg, reqID, cost, hashes)
  225. if err := expectResponse(peer.app, BlockBodiesMsg, reqID, testBufLimit, bodies); err != nil {
  226. t.Errorf("test %d: bodies mismatch: %v", i, err)
  227. }
  228. }
  229. }
  230. // Tests that the contract codes can be retrieved based on account addresses.
  231. func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) }
  232. func testGetCode(t *testing.T, protocol int) {
  233. // Assemble the test environment
  234. pm, _, _ := newTestProtocolManagerMust(t, false, 4, testChainGen)
  235. bc := pm.blockchain.(*core.BlockChain)
  236. peer, _ := newTestPeer(t, "peer", protocol, pm, true)
  237. defer peer.close()
  238. var codereqs []*CodeReq
  239. var codes [][]byte
  240. for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
  241. header := bc.GetHeaderByNumber(i)
  242. req := &CodeReq{
  243. BHash: header.Hash(),
  244. AccKey: crypto.Keccak256(testContractAddr[:]),
  245. }
  246. codereqs = append(codereqs, req)
  247. if i >= testContractDeployed {
  248. codes = append(codes, testContractCodeDeployed)
  249. }
  250. }
  251. cost := peer.GetRequestCost(GetCodeMsg, len(codereqs))
  252. sendRequest(peer.app, GetCodeMsg, 42, cost, codereqs)
  253. if err := expectResponse(peer.app, CodeMsg, 42, testBufLimit, codes); err != nil {
  254. t.Errorf("codes mismatch: %v", err)
  255. }
  256. }
  257. // Tests that the transaction receipts can be retrieved based on hashes.
  258. func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) }
  259. func testGetReceipt(t *testing.T, protocol int) {
  260. // Assemble the test environment
  261. pm, db, _ := newTestProtocolManagerMust(t, false, 4, testChainGen)
  262. bc := pm.blockchain.(*core.BlockChain)
  263. peer, _ := newTestPeer(t, "peer", protocol, pm, true)
  264. defer peer.close()
  265. // Collect the hashes to request, and the response to expect
  266. hashes, receipts := []common.Hash{}, []types.Receipts{}
  267. for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
  268. block := bc.GetBlockByNumber(i)
  269. hashes = append(hashes, block.Hash())
  270. receipts = append(receipts, core.GetBlockReceipts(db, block.Hash(), block.NumberU64()))
  271. }
  272. // Send the hash request and verify the response
  273. cost := peer.GetRequestCost(GetReceiptsMsg, len(hashes))
  274. sendRequest(peer.app, GetReceiptsMsg, 42, cost, hashes)
  275. if err := expectResponse(peer.app, ReceiptsMsg, 42, testBufLimit, receipts); err != nil {
  276. t.Errorf("receipts mismatch: %v", err)
  277. }
  278. }
  279. // Tests that trie merkle proofs can be retrieved
  280. func TestGetProofsLes1(t *testing.T) { testGetReceipt(t, 1) }
  281. func testGetProofs(t *testing.T, protocol int) {
  282. // Assemble the test environment
  283. pm, db, _ := newTestProtocolManagerMust(t, false, 4, testChainGen)
  284. bc := pm.blockchain.(*core.BlockChain)
  285. peer, _ := newTestPeer(t, "peer", protocol, pm, true)
  286. defer peer.close()
  287. var proofreqs []ProofReq
  288. var proofs [][]rlp.RawValue
  289. accounts := []common.Address{testBankAddress, acc1Addr, acc2Addr, common.Address{}}
  290. for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ {
  291. header := bc.GetHeaderByNumber(i)
  292. root := header.Root
  293. trie, _ := trie.New(root, db)
  294. for _, acc := range accounts {
  295. req := ProofReq{
  296. BHash: header.Hash(),
  297. Key: acc[:],
  298. }
  299. proofreqs = append(proofreqs, req)
  300. proof := trie.Prove(crypto.Keccak256(acc[:]))
  301. proofs = append(proofs, proof)
  302. }
  303. }
  304. // Send the proof request and verify the response
  305. cost := peer.GetRequestCost(GetProofsMsg, len(proofreqs))
  306. sendRequest(peer.app, GetProofsMsg, 42, cost, proofreqs)
  307. if err := expectResponse(peer.app, ProofsMsg, 42, testBufLimit, proofs); err != nil {
  308. t.Errorf("proofs mismatch: %v", err)
  309. }
  310. }