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