github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/handler_test.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:39</date> 10 //</624450095424737280> 11 12 13 package les 14 15 import ( 16 "encoding/binary" 17 "math/big" 18 "math/rand" 19 "testing" 20 "time" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/consensus/ethash" 24 "github.com/ethereum/go-ethereum/core" 25 "github.com/ethereum/go-ethereum/core/rawdb" 26 "github.com/ethereum/go-ethereum/core/types" 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/eth/downloader" 29 "github.com/ethereum/go-ethereum/ethdb" 30 "github.com/ethereum/go-ethereum/light" 31 "github.com/ethereum/go-ethereum/p2p" 32 "github.com/ethereum/go-ethereum/params" 33 "github.com/ethereum/go-ethereum/rlp" 34 "github.com/ethereum/go-ethereum/trie" 35 ) 36 37 func expectResponse(r p2p.MsgReader, msgcode, reqID, bv uint64, data interface{}) error { 38 type resp struct { 39 ReqID, BV uint64 40 Data interface{} 41 } 42 return p2p.ExpectMsg(r, msgcode, resp{reqID, bv, data}) 43 } 44 45 //可以根据用户查询从远程链中检索阻止头的测试。 46 func TestGetBlockHeadersLes1(t *testing.T) { testGetBlockHeaders(t, 1) } 47 func TestGetBlockHeadersLes2(t *testing.T) { testGetBlockHeaders(t, 2) } 48 49 func testGetBlockHeaders(t *testing.T, protocol int) { 50 server, tearDown := newServerEnv(t, downloader.MaxHashFetch+15, protocol, nil) 51 defer tearDown() 52 bc := server.pm.blockchain.(*core.BlockChain) 53 54 //为测试创建一个“随机”的未知哈希 55 var unknown common.Hash 56 for i := range unknown { 57 unknown[i] = byte(i) 58 } 59 //为各种方案创建一批测试 60 limit := uint64(MaxHeaderFetch) 61 tests := []struct { 62 query *getBlockHeadersData //要为头检索执行的查询 63 expect []common.Hash //应为其头的块的哈希 64 }{ 65 //单个随机块也应该可以通过哈希和数字检索。 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 //应可从两个方向检索多个邮件头 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 //应检索具有跳过列表的多个邮件头 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 //链端点应该是可检索的 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 //确保遵守协议限制 114 /* 115 &getBlockHeadersData_origin:hashornumber_number:bc.currentBlock().numberU64()-1,amount:limit+10,reverse:true, 116 bc.getBlockHashesFromHash(bc.currentBlock().hash(),限制), 117 }*/ 118 119 //检查请求是否处理得当 120 { 121 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, 122 []common.Hash{ 123 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(), 124 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64()).Hash(), 125 }, 126 }, { 127 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, 128 []common.Hash{ 129 bc.GetBlockByNumber(4).Hash(), 130 bc.GetBlockByNumber(0).Hash(), 131 }, 132 }, 133 //检查请求是否处理得当,即使中间跳过 134 { 135 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, 136 []common.Hash{ 137 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 4).Hash(), 138 bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1).Hash(), 139 }, 140 }, { 141 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, 142 []common.Hash{ 143 bc.GetBlockByNumber(4).Hash(), 144 bc.GetBlockByNumber(1).Hash(), 145 }, 146 }, 147 //检查是否未返回不存在的邮件头 148 { 149 &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, 150 []common.Hash{}, 151 }, { 152 &getBlockHeadersData{Origin: hashOrNumber{Number: bc.CurrentBlock().NumberU64() + 1}, Amount: 1}, 153 []common.Hash{}, 154 }, 155 } 156 //运行每个测试并对照链验证结果 157 var reqID uint64 158 for i, tt := range tests { 159 //收集响应中预期的头 160 headers := []*types.Header{} 161 for _, hash := range tt.expect { 162 headers = append(headers, bc.GetHeaderByHash(hash)) 163 } 164 //发送哈希请求并验证响应 165 reqID++ 166 cost := server.tPeer.GetRequestCost(GetBlockHeadersMsg, int(tt.query.Amount)) 167 sendRequest(server.tPeer.app, GetBlockHeadersMsg, reqID, cost, tt.query) 168 if err := expectResponse(server.tPeer.app, BlockHeadersMsg, reqID, testBufLimit, headers); err != nil { 169 t.Errorf("test %d: headers mismatch: %v", i, err) 170 } 171 } 172 } 173 174 //可以基于哈希从远程链中检索阻止内容的测试。 175 func TestGetBlockBodiesLes1(t *testing.T) { testGetBlockBodies(t, 1) } 176 func TestGetBlockBodiesLes2(t *testing.T) { testGetBlockBodies(t, 2) } 177 178 func testGetBlockBodies(t *testing.T, protocol int) { 179 server, tearDown := newServerEnv(t, downloader.MaxBlockFetch+15, protocol, nil) 180 defer tearDown() 181 bc := server.pm.blockchain.(*core.BlockChain) 182 183 //为各种方案创建一批测试 184 limit := MaxBodyFetch 185 tests := []struct { 186 random int //从链中随机提取的块数 187 explicit []common.Hash //显式请求的块 188 available []bool //显式请求块的可用性 189 expected int //期望的现有块总数 190 }{ 191 {1, nil, nil, 1}, //单个随机块应该是可检索的 192 {10, nil, nil, 10}, //应可检索多个随机块 193 {limit, nil, nil, limit}, //最大可能的块应该是可检索的 194 //limit+1,nil,nil,limit,//返回的块数不应超过可能的块数 195 {0, []common.Hash{bc.Genesis().Hash()}, []bool{true}, 1}, //Genesis区块应该是可回收的。 196 {0, []common.Hash{bc.CurrentBlock().Hash()}, []bool{true}, 1}, //链头滑轮应可回收。 197 {0, []common.Hash{{}}, []bool{false}, 0}, //不应返回不存在的块 198 199 //现有和不存在的块交错不应导致问题 200 {0, []common.Hash{ 201 {}, 202 bc.GetBlockByNumber(1).Hash(), 203 {}, 204 bc.GetBlockByNumber(10).Hash(), 205 {}, 206 bc.GetBlockByNumber(100).Hash(), 207 {}, 208 }, []bool{false, true, false, true, false, true, false}, 3}, 209 } 210 //运行每个测试并对照链验证结果 211 var reqID uint64 212 for i, tt := range tests { 213 //收集要请求的哈希值和预期的响应 214 hashes, seen := []common.Hash{}, make(map[int64]bool) 215 bodies := []*types.Body{} 216 217 for j := 0; j < tt.random; j++ { 218 for { 219 num := rand.Int63n(int64(bc.CurrentBlock().NumberU64())) 220 if !seen[num] { 221 seen[num] = true 222 223 block := bc.GetBlockByNumber(uint64(num)) 224 hashes = append(hashes, block.Hash()) 225 if len(bodies) < tt.expected { 226 bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()}) 227 } 228 break 229 } 230 } 231 } 232 for j, hash := range tt.explicit { 233 hashes = append(hashes, hash) 234 if tt.available[j] && len(bodies) < tt.expected { 235 block := bc.GetBlockByHash(hash) 236 bodies = append(bodies, &types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()}) 237 } 238 } 239 reqID++ 240 //发送哈希请求并验证响应 241 cost := server.tPeer.GetRequestCost(GetBlockBodiesMsg, len(hashes)) 242 sendRequest(server.tPeer.app, GetBlockBodiesMsg, reqID, cost, hashes) 243 if err := expectResponse(server.tPeer.app, BlockBodiesMsg, reqID, testBufLimit, bodies); err != nil { 244 t.Errorf("test %d: bodies mismatch: %v", i, err) 245 } 246 } 247 } 248 249 //测试是否可以根据帐户地址检索合同代码。 250 func TestGetCodeLes1(t *testing.T) { testGetCode(t, 1) } 251 func TestGetCodeLes2(t *testing.T) { testGetCode(t, 2) } 252 253 func testGetCode(t *testing.T, protocol int) { 254 //组装测试环境 255 server, tearDown := newServerEnv(t, 4, protocol, nil) 256 defer tearDown() 257 bc := server.pm.blockchain.(*core.BlockChain) 258 259 var codereqs []*CodeReq 260 var codes [][]byte 261 262 for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { 263 header := bc.GetHeaderByNumber(i) 264 req := &CodeReq{ 265 BHash: header.Hash(), 266 AccKey: crypto.Keccak256(testContractAddr[:]), 267 } 268 codereqs = append(codereqs, req) 269 if i >= testContractDeployed { 270 codes = append(codes, testContractCodeDeployed) 271 } 272 } 273 274 cost := server.tPeer.GetRequestCost(GetCodeMsg, len(codereqs)) 275 sendRequest(server.tPeer.app, GetCodeMsg, 42, cost, codereqs) 276 if err := expectResponse(server.tPeer.app, CodeMsg, 42, testBufLimit, codes); err != nil { 277 t.Errorf("codes mismatch: %v", err) 278 } 279 } 280 281 //测试是否可以基于哈希值检索事务回执。 282 func TestGetReceiptLes1(t *testing.T) { testGetReceipt(t, 1) } 283 func TestGetReceiptLes2(t *testing.T) { testGetReceipt(t, 2) } 284 285 func testGetReceipt(t *testing.T, protocol int) { 286 //组装测试环境 287 server, tearDown := newServerEnv(t, 4, protocol, nil) 288 defer tearDown() 289 bc := server.pm.blockchain.(*core.BlockChain) 290 291 //收集要请求的哈希值和预期的响应 292 hashes, receipts := []common.Hash{}, []types.Receipts{} 293 for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { 294 block := bc.GetBlockByNumber(i) 295 296 hashes = append(hashes, block.Hash()) 297 receipts = append(receipts, rawdb.ReadReceipts(server.db, block.Hash(), block.NumberU64())) 298 } 299 //发送哈希请求并验证响应 300 cost := server.tPeer.GetRequestCost(GetReceiptsMsg, len(hashes)) 301 sendRequest(server.tPeer.app, GetReceiptsMsg, 42, cost, hashes) 302 if err := expectResponse(server.tPeer.app, ReceiptsMsg, 42, testBufLimit, receipts); err != nil { 303 t.Errorf("receipts mismatch: %v", err) 304 } 305 } 306 307 //可检索检索检索Merkle校对的测试 308 func TestGetProofsLes1(t *testing.T) { testGetProofs(t, 1) } 309 func TestGetProofsLes2(t *testing.T) { testGetProofs(t, 2) } 310 311 func testGetProofs(t *testing.T, protocol int) { 312 //组装测试环境 313 server, tearDown := newServerEnv(t, 4, protocol, nil) 314 defer tearDown() 315 bc := server.pm.blockchain.(*core.BlockChain) 316 317 var ( 318 proofreqs []ProofReq 319 proofsV1 [][]rlp.RawValue 320 ) 321 proofsV2 := light.NewNodeSet() 322 323 accounts := []common.Address{testBankAddress, acc1Addr, acc2Addr, {}} 324 for i := uint64(0); i <= bc.CurrentBlock().NumberU64(); i++ { 325 header := bc.GetHeaderByNumber(i) 326 root := header.Root 327 trie, _ := trie.New(root, trie.NewDatabase(server.db)) 328 329 for _, acc := range accounts { 330 req := ProofReq{ 331 BHash: header.Hash(), 332 Key: crypto.Keccak256(acc[:]), 333 } 334 proofreqs = append(proofreqs, req) 335 336 switch protocol { 337 case 1: 338 var proof light.NodeList 339 trie.Prove(crypto.Keccak256(acc[:]), 0, &proof) 340 proofsV1 = append(proofsV1, proof) 341 case 2: 342 trie.Prove(crypto.Keccak256(acc[:]), 0, proofsV2) 343 } 344 } 345 } 346 //发送证明请求并验证响应 347 switch protocol { 348 case 1: 349 cost := server.tPeer.GetRequestCost(GetProofsV1Msg, len(proofreqs)) 350 sendRequest(server.tPeer.app, GetProofsV1Msg, 42, cost, proofreqs) 351 if err := expectResponse(server.tPeer.app, ProofsV1Msg, 42, testBufLimit, proofsV1); err != nil { 352 t.Errorf("proofs mismatch: %v", err) 353 } 354 case 2: 355 cost := server.tPeer.GetRequestCost(GetProofsV2Msg, len(proofreqs)) 356 sendRequest(server.tPeer.app, GetProofsV2Msg, 42, cost, proofreqs) 357 if err := expectResponse(server.tPeer.app, ProofsV2Msg, 42, testBufLimit, proofsV2.NodeList()); err != nil { 358 t.Errorf("proofs mismatch: %v", err) 359 } 360 } 361 } 362 363 //能够正确检索CHT证明的测试。 364 func TestGetCHTProofsLes1(t *testing.T) { testGetCHTProofs(t, 1) } 365 func TestGetCHTProofsLes2(t *testing.T) { testGetCHTProofs(t, 2) } 366 367 func testGetCHTProofs(t *testing.T, protocol int) { 368 config := light.TestServerIndexerConfig 369 frequency := config.ChtSize 370 if protocol == 2 { 371 frequency = config.PairChtSize 372 } 373 374 waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) { 375 expectSections := frequency / config.ChtSize 376 for { 377 cs, _, _ := cIndexer.Sections() 378 bs, _, _ := bIndexer.Sections() 379 if cs >= expectSections && bs >= expectSections { 380 break 381 } 382 time.Sleep(10 * time.Millisecond) 383 } 384 } 385 server, tearDown := newServerEnv(t, int(frequency+config.ChtConfirms), protocol, waitIndexers) 386 defer tearDown() 387 bc := server.pm.blockchain.(*core.BlockChain) 388 389 //从不同的协议中收集证据 390 header := bc.GetHeaderByNumber(frequency - 1) 391 rlp, _ := rlp.EncodeToBytes(header) 392 393 key := make([]byte, 8) 394 binary.BigEndian.PutUint64(key, frequency-1) 395 396 proofsV1 := []ChtResp{{ 397 Header: header, 398 }} 399 proofsV2 := HelperTrieResps{ 400 AuxData: [][]byte{rlp}, 401 } 402 switch protocol { 403 case 1: 404 root := light.GetChtRoot(server.db, 0, bc.GetHeaderByNumber(frequency-1).Hash()) 405 trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(server.db, light.ChtTablePrefix))) 406 407 var proof light.NodeList 408 trie.Prove(key, 0, &proof) 409 proofsV1[0].Proof = proof 410 411 case 2: 412 root := light.GetChtRoot(server.db, (frequency/config.ChtSize)-1, bc.GetHeaderByNumber(frequency-1).Hash()) 413 trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(server.db, light.ChtTablePrefix))) 414 trie.Prove(key, 0, &proofsV2.Proofs) 415 } 416 //汇编不同协议的请求 417 requestsV1 := []ChtReq{{ 418 ChtNum: frequency / config.ChtSize, 419 BlockNum: frequency - 1, 420 }} 421 requestsV2 := []HelperTrieReq{{ 422 Type: htCanonical, 423 TrieIdx: frequency/config.PairChtSize - 1, 424 Key: key, 425 AuxReq: auxHeader, 426 }} 427 //发送证明请求并验证响应 428 switch protocol { 429 case 1: 430 cost := server.tPeer.GetRequestCost(GetHeaderProofsMsg, len(requestsV1)) 431 sendRequest(server.tPeer.app, GetHeaderProofsMsg, 42, cost, requestsV1) 432 if err := expectResponse(server.tPeer.app, HeaderProofsMsg, 42, testBufLimit, proofsV1); err != nil { 433 t.Errorf("proofs mismatch: %v", err) 434 } 435 case 2: 436 cost := server.tPeer.GetRequestCost(GetHelperTrieProofsMsg, len(requestsV2)) 437 sendRequest(server.tPeer.app, GetHelperTrieProofsMsg, 42, cost, requestsV2) 438 if err := expectResponse(server.tPeer.app, HelperTrieProofsMsg, 42, testBufLimit, proofsV2); err != nil { 439 t.Errorf("proofs mismatch: %v", err) 440 } 441 } 442 } 443 444 //可以正确检索Bloombits校对的测试。 445 func TestGetBloombitsProofs(t *testing.T) { 446 config := light.TestServerIndexerConfig 447 448 waitIndexers := func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) { 449 for { 450 cs, _, _ := cIndexer.Sections() 451 bs, _, _ := bIndexer.Sections() 452 bts, _, _ := btIndexer.Sections() 453 if cs >= 8 && bs >= 8 && bts >= 1 { 454 break 455 } 456 time.Sleep(10 * time.Millisecond) 457 } 458 } 459 server, tearDown := newServerEnv(t, int(config.BloomTrieSize+config.BloomTrieConfirms), 2, waitIndexers) 460 defer tearDown() 461 bc := server.pm.blockchain.(*core.BlockChain) 462 463 //请求并验证每个bloom位的证明 464 for bit := 0; bit < 2048; bit++ { 465 //为Bloombits收集请求和证据 466 key := make([]byte, 10) 467 468 binary.BigEndian.PutUint16(key[:2], uint16(bit)) 469 //只有第一个Bloom部分有数据。 470 binary.BigEndian.PutUint64(key[2:], 0) 471 472 requests := []HelperTrieReq{{ 473 Type: htBloomBits, 474 TrieIdx: 0, 475 Key: key, 476 }} 477 var proofs HelperTrieResps 478 479 root := light.GetBloomTrieRoot(server.db, 0, bc.GetHeaderByNumber(config.BloomTrieSize-1).Hash()) 480 trie, _ := trie.New(root, trie.NewDatabase(ethdb.NewTable(server.db, light.BloomTrieTablePrefix))) 481 trie.Prove(key, 0, &proofs.Proofs) 482 483 //发送证明请求并验证响应 484 cost := server.tPeer.GetRequestCost(GetHelperTrieProofsMsg, len(requests)) 485 sendRequest(server.tPeer.app, GetHelperTrieProofsMsg, 42, cost, requests) 486 if err := expectResponse(server.tPeer.app, HelperTrieProofsMsg, 42, testBufLimit, proofs); err != nil { 487 t.Errorf("bit %d: proofs mismatch: %v", bit, err) 488 } 489 } 490 } 491 492 func TestTransactionStatusLes2(t *testing.T) { 493 db := ethdb.NewMemDatabase() 494 pm := newTestProtocolManagerMust(t, false, 0, nil, nil, nil, db) 495 chain := pm.blockchain.(*core.BlockChain) 496 config := core.DefaultTxPoolConfig 497 config.Journal = "" 498 txpool := core.NewTxPool(config, params.TestChainConfig, chain) 499 pm.txpool = txpool 500 peer, _ := newTestPeer(t, "peer", 2, pm, true) 501 defer peer.close() 502 503 var reqID uint64 504 505 test := func(tx *types.Transaction, send bool, expStatus txStatus) { 506 reqID++ 507 if send { 508 cost := peer.GetRequestCost(SendTxV2Msg, 1) 509 sendRequest(peer.app, SendTxV2Msg, reqID, cost, types.Transactions{tx}) 510 } else { 511 cost := peer.GetRequestCost(GetTxStatusMsg, 1) 512 sendRequest(peer.app, GetTxStatusMsg, reqID, cost, []common.Hash{tx.Hash()}) 513 } 514 if err := expectResponse(peer.app, TxStatusMsg, reqID, testBufLimit, []txStatus{expStatus}); err != nil { 515 t.Errorf("transaction status mismatch") 516 } 517 } 518 519 signer := types.HomesteadSigner{} 520 521 //通过发送定价过低的事务来测试错误状态 522 tx0, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 523 test(tx0, true, txStatus{Status: core.TxStatusUnknown, Error: core.ErrUnderpriced.Error()}) 524 525 tx1, _ := types.SignTx(types.NewTransaction(0, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey) 526 test(tx1, false, txStatus{Status: core.TxStatusUnknown}) //发送前查询,应为未知 527 test(tx1, true, txStatus{Status: core.TxStatusPending}) //发送有效的可处理Tx,应返回挂起 528 test(tx1, true, txStatus{Status: core.TxStatusPending}) //再次添加不应返回错误 529 530 tx2, _ := types.SignTx(types.NewTransaction(1, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey) 531 tx3, _ := types.SignTx(types.NewTransaction(2, acc1Addr, big.NewInt(10000), params.TxGas, big.NewInt(100000000000), nil), signer, testBankKey) 532 //send transactions in the wrong order, tx3 should be queued 533 test(tx3, true, txStatus{Status: core.TxStatusQueued}) 534 test(tx2, true, txStatus{Status: core.TxStatusPending}) 535 //再次查询,现在tx3也应该挂起 536 test(tx3, false, txStatus{Status: core.TxStatusPending}) 537 538 //生成并添加包含tx1和tx2的块 539 gchain, _ := core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 1, func(i int, block *core.BlockGen) { 540 block.AddTx(tx1) 541 block.AddTx(tx2) 542 }) 543 if _, err := chain.InsertChain(gchain); err != nil { 544 panic(err) 545 } 546 //等待txpool处理插入的块 547 for i := 0; i < 10; i++ { 548 if pending, _ := txpool.Stats(); pending == 1 { 549 break 550 } 551 time.Sleep(100 * time.Millisecond) 552 } 553 if pending, _ := txpool.Stats(); pending != 1 { 554 t.Fatalf("pending count mismatch: have %d, want 1", pending) 555 } 556 557 //检查他们的状态现在是否包括在内 558 block1hash := rawdb.ReadCanonicalHash(db, 1) 559 test(tx1, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 0}}) 560 test(tx2, false, txStatus{Status: core.TxStatusIncluded, Lookup: &rawdb.TxLookupEntry{BlockHash: block1hash, BlockIndex: 1, Index: 1}}) 561 562 //创建一个REORG,将其回滚 563 gchain, _ = core.GenerateChain(params.TestChainConfig, chain.GetBlockByNumber(0), ethash.NewFaker(), db, 2, func(i int, block *core.BlockGen) {}) 564 if _, err := chain.InsertChain(gchain); err != nil { 565 panic(err) 566 } 567 //等待txpool处理REORG 568 for i := 0; i < 10; i++ { 569 if pending, _ := txpool.Stats(); pending == 3 { 570 break 571 } 572 time.Sleep(100 * time.Millisecond) 573 } 574 if pending, _ := txpool.Stats(); pending != 3 { 575 t.Fatalf("pending count mismatch: have %d, want 3", pending) 576 } 577 //检查其状态是否再次处于挂起状态 578 test(tx1, false, txStatus{Status: core.TxStatusPending}) 579 test(tx2, false, txStatus{Status: core.TxStatusPending}) 580 } 581