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