github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/les/handler_test.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package les 13 14 import ( 15 "encoding/binary" 16 "math/big" 17 "math/rand" 18 "testing" 19 "time" 20 21 "github.com/Sberex/go-sberex/common" 22 "github.com/Sberex/go-sberex/consensus/ethash" 23 "github.com/Sberex/go-sberex/core" 24 "github.com/Sberex/go-sberex/core/types" 25 "github.com/Sberex/go-sberex/crypto" 26 "github.com/Sberex/go-sberex/eth/downloader" 27 "github.com/Sberex/go-sberex/ethdb" 28 "github.com/Sberex/go-sberex/light" 29 "github.com/Sberex/go-sberex/p2p" 30 "github.com/Sberex/go-sberex/params" 31 "github.com/Sberex/go-sberex/rlp" 32 "github.com/Sberex/go-sberex/trie" 33 ) 34 35 func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}) error { 36 type resp struct { 37 ReqID, BV uint64 38 Data interface{} 39 } 40 return p2p.ExpectMsg(r, msgcode, resp{reqID, bv, data}) 41 } 42 43 // Tests that block headers can be retrieved from a remote chain based on user queries. 44 func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) } 45 func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) } 46 47 func testGetBlockHeaders(t *testing.T, protocol int) { 48 db, _ := ethdb.NewMemDatabase() 49 pm := newTestProtocolManagerMust(t, false, downloader.MaxHashFetch+15, nil, nil, nil, db) 50 bc := pm.blockchain.(*core.BlockChain) 51 peer, _ := newTestPeer(t, "peer", protocol, pm, true) 52 defer peer.close() 53 54 // Create a "random" unknown hash for testing 55 var unknown common.Hash 56 for i := range unknown { 57 unknown[i] = byte(i) 58 } 59 // Create a batch of tests for various scenarios 60 limit := uint64(MaxHeaderFetch) 61 tests := []struct { 62 query *getBlockHeadersData // The query to execute for header retrieval 63 expect []common.Hash // The hashes of the block whose headers are expected 64 }{ 65 // A single random block should be retrievable by hash and number too 66 { 67 &getBlockHeadersData{Origin: hashOrNumber{Hash: bc.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, 68 []common.Hash{bc.GetBlockByNumber(limit / 2).Hash()}, 69 }, { 70 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1}, 71 []common.Hash{bc.GetBlockByNumber(limit / 2).Hash()}, 72 }, 73 // Multiple headers should be retrievable in both directions 74 { 75 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3}, 76 []common.Hash{ 77 bc.GetBlockByNumber(limit / 2).Hash(), 78 bc.GetBlockByNumber(limit/2 + 1).Hash(), 79 bc.GetBlockByNumber(limit/2 + 2).Hash(), 80 }, 81 }, { 82 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, 83 []common.Hash{ 84 bc.GetBlockByNumber(limit / 2).Hash(), 85 bc.GetBlockByNumber(limit/2 - 1).Hash(), 86 bc.GetBlockByNumber(limit/2 - 2).Hash(), 87 }, 88 }, 89 // Multiple headers with skip lists should be retrievable 90 { 91 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, 92 []common.Hash{ 93 bc.GetBlockByNumber(limit / 2).Hash(), 94 bc.GetBlockByNumber(limit/2 + 4).Hash(), 95 bc.GetBlockByNumber(limit/2 + 8).Hash(), 96 }, 97 }, { 98 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, 99 []common.Hash{ 100 bc.GetBlockByNumber(limit / 2).Hash(), 101 bc.GetBlockByNumber(limit/2 - 4).Hash(), 102 bc.GetBlockByNumber(limit/2 - 8).Hash(), 103 }, 104 }, 105 // The chain endpoints should be retrievable 106 { 107 &getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1}, 108 []common.Hash{bc.GetBlockByNumber(0).Hash()}, 109 }, { 110 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64()}, Amount: 1}, 111 []common.Hash{bc.CurrentBlock().Hash()}, 112 }, 113 // Ensure protocol limits are honored 114 /*{ 115 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, 116 bc.GetBlockHashesFromHash(bc.CurrentBlock().Hash(), limit), 117 },*/ 118 // Check that requesting more than available is handled gracefully 119 { 120 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, 121 []common.Hash{ 122 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(), 123 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64()).Hash(), 124 }, 125 }, { 126 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, 127 []common.Hash{ 128 bc.GetBlockByNumber(4).Hash(), 129 bc.GetBlockByNumber(0).Hash(), 130 }, 131 }, 132 // Check that requesting more than available is handled gracefully, even if mid skip 133 { 134 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, 135 []common.Hash{ 136 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(), 137 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1).Hash(), 138 }, 139 }, { 140 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, 141 []common.Hash{ 142 bc.GetBlockByNumber(4).Hash(), 143 bc.GetBlockByNumber(1).Hash(), 144 }, 145 }, 146 // Check that non existing headers aren't returned 147 { 148 &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, 149 []common.Hash{}, 150 }, { 151 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() + 1}, Amount: 1}, 152 []common.Hash{}, 153 }, 154 } 155 // Run each of the tests and verify the results against the chain 156 var reqID uint64 157 for i, tt := range tests { 158 // Collect the headers to expect in the response 159 headers := []*types.Header{} 160 for _, hash := range tt.expect { 161 headers = append(headers, bc.GetHeaderByHash(hash)) 162 } 163 // Send the hash request and verify the response 164 reqID++ 165 cost := peer.GetRequestCost(GetBlockHeadersMsg, int(tt.query.Amount)) 166 sendRequest(peer.app, GetBlockHeadersMsg, reqID, cost, tt.query) 167 if err := expectResponse(peer.app, BlockHeadersMsg, reqID, testBufLimit, headers); err != nil { 168 t.Errorf("test %d: headers mismatch: %v", i, err) 169 } 170 } 171 } 172 173 // Tests that block contents can be retrieved from a remote chain based on their hashes. 174 func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) } 175 func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) } 176 177 func testGetBlockBodies(t *testing.T, protocol int) { 178 db, _ := ethdb.NewMemDatabase() 179 pm := newTestProtocolManagerMust(t, false, downloader.MaxBlockFetch+15, nil, nil, nil, db) 180 bc := pm.blockchain.(*core.BlockChain) 181 peer, _ := newTestPeer(t, "peer", protocol, pm, true) 182 defer peer.close() 183 184 // Create a batch of tests for various scenarios 185 limit := MaxBodyFetch 186 tests := []struct { 187 random int // Number of blocks to fetch randomly from the chain 188 explicit []common.Hash // Explicitly requested blocks 189 available []bool // Availability of explicitly requested blocks 190 expected int // Total number of existing blocks to expect 191 }{ 192 {1, nil, nil, 1}, // A single random block should be retrievable 193 {10, nil, nil, 10}, // Multiple random blocks should be retrievable 194 {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable 195 //{limit + 1, nil, nil, limit}, // No more than the possible block count should be returned 196 {0, []common.Hash{bc.Genesis().Hash()}, []bool{true}, 1}, // The genesis block should be retrievable 197 {0, []common.Hash{bc.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable 198 {0, []common.Hash{{}}, []bool{false}, 0}, // A non existent block should not be returned 199 200 // Existing and non-existing blocks interleaved should not cause problems 201 {0, []common.Hash{ 202 {}, 203 bc.GetBlockByNumber(1).Hash(), 204 {}, 205 bc.GetBlockByNumber(10).Hash(), 206 {}, 207 bc.GetBlockByNumber(100).Hash(), 208 {}, 209 }, []bool{false, true, false, true, false, true, false}, 3}, 210 } 211 // Run each of the tests and verify the results against the chain 212 var reqID uint64 213 for i, tt := range tests { 214 // Collect the hashes to request, and the response to expect 215 hashes, seen := []common.Hash{}, make(map[int64]bool) 216 bodies := []*types.Body{} 217 218 for j := 0; j < tt.random; j++ { 219 for { 220 num := rand.Int63n(int64(bc.CurrentBlock().NumberU64())) 221 if !seen[num] { 222 seen[num] = true 223 224 block := bc.GetBlockByNumber(uint64(num)) 225 hashes = append(hashes, block.Hash()) 226 if len(bodies) < tt.expected { 227 bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()}) 228 } 229 break 230 } 231 } 232 } 233 for j, hash := range tt.explicit { 234 hashes = append(hashes, hash) 235 if tt.available[j] && len(bodies) < tt.expected { 236 block := bc.GetBlockByHash(hash) 237 bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()}) 238 } 239 } 240 reqID++ 241 // Send the hash request and verify the response 242 cost := peer.GetRequestCost(GetBlockBodiesMsg, len(hashes)) 243 sendRequest(peer.app, GetBlockBodiesMsg, reqID, cost, hashes) 244 if err := expectResponse(peer.app, BlockBodiesMsg, reqID, testBufLimit, bodies); err != nil { 245 t.Errorf("test %d: bodies mismatch: %v", i, err) 246 } 247 } 248 } 249 250 // Tests that the contract codes can be retrieved based on account addresses. 251 func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) } 252 func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) } 253 254 func testGetCode(t *testing.T, protocol int) { 255 // Assemble the test environment 256 db, _ := ethdb.NewMemDatabase() 257 pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db) 258 bc := pm.blockchain.(*core.BlockChain) 259 peer, _ := newTestPeer(t, "peer", protocol, pm, true) 260 defer peer.close() 261 262 var codereqs []*CodeReq 263 var codes [][]byte 264 265 for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { 266 header := bc.GetHeaderByNumber(i) 267 req := &CodeReq{ 268 BHash: header.Hash(), 269 AccKey: crypto.Keccak256(testContractAddr[:]), 270 } 271 codereqs = append(codereqs, req) 272 if i >= testContractDeployed { 273 codes = append(codes, testContractCodeDeployed) 274 } 275 } 276 277 cost := peer.GetRequestCost(GetCodeMsg, len(codereqs)) 278 sendRequest(peer.app, GetCodeMsg, 42, cost, codereqs) 279 if err := expectResponse(peer.app, CodeMsg, 42, testBufLimit, codes); err != nil { 280 t.Errorf("codes mismatch: %v", err) 281 } 282 } 283 284 // Tests that the transaction receipts can be retrieved based on hashes. 285 func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) } 286 func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) } 287 288 func testGetReceipt(t *testing.T, protocol int) { 289 // Assemble the test environment 290 db, _ := ethdb.NewMemDatabase() 291 pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db) 292 bc := pm.blockchain.(*core.BlockChain) 293 peer, _ := newTestPeer(t, "peer", protocol, pm, true) 294 defer peer.close() 295 296 // Collect the hashes to request, and the response to expect 297 hashes, receipts := []common.Hash{}, []types.Receipts{} 298 for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { 299 block := bc.GetBlockByNumber(i) 300 301 hashes = append(hashes, block.Hash()) 302 receipts = append(receipts, core.GetBlockReceipts(db, block.Hash(), block.NumberU64())) 303 } 304 // Send the hash request and verify the response 305 cost := peer.GetRequestCost(GetReceiptsMsg, len(hashes)) 306 sendRequest(peer.app, GetReceiptsMsg, 42, cost, hashes) 307 if err := expectResponse(peer.app, ReceiptsMsg, 42, testBufLimit, receipts); err != nil { 308 t.Errorf("receipts mismatch: %v", err) 309 } 310 } 311 312 // Tests that trie merkle proofs can be retrieved 313 func TestGetProofsLes1(t *testing.T) { testGetProofs(t, 1) } 314 func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) } 315 316 func testGetProofs(t *testing.T, protocol int) { 317 // Assemble the test environment 318 db, _ := ethdb.NewMemDatabase() 319 pm := newTestProtocolManagerMust(t, false, 4, testChainGen, nil, nil, db) 320 bc := pm.blockchain.(*core.BlockChain) 321 peer, _ := newTestPeer(t, "peer", protocol, pm, true) 322 defer peer.close() 323 324 var ( 325 proofreqs []ProofReq 326 proofsV1 [][]rlp.RawValue 327 ) 328 proofsV2 := light.NewNodeSet() 329 330 accounts := []common.Address{testBankAddress, acc1Addr, acc2Addr, {}} 331 for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { 332 header := bc.GetHeaderByNumber(i) 333 root := header.Root 334 trie, _ := trie.New(root, trie.NewDatabase(db)) 335 336 for _, acc := range accounts { 337 req := ProofReq{ 338 BHash: header.Hash(), 339 Key: crypto.Keccak256(acc[:]), 340 } 341 proofreqs = append(proofreqs, req) 342 343 switch protocol { 344 case 1: 345 var proof light.NodeList 346 trie.Prove(crypto.Keccak256(acc[:]), 0, &proof) 347 proofsV1 = append(proofsV1, proof) 348 case 2: 349 trie.Prove(crypto.Keccak256(acc[:]), 0, proofsV2) 350 } 351 } 352 } 353 // Send the proof request and verify the response 354 switch protocol { 355 case 1: 356 cost := peer.GetRequestCost(GetProofsV1Msg, len(proofreqs)) 357 sendRequest(peer.app, GetProofsV1Msg, 42, cost, proofreqs) 358 if err := expectResponse(peer.app, ProofsV1Msg, 42, testBufLimit, proofsV1); err != nil { 359 t.Errorf("proofs mismatch: %v", err) 360 } 361 case 2: 362 cost := peer.GetRequestCost(GetProofsV2Msg, len(proofreqs)) 363 sendRequest(peer.app, GetProofsV2Msg, 42, cost, proofreqs) 364 if err := expectResponse(peer.app, ProofsV2Msg, 42, testBufLimit, proofsV2.NodeList()); err != nil { 365 t.Errorf("proofs mismatch: %v", err) 366 } 367 } 368 } 369 370 // Tests that CHT proofs can be correctly retrieved. 371 func TestGetCHTProofsLes1(t *testing.T) { testGetCHTProofs(t, 1) } 372 func TestGetCHTProofsLes2(t *testing.T) { testGetCHTProofs(t, 2) } 373 374 func testGetCHTProofs(t *testing.T, protocol int) { 375 // Figure out the client's CHT frequency 376 frequency := uint64(light.CHTFrequencyClient) 377 if protocol == 1 { 378 frequency = uint64(light.CHTFrequencyServer) 379 } 380 // Assemble the test environment 381 db, _ := ethdb.NewMemDatabase() 382 pm := newTestProtocolManagerMust(t, false, int(frequency)+light.HelperTrieProcessConfirmations, testChainGen, nil, nil, db) 383 bc := pm.blockchain.(*core.BlockChain) 384 peer, _ := newTestPeer(t, "peer", protocol, pm, true) 385 defer peer.close() 386 387 // Wait a while for the CHT indexer to process the new headers 388 time.Sleep(100 * time.Millisecond * time.Duration(frequency/light.CHTFrequencyServer)) // Chain indexer throttling 389 time.Sleep(250 * time.Millisecond) // CI tester slack 390 391 // Assemble the proofs from the different protocols 392 header := bc.GetHeaderByNumber(frequency) 393 rlp, _ := rlp.EncodeToBytes(header) 394 395 key := make([]byte, 8) 396 binary.BigEndian.PutUint64(key, frequency) 397 398 proofsV1 := []ChtResp{{ 399 Header: header, 400 }} 401 proofsV2 := HelperTrieResps{ 402 AuxData: [][]byte{rlp}, 403 } 404 switch protocol { 405 case 1: 406 root := light.GetChtRoot(db, 0, bc.GetHeaderByNumber(frequency-1).Hash()) 407 trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.ChtTablePrefix))) 408 409 var proof light.NodeList 410 trie.Prove(key, 0, &proof) 411 proofsV1[0].Proof = proof 412 413 case 2: 414 root := light.GetChtV2Root(db, 0, bc.GetHeaderByNumber(frequency-1).Hash()) 415 trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.ChtTablePrefix))) 416 trie.Prove(key, 0, &proofsV2.Proofs) 417 } 418 // Assemble the requests for the different protocols 419 requestsV1 := []ChtReq{{ 420 ChtNum: 1, 421 BlockNum: frequency, 422 }} 423 requestsV2 := []HelperTrieReq{{ 424 Type: htCanonical, 425 TrieIdx: 0, 426 Key: key, 427 AuxReq: auxHeader, 428 }} 429 // Send the proof request and verify the response 430 switch protocol { 431 case 1: 432 cost := peer.GetRequestCost(GetHeaderProofsMsg, len(requestsV1)) 433 sendRequest(peer.app, GetHeaderProofsMsg, 42, cost, requestsV1) 434 if err := expectResponse(peer.app, HeaderProofsMsg, 42, testBufLimit, proofsV1); err != nil { 435 t.Errorf("proofs mismatch: %v", err) 436 } 437 case 2: 438 cost := peer.GetRequestCost(GetHelperTrieProofsMsg, len(requestsV2)) 439 sendRequest(peer.app, GetHelperTrieProofsMsg, 42, cost, requestsV2) 440 if err := expectResponse(peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofsV2); err != nil { 441 t.Errorf("proofs mismatch: %v", err) 442 } 443 } 444 } 445 446 // Tests that bloombits proofs can be correctly retrieved. 447 func TestGetBloombitsProofs(t *testing.T) { 448 // Assemble the test environment 449 db, _ := ethdb.NewMemDatabase() 450 pm := newTestProtocolManagerMust(t, false, light.BloomTrieFrequency+256, testChainGen, nil, nil, db) 451 bc := pm.blockchain.(*core.BlockChain) 452 peer, _ := newTestPeer(t, "peer", 2, pm, true) 453 defer peer.close() 454 455 // Wait a while for the bloombits indexer to process the new headers 456 time.Sleep(100 * time.Millisecond * time.Duration(light.BloomTrieFrequency/4096)) // Chain indexer throttling 457 time.Sleep(250 * time.Millisecond) // CI tester slack 458 459 // Request and verify each bit of the bloom bits proofs 460 for bit := 0; bit < 2048; bit++ { 461 // Assemble therequest and proofs for the bloombits 462 key := make([]byte, 10) 463 464 binary.BigEndian.PutUint16(key[:2], uint16(bit)) 465 binary.BigEndian.PutUint64(key[2:], uint64(light.BloomTrieFrequency)) 466 467 requests := []HelperTrieReq{{ 468 Type: htBloomBits, 469 TrieIdx: 0, 470 Key: key, 471 }} 472 var proofs HelperTrieResps 473 474 root := light.GetBloomTrieRoot(db, 0, bc.GetHeaderByNumber(light.BloomTrieFrequency-1).Hash()) 475 trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(db, light.BloomTrieTablePrefix))) 476 trie.Prove(key, 0, &proofs.Proofs) 477 478 // Send the proof request and verify the response 479 cost := peer.GetRequestCost(GetHelperTrieProofsMsg, len(requests)) 480 sendRequest(peer.app, GetHelperTrieProofsMsg, 42, cost, requests) 481 if err := expectResponse(peer.app, HelperTrieProofsMsg, 42, testBufLimit, proofs); err != nil { 482 t.Errorf("bit %d: proofs mismatch: %v", bit, err) 483 } 484 } 485 } 486 487 func TestTransactionStatusLes2(t *testing.T) { 488 db, _ := ethdb.NewMemDatabase() 489 pm := newTestProtocolManagerMust(t, false, 0, nil, nil, nil, db) 490 chain := pm.blockchain.(*core.BlockChain) 491 config := core.DefaultTxPoolConfig 492 config.Journal = "" 493 txpool := core.NewTxPool(config, params.TestChainConfig, chain) 494 pm.txpool = txpool 495 peer, _ := newTestPeer(t, "peer", 2, pm, true) 496 defer peer.close() 497 498 var reqID uint64 499 500 test := func(tx *types.Transaction, send bool, expStatus txStatus) { 501 reqID++ 502 if send { 503 cost := peer.GetRequestCost(SendTxV2Msg, 1) 504 sendRequest(peer.app, SendTxV2Msg, reqID, cost, types.Transactions{tx}) 505 } else { 506 cost := peer.GetRequestCost(GetTxStatusMsg, 1) 507 sendRequest(peer.app, GetTxStatusMsg, reqID, cost, []common.Hash{tx.Hash()}) 508 } 509 if err := expectResponse(peer.app, TxStatusMsg, reqID, testBufLimit, []txStatus{expStatus}); err != nil { 510 t.Errorf("transaction status mismatch") 511 } 512 } 513 514 signer := types.HomesteadSigner{} 515 516 // test error status by sending an underpriced transaction 517 tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 518 test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced.Error()}) 519 520 tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey) 521 test(tx1, false, txStatus{Status: core.TxStatusUnknown}) // query before sending, should be unknown 522 test(tx1, true, txStatus{Status: core.TxStatusPending}) // send valid processable tx, should return pending 523 test(tx1, true, txStatus{Status: core.TxStatusPending}) // adding it again should not return an error 524 525 tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey) 526 tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey) 527 // send transactions in the wrong order, tx3 should be queued 528 test(tx3, true, txStatus{Status: core.TxStatusQueued}) 529 test(tx2, true, txStatus{Status: core.TxStatusPending}) 530 // query again, now tx3 should be pending too 531 test(tx3, false, txStatus{Status: core.TxStatusPending}) 532 533 // generate and add a block with tx1 and tx2 included 534 gchain, _ := core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) { 535 block.AddTx(tx1) 536 block.AddTx(tx2) 537 }) 538 if _, err := chain.InsertChain(gchain); err != nil { 539 panic(err) 540 } 541 // wait until TxPool processes the inserted block 542 for i := 0; i < 10; i++ { 543 if pending, _ := txpool.Stats(); pending == 1 { 544 break 545 } 546 time.Sleep(100 * time.Millisecond) 547 } 548 if pending, _ := txpool.Stats(); pending != 1 { 549 t.Fatalf("pending count mismatch: have %d, want 1", pending) 550 } 551 552 // check if their status is included now 553 block1hash := core.GetCanonicalHash(db, 1) 554 test(tx1, false, txStatus{Status: core.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}}) 555 test(tx2, false, txStatus{Status: core.TxStatusIncluded, Lookup: &core.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}}) 556 557 // create a reorg that rolls them back 558 gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 2, func(i int, block *core.BlockGen) {}) 559 if _, err := chain.InsertChain(gchain); err != nil { 560 panic(err) 561 } 562 // wait until TxPool processes the reorg 563 for i := 0; i < 10; i++ { 564 if pending, _ := txpool.Stats(); pending == 3 { 565 break 566 } 567 time.Sleep(100 * time.Millisecond) 568 } 569 if pending, _ := txpool.Stats(); pending != 3 { 570 t.Fatalf("pending count mismatch: have %d, want 3", pending) 571 } 572 // check if their status is pending again 573 test(tx1, false, txStatus{Status: core.TxStatusPending}) 574 test(tx2, false, txStatus{Status: core.TxStatusPending}) 575 }