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