github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/fetcher/fetcher_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 12:09:38</date>
    10  //</624342634571239424>
    11  
    12  
    13  package fetcher
    14  
    15  import (
    16  	"errors"
    17  	"math/big"
    18  	"sync"
    19  	"sync/atomic"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/consensus/ethash"
    25  	"github.com/ethereum/go-ethereum/core"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/crypto"
    28  	"github.com/ethereum/go-ethereum/ethdb"
    29  	"github.com/ethereum/go-ethereum/params"
    30  )
    31  
    32  var (
    33  	testdb       = ethdb.NewMemDatabase()
    34  	testKey, _   = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    35  	testAddress  = crypto.PubkeyToAddress(testKey.PublicKey)
    36  	genesis      = core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000))
    37  	unknownBlock = types.NewBlock(&types.Header{GasLimit: params.GenesisGasLimit}, nil, nil, nil)
    38  )
    39  
    40  //makechain创建一个由n个块组成的链,从父块开始并包含父块。
    41  //返回的哈希链是有序的head->parent。此外,每三个街区
    42  //包含一个事务,每隔5分钟一个叔叔以允许测试正确的块
    43  //重新组装。
    44  func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common.Hash]*types.Block) {
    45  	blocks, _ := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), testdb, n, func(i int, block *core.BlockGen) {
    46  		block.SetCoinbase(common.Address{seed})
    47  
    48  //如果区块号是3的倍数,则向矿工发送奖金交易。
    49  		if parent == genesis && i%3 == 0 {
    50  			signer := types.MakeSigner(params.TestChainConfig, block.Number())
    51  			tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, nil, nil), signer, testKey)
    52  			if err != nil {
    53  				panic(err)
    54  			}
    55  			block.AddTx(tx)
    56  		}
    57  //如果区块编号是5的倍数,请在区块中添加一个奖金叔叔。
    58  		if i%5 == 0 {
    59  			block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))})
    60  		}
    61  	})
    62  	hashes := make([]common.Hash, n+1)
    63  	hashes[len(hashes)-1] = parent.Hash()
    64  	blockm := make(map[common.Hash]*types.Block, n+1)
    65  	blockm[parent.Hash()] = parent
    66  	for i, b := range blocks {
    67  		hashes[len(hashes)-i-2] = b.Hash()
    68  		blockm[b.Hash()] = b
    69  	}
    70  	return hashes, blockm
    71  }
    72  
    73  //Fetchertester是模拟本地块链的测试模拟器。
    74  type fetcherTester struct {
    75  	fetcher *Fetcher
    76  
    77  hashes []common.Hash                //属于测试人员的哈希链
    78  blocks map[common.Hash]*types.Block //属于测试仪的块
    79  drops  map[string]bool              //取方丢弃的对等点图
    80  
    81  	lock sync.RWMutex
    82  }
    83  
    84  //NewTester创建一个新的获取器测试mocker。
    85  func newTester() *fetcherTester {
    86  	tester := &fetcherTester{
    87  		hashes: []common.Hash{genesis.Hash()},
    88  		blocks: map[common.Hash]*types.Block{genesis.Hash(): genesis},
    89  		drops:  make(map[string]bool),
    90  	}
    91  	tester.fetcher = New(tester.getBlock, tester.verifyHeader, tester.broadcastBlock, tester.chainHeight, tester.insertChain, tester.dropPeer)
    92  	tester.fetcher.Start()
    93  
    94  	return tester
    95  }
    96  
    97  //GetBlock从测试仪的区块链中检索一个区块。
    98  func (f *fetcherTester) getBlock(hash common.Hash) *types.Block {
    99  	f.lock.RLock()
   100  	defer f.lock.RUnlock()
   101  
   102  	return f.blocks[hash]
   103  }
   104  
   105  //verifyheader是块头验证的nop占位符。
   106  func (f *fetcherTester) verifyHeader(header *types.Header) error {
   107  	return nil
   108  }
   109  
   110  //BroadcastBlock是块广播的NOP占位符。
   111  func (f *fetcherTester) broadcastBlock(block *types.Block, propagate bool) {
   112  }
   113  
   114  //chain height检索链的当前高度(块号)。
   115  func (f *fetcherTester) chainHeight() uint64 {
   116  	f.lock.RLock()
   117  	defer f.lock.RUnlock()
   118  
   119  	return f.blocks[f.hashes[len(f.hashes)-1]].NumberU64()
   120  }
   121  
   122  //insertchain向模拟链中注入新的块。
   123  func (f *fetcherTester) insertChain(blocks types.Blocks) (int, error) {
   124  	f.lock.Lock()
   125  	defer f.lock.Unlock()
   126  
   127  	for i, block := range blocks {
   128  //确保中的父级
   129  		if _, ok := f.blocks[block.ParentHash()]; !ok {
   130  			return i, errors.New("unknown parent")
   131  		}
   132  //如果已经存在相同高度,则丢弃所有新块
   133  		if block.NumberU64() <= f.blocks[f.hashes[len(f.hashes)-1]].NumberU64() {
   134  			return i, nil
   135  		}
   136  //否则就建立我们现在的链条
   137  		f.hashes = append(f.hashes, block.Hash())
   138  		f.blocks[block.Hash()] = block
   139  	}
   140  	return 0, nil
   141  }
   142  
   143  //Droppeer是一个对等删除的仿真器,只需将
   144  //同龄人被牵线人甩了。
   145  func (f *fetcherTester) dropPeer(peer string) {
   146  	f.lock.Lock()
   147  	defer f.lock.Unlock()
   148  
   149  	f.drops[peer] = true
   150  }
   151  
   152  //MakeHeaderFetcher检索与模拟对等机关联的块头获取程序。
   153  func (f *fetcherTester) makeHeaderFetcher(peer string, blocks map[common.Hash]*types.Block, drift time.Duration) headerRequesterFn {
   154  	closure := make(map[common.Hash]*types.Block)
   155  	for hash, block := range blocks {
   156  		closure[hash] = block
   157  	}
   158  //创建一个从闭包返回头的函数
   159  	return func(hash common.Hash) error {
   160  //收集积木返回
   161  		headers := make([]*types.Header, 0, 1)
   162  		if block, ok := closure[hash]; ok {
   163  			headers = append(headers, block.Header())
   164  		}
   165  //返回新线程
   166  		go f.fetcher.FilterHeaders(peer, headers, time.Now().Add(drift))
   167  
   168  		return nil
   169  	}
   170  }
   171  
   172  //MakeBodyFetcher检索与模拟对等体关联的块体Fetcher。
   173  func (f *fetcherTester) makeBodyFetcher(peer string, blocks map[common.Hash]*types.Block, drift time.Duration) bodyRequesterFn {
   174  	closure := make(map[common.Hash]*types.Block)
   175  	for hash, block := range blocks {
   176  		closure[hash] = block
   177  	}
   178  //创建从闭包返回块的函数
   179  	return func(hashes []common.Hash) error {
   180  //收集块体返回
   181  		transactions := make([][]*types.Transaction, 0, len(hashes))
   182  		uncles := make([][]*types.Header, 0, len(hashes))
   183  
   184  		for _, hash := range hashes {
   185  			if block, ok := closure[hash]; ok {
   186  				transactions = append(transactions, block.Transactions())
   187  				uncles = append(uncles, block.Uncles())
   188  			}
   189  		}
   190  //返回新线程
   191  		go f.fetcher.FilterBodies(peer, transactions, uncles, time.Now().Add(drift))
   192  
   193  		return nil
   194  	}
   195  }
   196  
   197  //VerifyFetchingEvent验证单个事件是否到达提取通道。
   198  func verifyFetchingEvent(t *testing.T, fetching chan []common.Hash, arrive bool) {
   199  	if arrive {
   200  		select {
   201  		case <-fetching:
   202  		case <-time.After(time.Second):
   203  			t.Fatalf("fetching timeout")
   204  		}
   205  	} else {
   206  		select {
   207  		case <-fetching:
   208  			t.Fatalf("fetching invoked")
   209  		case <-time.After(10 * time.Millisecond):
   210  		}
   211  	}
   212  }
   213  
   214  //VerifyCompletingEvent验证单个事件是否到达完成通道。
   215  func verifyCompletingEvent(t *testing.T, completing chan []common.Hash, arrive bool) {
   216  	if arrive {
   217  		select {
   218  		case <-completing:
   219  		case <-time.After(time.Second):
   220  			t.Fatalf("completing timeout")
   221  		}
   222  	} else {
   223  		select {
   224  		case <-completing:
   225  			t.Fatalf("completing invoked")
   226  		case <-time.After(10 * time.Millisecond):
   227  		}
   228  	}
   229  }
   230  
   231  //verifyimportevent验证一个事件是否到达导入通道。
   232  func verifyImportEvent(t *testing.T, imported chan *types.Block, arrive bool) {
   233  	if arrive {
   234  		select {
   235  		case <-imported:
   236  		case <-time.After(time.Second):
   237  			t.Fatalf("import timeout")
   238  		}
   239  	} else {
   240  		select {
   241  		case <-imported:
   242  			t.Fatalf("import invoked")
   243  		case <-time.After(10 * time.Millisecond):
   244  		}
   245  	}
   246  }
   247  
   248  //verifyimportcount验证在
   249  //导入挂钩通道。
   250  func verifyImportCount(t *testing.T, imported chan *types.Block, count int) {
   251  	for i := 0; i < count; i++ {
   252  		select {
   253  		case <-imported:
   254  		case <-time.After(time.Second):
   255  			t.Fatalf("block %d: import timeout", i+1)
   256  		}
   257  	}
   258  	verifyImportDone(t, imported)
   259  }
   260  
   261  //verifyimportdone验证导入通道上没有其他事件到达。
   262  func verifyImportDone(t *testing.T, imported chan *types.Block) {
   263  	select {
   264  	case <-imported:
   265  		t.Fatalf("extra block imported")
   266  	case <-time.After(50 * time.Millisecond):
   267  	}
   268  }
   269  
   270  //测试获取程序接受块通知并为
   271  //成功导入到本地链。
   272  func TestSequentialAnnouncements62(t *testing.T) { testSequentialAnnouncements(t, 62) }
   273  func TestSequentialAnnouncements63(t *testing.T) { testSequentialAnnouncements(t, 63) }
   274  func TestSequentialAnnouncements64(t *testing.T) { testSequentialAnnouncements(t, 64) }
   275  
   276  func testSequentialAnnouncements(t *testing.T, protocol int) {
   277  //创建要导入的块链
   278  	targetBlocks := 4 * hashLimit
   279  	hashes, blocks := makeChain(targetBlocks, 0, genesis)
   280  
   281  	tester := newTester()
   282  	headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack)
   283  	bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0)
   284  
   285  //迭代地通知块,直到全部导入
   286  	imported := make(chan *types.Block)
   287  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   288  
   289  	for i := len(hashes) - 2; i >= 0; i-- {
   290  		tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   291  		verifyImportEvent(t, imported, true)
   292  	}
   293  	verifyImportDone(t, imported)
   294  }
   295  
   296  //测试多个对等方(甚至同一个bug)是否宣布块
   297  //它们最多只能下载一次。
   298  func TestConcurrentAnnouncements62(t *testing.T) { testConcurrentAnnouncements(t, 62) }
   299  func TestConcurrentAnnouncements63(t *testing.T) { testConcurrentAnnouncements(t, 63) }
   300  func TestConcurrentAnnouncements64(t *testing.T) { testConcurrentAnnouncements(t, 64) }
   301  
   302  func testConcurrentAnnouncements(t *testing.T, protocol int) {
   303  //创建要导入的块链
   304  	targetBlocks := 4 * hashLimit
   305  	hashes, blocks := makeChain(targetBlocks, 0, genesis)
   306  
   307  //为请求装配带有内置计数器的测试仪
   308  	tester := newTester()
   309  	firstHeaderFetcher := tester.makeHeaderFetcher("first", blocks, -gatherSlack)
   310  	firstBodyFetcher := tester.makeBodyFetcher("first", blocks, 0)
   311  	secondHeaderFetcher := tester.makeHeaderFetcher("second", blocks, -gatherSlack)
   312  	secondBodyFetcher := tester.makeBodyFetcher("second", blocks, 0)
   313  
   314  	counter := uint32(0)
   315  	firstHeaderWrapper := func(hash common.Hash) error {
   316  		atomic.AddUint32(&counter, 1)
   317  		return firstHeaderFetcher(hash)
   318  	}
   319  	secondHeaderWrapper := func(hash common.Hash) error {
   320  		atomic.AddUint32(&counter, 1)
   321  		return secondHeaderFetcher(hash)
   322  	}
   323  //迭代地通知块,直到全部导入
   324  	imported := make(chan *types.Block)
   325  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   326  
   327  	for i := len(hashes) - 2; i >= 0; i-- {
   328  		tester.fetcher.Notify("first", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), firstHeaderWrapper, firstBodyFetcher)
   329  		tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout+time.Millisecond), secondHeaderWrapper, secondBodyFetcher)
   330  		tester.fetcher.Notify("second", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout-time.Millisecond), secondHeaderWrapper, secondBodyFetcher)
   331  		verifyImportEvent(t, imported, true)
   332  	}
   333  	verifyImportDone(t, imported)
   334  
   335  //确保两次未检索到任何块
   336  	if int(counter) != targetBlocks {
   337  		t.Fatalf("retrieval count mismatch: have %v, want %v", counter, targetBlocks)
   338  	}
   339  }
   340  
   341  //在提取前一个通知时通知到达的测试
   342  //导致有效导入。
   343  func TestOverlappingAnnouncements62(t *testing.T) { testOverlappingAnnouncements(t, 62) }
   344  func TestOverlappingAnnouncements63(t *testing.T) { testOverlappingAnnouncements(t, 63) }
   345  func TestOverlappingAnnouncements64(t *testing.T) { testOverlappingAnnouncements(t, 64) }
   346  
   347  func testOverlappingAnnouncements(t *testing.T, protocol int) {
   348  //创建要导入的块链
   349  	targetBlocks := 4 * hashLimit
   350  	hashes, blocks := makeChain(targetBlocks, 0, genesis)
   351  
   352  	tester := newTester()
   353  	headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack)
   354  	bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0)
   355  
   356  //迭代地通知块,但连续地重叠它们
   357  	overlap := 16
   358  	imported := make(chan *types.Block, len(hashes)-1)
   359  	for i := 0; i < overlap; i++ {
   360  		imported <- nil
   361  	}
   362  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   363  
   364  	for i := len(hashes) - 2; i >= 0; i-- {
   365  		tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   366  		select {
   367  		case <-imported:
   368  		case <-time.After(time.Second):
   369  			t.Fatalf("block %d: import timeout", len(hashes)-i)
   370  		}
   371  	}
   372  //等待所有导入完成并检查计数
   373  	verifyImportCount(t, imported, overlap)
   374  }
   375  
   376  //宣布已检索的测试将不会重复。
   377  func TestPendingDeduplication62(t *testing.T) { testPendingDeduplication(t, 62) }
   378  func TestPendingDeduplication63(t *testing.T) { testPendingDeduplication(t, 63) }
   379  func TestPendingDeduplication64(t *testing.T) { testPendingDeduplication(t, 64) }
   380  
   381  func testPendingDeduplication(t *testing.T, protocol int) {
   382  //创建哈希和相应的块
   383  	hashes, blocks := makeChain(1, 0, genesis)
   384  
   385  //用内置计数器和延迟回卷器组装测试仪
   386  	tester := newTester()
   387  	headerFetcher := tester.makeHeaderFetcher("repeater", blocks, -gatherSlack)
   388  	bodyFetcher := tester.makeBodyFetcher("repeater", blocks, 0)
   389  
   390  	delay := 50 * time.Millisecond
   391  	counter := uint32(0)
   392  	headerWrapper := func(hash common.Hash) error {
   393  		atomic.AddUint32(&counter, 1)
   394  
   395  //模拟长时间运行的获取
   396  		go func() {
   397  			time.Sleep(delay)
   398  			headerFetcher(hash)
   399  		}()
   400  		return nil
   401  	}
   402  //多次通知同一个块,直到它被提取(等待任何挂起的操作)
   403  	for tester.getBlock(hashes[0]) == nil {
   404  		tester.fetcher.Notify("repeater", hashes[0], 1, time.Now().Add(-arriveTimeout), headerWrapper, bodyFetcher)
   405  		time.Sleep(time.Millisecond)
   406  	}
   407  	time.Sleep(delay)
   408  
   409  //检查是否已导入所有块,并且未提取两次
   410  	if imported := len(tester.blocks); imported != 2 {
   411  		t.Fatalf("synchronised block mismatch: have %v, want %v", imported, 2)
   412  	}
   413  	if int(counter) != 1 {
   414  		t.Fatalf("retrieval count mismatch: have %v, want %v", counter, 1)
   415  	}
   416  }
   417  
   418  //以随机顺序检索公告的测试将被缓存,并最终
   419  //填充所有间隙时导入。
   420  func TestRandomArrivalImport62(t *testing.T) { testRandomArrivalImport(t, 62) }
   421  func TestRandomArrivalImport63(t *testing.T) { testRandomArrivalImport(t, 63) }
   422  func TestRandomArrivalImport64(t *testing.T) { testRandomArrivalImport(t, 64) }
   423  
   424  func testRandomArrivalImport(t *testing.T, protocol int) {
   425  //创建要导入的块链,然后选择一个要延迟的块链
   426  	targetBlocks := maxQueueDist
   427  	hashes, blocks := makeChain(targetBlocks, 0, genesis)
   428  	skip := targetBlocks / 2
   429  
   430  	tester := newTester()
   431  	headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack)
   432  	bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0)
   433  
   434  //迭代地通知块,跳过一个条目
   435  	imported := make(chan *types.Block, len(hashes)-1)
   436  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   437  
   438  	for i := len(hashes) - 1; i >= 0; i-- {
   439  		if i != skip {
   440  			tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   441  			time.Sleep(time.Millisecond)
   442  		}
   443  	}
   444  //最后宣布跳过的条目并检查完全导入
   445  	tester.fetcher.Notify("valid", hashes[skip], uint64(len(hashes)-skip-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   446  	verifyImportCount(t, imported, len(hashes)-1)
   447  }
   448  
   449  //引导块排队的测试(由于块传播与哈希公告)
   450  //正确安排、填充和导入队列间隙。
   451  func TestQueueGapFill62(t *testing.T) { testQueueGapFill(t, 62) }
   452  func TestQueueGapFill63(t *testing.T) { testQueueGapFill(t, 63) }
   453  func TestQueueGapFill64(t *testing.T) { testQueueGapFill(t, 64) }
   454  
   455  func testQueueGapFill(t *testing.T, protocol int) {
   456  //创建一个要导入的块链,并选择一个完全不公告的块链
   457  	targetBlocks := maxQueueDist
   458  	hashes, blocks := makeChain(targetBlocks, 0, genesis)
   459  	skip := targetBlocks / 2
   460  
   461  	tester := newTester()
   462  	headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack)
   463  	bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0)
   464  
   465  //迭代地通知块,跳过一个条目
   466  	imported := make(chan *types.Block, len(hashes)-1)
   467  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   468  
   469  	for i := len(hashes) - 1; i >= 0; i-- {
   470  		if i != skip {
   471  			tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   472  			time.Sleep(time.Millisecond)
   473  		}
   474  	}
   475  //直接填充缺失的块,就像传播一样
   476  	tester.fetcher.Enqueue("valid", blocks[hashes[skip]])
   477  	verifyImportCount(t, imported, len(hashes)-1)
   478  }
   479  
   480  //阻止来自不同源(多个传播、哈希)的测试
   481  //不安排多次导入。
   482  func TestImportDeduplication62(t *testing.T) { testImportDeduplication(t, 62) }
   483  func TestImportDeduplication63(t *testing.T) { testImportDeduplication(t, 63) }
   484  func TestImportDeduplication64(t *testing.T) { testImportDeduplication(t, 64) }
   485  
   486  func testImportDeduplication(t *testing.T, protocol int) {
   487  //创建两个要导入的块(一个用于复制,另一个用于暂停)
   488  	hashes, blocks := makeChain(2, 0, genesis)
   489  
   490  //创建检测仪并用计数器包装进口商
   491  	tester := newTester()
   492  	headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack)
   493  	bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0)
   494  
   495  	counter := uint32(0)
   496  	tester.fetcher.insertChain = func(blocks types.Blocks) (int, error) {
   497  		atomic.AddUint32(&counter, uint32(len(blocks)))
   498  		return tester.insertChain(blocks)
   499  	}
   500  //检测获取和导入的事件
   501  	fetching := make(chan []common.Hash)
   502  	imported := make(chan *types.Block, len(hashes)-1)
   503  	tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- hashes }
   504  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   505  
   506  //通知复制块,等待检索,并直接传播
   507  	tester.fetcher.Notify("valid", hashes[0], 1, time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   508  	<-fetching
   509  
   510  	tester.fetcher.Enqueue("valid", blocks[hashes[0]])
   511  	tester.fetcher.Enqueue("valid", blocks[hashes[0]])
   512  	tester.fetcher.Enqueue("valid", blocks[hashes[0]])
   513  
   514  //像传播一样直接填充缺失的块,并检查导入的唯一性
   515  	tester.fetcher.Enqueue("valid", blocks[hashes[1]])
   516  	verifyImportCount(t, imported, 2)
   517  
   518  	if counter != 2 {
   519  		t.Fatalf("import invocation count mismatch: have %v, want %v", counter, 2)
   520  	}
   521  }
   522  
   523  //用远低于或高于当前磁头的数字阻塞的测试得到
   524  //丢弃以防止将资源浪费在来自故障对等机的无用块上。
   525  func TestDistantPropagationDiscarding(t *testing.T) {
   526  //创建一个长链以导入和定义丢弃边界
   527  	hashes, blocks := makeChain(3*maxQueueDist, 0, genesis)
   528  	head := hashes[len(hashes)/2]
   529  
   530  	low, high := len(hashes)/2+maxUncleDist+1, len(hashes)/2-maxQueueDist-1
   531  
   532  //创建一个测试仪并模拟上边链中间的头块
   533  	tester := newTester()
   534  
   535  	tester.lock.Lock()
   536  	tester.hashes = []common.Hash{head}
   537  	tester.blocks = map[common.Hash]*types.Block{head: blocks[head]}
   538  	tester.lock.Unlock()
   539  
   540  //确保丢弃数字低于阈值的块
   541  	tester.fetcher.Enqueue("lower", blocks[hashes[low]])
   542  	time.Sleep(10 * time.Millisecond)
   543  	if !tester.fetcher.queue.Empty() {
   544  		t.Fatalf("fetcher queued stale block")
   545  	}
   546  //确保丢弃数字高于阈值的块
   547  	tester.fetcher.Enqueue("higher", blocks[hashes[high]])
   548  	time.Sleep(10 * time.Millisecond)
   549  	if !tester.fetcher.queue.Empty() {
   550  		t.Fatalf("fetcher queued future block")
   551  	}
   552  }
   553  
   554  //数字远低于或高于输出电流的测试
   555  //头被丢弃,以防止浪费资源在无用的块故障
   556  //同龄人。
   557  func TestDistantAnnouncementDiscarding62(t *testing.T) { testDistantAnnouncementDiscarding(t, 62) }
   558  func TestDistantAnnouncementDiscarding63(t *testing.T) { testDistantAnnouncementDiscarding(t, 63) }
   559  func TestDistantAnnouncementDiscarding64(t *testing.T) { testDistantAnnouncementDiscarding(t, 64) }
   560  
   561  func testDistantAnnouncementDiscarding(t *testing.T, protocol int) {
   562  //创建一个长链以导入和定义丢弃边界
   563  	hashes, blocks := makeChain(3*maxQueueDist, 0, genesis)
   564  	head := hashes[len(hashes)/2]
   565  
   566  	low, high := len(hashes)/2+maxUncleDist+1, len(hashes)/2-maxQueueDist-1
   567  
   568  //创建一个测试仪并模拟上边链中间的头块
   569  	tester := newTester()
   570  
   571  	tester.lock.Lock()
   572  	tester.hashes = []common.Hash{head}
   573  	tester.blocks = map[common.Hash]*types.Block{head: blocks[head]}
   574  	tester.lock.Unlock()
   575  
   576  	headerFetcher := tester.makeHeaderFetcher("lower", blocks, -gatherSlack)
   577  	bodyFetcher := tester.makeBodyFetcher("lower", blocks, 0)
   578  
   579  	fetching := make(chan struct{}, 2)
   580  	tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- struct{}{} }
   581  
   582  //确保丢弃数字低于阈值的块
   583  	tester.fetcher.Notify("lower", hashes[low], blocks[hashes[low]].NumberU64(), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   584  	select {
   585  	case <-time.After(50 * time.Millisecond):
   586  	case <-fetching:
   587  		t.Fatalf("fetcher requested stale header")
   588  	}
   589  //确保丢弃数字高于阈值的块
   590  	tester.fetcher.Notify("higher", hashes[high], blocks[hashes[high]].NumberU64(), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   591  	select {
   592  	case <-time.After(50 * time.Millisecond):
   593  	case <-fetching:
   594  		t.Fatalf("fetcher requested future header")
   595  	}
   596  }
   597  
   598  //对等方用无效数字(即不匹配)宣布块的测试
   599  //随后提供的头)作为恶意丢弃。
   600  func TestInvalidNumberAnnouncement62(t *testing.T) { testInvalidNumberAnnouncement(t, 62) }
   601  func TestInvalidNumberAnnouncement63(t *testing.T) { testInvalidNumberAnnouncement(t, 63) }
   602  func TestInvalidNumberAnnouncement64(t *testing.T) { testInvalidNumberAnnouncement(t, 64) }
   603  
   604  func testInvalidNumberAnnouncement(t *testing.T, protocol int) {
   605  //创建一个块以导入和检查编号
   606  	hashes, blocks := makeChain(1, 0, genesis)
   607  
   608  	tester := newTester()
   609  	badHeaderFetcher := tester.makeHeaderFetcher("bad", blocks, -gatherSlack)
   610  	badBodyFetcher := tester.makeBodyFetcher("bad", blocks, 0)
   611  
   612  	imported := make(chan *types.Block)
   613  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   614  
   615  //宣布一个有错误数字的块,检查是否立即丢弃
   616  	tester.fetcher.Notify("bad", hashes[0], 2, time.Now().Add(-arriveTimeout), badHeaderFetcher, badBodyFetcher)
   617  	verifyImportEvent(t, imported, false)
   618  
   619  	tester.lock.RLock()
   620  	dropped := tester.drops["bad"]
   621  	tester.lock.RUnlock()
   622  
   623  	if !dropped {
   624  		t.Fatalf("peer with invalid numbered announcement not dropped")
   625  	}
   626  
   627  	goodHeaderFetcher := tester.makeHeaderFetcher("good", blocks, -gatherSlack)
   628  	goodBodyFetcher := tester.makeBodyFetcher("good", blocks, 0)
   629  //确保一个好的通知一滴一滴地通过
   630  	tester.fetcher.Notify("good", hashes[0], 1, time.Now().Add(-arriveTimeout), goodHeaderFetcher, goodBodyFetcher)
   631  	verifyImportEvent(t, imported, true)
   632  
   633  	tester.lock.RLock()
   634  	dropped = tester.drops["good"]
   635  	tester.lock.RUnlock()
   636  
   637  	if dropped {
   638  		t.Fatalf("peer with valid numbered announcement dropped")
   639  	}
   640  	verifyImportDone(t, imported)
   641  }
   642  
   643  //测试如果一个块为空(即仅限头),则不应该有body请求
   644  //制作,而不是集管本身组装成一个整体。
   645  func TestEmptyBlockShortCircuit62(t *testing.T) { testEmptyBlockShortCircuit(t, 62) }
   646  func TestEmptyBlockShortCircuit63(t *testing.T) { testEmptyBlockShortCircuit(t, 63) }
   647  func TestEmptyBlockShortCircuit64(t *testing.T) { testEmptyBlockShortCircuit(t, 64) }
   648  
   649  func testEmptyBlockShortCircuit(t *testing.T, protocol int) {
   650  //创建要导入的块链
   651  	hashes, blocks := makeChain(32, 0, genesis)
   652  
   653  	tester := newTester()
   654  	headerFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack)
   655  	bodyFetcher := tester.makeBodyFetcher("valid", blocks, 0)
   656  
   657  //为所有内部事件添加监视挂钩
   658  	fetching := make(chan []common.Hash)
   659  	tester.fetcher.fetchingHook = func(hashes []common.Hash) { fetching <- hashes }
   660  
   661  	completing := make(chan []common.Hash)
   662  	tester.fetcher.completingHook = func(hashes []common.Hash) { completing <- hashes }
   663  
   664  	imported := make(chan *types.Block)
   665  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   666  
   667  //迭代地通知块,直到全部导入
   668  	for i := len(hashes) - 2; i >= 0; i-- {
   669  		tester.fetcher.Notify("valid", hashes[i], uint64(len(hashes)-i-1), time.Now().Add(-arriveTimeout), headerFetcher, bodyFetcher)
   670  
   671  //所有公告都应获取标题
   672  		verifyFetchingEvent(t, fetching, true)
   673  
   674  //只有包含数据内容的块才应请求正文
   675  		verifyCompletingEvent(t, completing, len(blocks[hashes[i]].Transactions()) > 0 || len(blocks[hashes[i]].Uncles()) > 0)
   676  
   677  //与构造无关,导入应该成功
   678  		verifyImportEvent(t, imported, true)
   679  	}
   680  	verifyImportDone(t, imported)
   681  }
   682  
   683  //测试对等端无法使用无限发送的无限内存
   684  //阻止向节点发布公告,但即使面对此类攻击,
   685  //取纸器仍在工作。
   686  func TestHashMemoryExhaustionAttack62(t *testing.T) { testHashMemoryExhaustionAttack(t, 62) }
   687  func TestHashMemoryExhaustionAttack63(t *testing.T) { testHashMemoryExhaustionAttack(t, 63) }
   688  func TestHashMemoryExhaustionAttack64(t *testing.T) { testHashMemoryExhaustionAttack(t, 64) }
   689  
   690  func testHashMemoryExhaustionAttack(t *testing.T, protocol int) {
   691  //使用插入仪器的导入挂钩创建测试仪
   692  	tester := newTester()
   693  
   694  	imported, announces := make(chan *types.Block), int32(0)
   695  	tester.fetcher.importedHook = func(block *types.Block) { imported <- block }
   696  	tester.fetcher.announceChangeHook = func(hash common.Hash, added bool) {
   697  		if added {
   698  			atomic.AddInt32(&announces, 1)
   699  		} else {
   700  			atomic.AddInt32(&announces, -1)
   701  		}
   702  	}
   703  //创建有效的链和无限的垃圾链
   704  	targetBlocks := hashLimit + 2*maxQueueDist
   705  	hashes, blocks := makeChain(targetBlocks, 0, genesis)
   706  	validHeaderFetcher := tester.makeHeaderFetcher("valid", blocks, -gatherSlack)
   707  	validBodyFetcher := tester.makeBodyFetcher("valid", blocks, 0)
   708  
   709  	attack, _ := makeChain(targetBlocks, 0, unknownBlock)
   710  	attackerHeaderFetcher := tester.makeHeaderFetcher("attacker", nil, -gatherSlack)
   711  	attackerBodyFetcher := tester.makeBodyFetcher("attacker", nil, 0)
   712  
   713  //向测试人员提供来自攻击者的大量哈希集,以及来自有效对等端的有限哈希集
   714  	for i := 0; i < len(attack); i++ {
   715  		if i < maxQueueDist {
   716  			tester.fetcher.Notify("valid", hashes[len(hashes)-2-i], uint64(i+1), time.Now(), validHeaderFetcher, validBodyFetcher)
   717  		}
   718    /*ter.fetcher.notify(“攻击者”,攻击[i],1/*不要距离下降*/,time.now(),攻击者headerfetcher,攻击者bodyfetcher)
   719   }
   720   如果计数:=atomic.loadint32(&announces);计数!=hashlimit+maxqueuedist_
   721    t.fatalf(“排队的公告计数不匹配:有%d,需要%d”,count,hashlimit+maxqueuedist)
   722   }
   723   //等待回迁完成
   724   verifyimportcount(t,导入,maxqueuedist)
   725  
   726   //馈送剩余的有效哈希以确保DOS保护状态保持干净
   727   对于i:=len(hashes)-maxqueuedist-2;i>=0;i--
   728    tester.fetcher.notify(“valid”,hashes[i],uint64(len(hashes)-i-1),time.now().add(-arrieveTimeout),validHeaderFetcher,validBodyFetcher)
   729    verifyimportevent(t,导入,真)
   730   }
   731   验证导入完成(T,导入)
   732  }
   733  
   734  //测试发送到获取程序的块(通过传播或通过哈希
   735  //announces和retrievals)不要无限期地堆积起来,这样会耗尽可用的资源。
   736  //系统内存。
   737  func testblockmemoryxhausationattack(t*testing.t)
   738   //使用插入指令的导入挂钩创建测试仪
   739   测试仪:=新测试仪()
   740  
   741   导入,排队:=make(chan*types.block),int32(0)
   742   tester.fetcher.importedhook=func(block*types.block)imported<-block
   743   tester.fetcher.queuechangehook=func(hash common.hash,added bool)
   744    如果添加{
   745     Atomic.AddInt32(&Enqueued,1)
   746    }否则{
   747     原子.addint32(&enqueued,-1)
   748    }
   749   }
   750   //创建有效的链和一批悬空(但在范围内)块
   751   目标块:=hashlimit+2*maxqueuedist
   752   哈希,块:=makechain(targetBlocks,0,genesis)
   753   攻击:=make(map[common.hash]*types.block)
   754   对于i:=byte(0);len(attack)<blocklimit+2*maxqueuedist;i++
   755    哈希,块:=makechain(maxqueuedist-1,i,unknownblock)
   756    对于u,哈希:=范围哈希[:maxQueueDist-2]
   757     攻击[hash]=块[hash]
   758    }
   759   }
   760   //尝试馈送所有攻击者块,确保只接受有限的批处理
   761   对于uu,封锁:=距离攻击
   762    tester.fetcher.enqueue(“攻击者”,block)
   763   }
   764   时间.睡眠(200*时间.毫秒)
   765   如果排队:=atomic.loadint32(&enqueued);排队!=块限制{
   766    t.fatalf(“排队的块计数不匹配:有%d个,需要%d个”,排队,块限制)
   767   }
   768   //将一批有效的块排队,并检查是否允许新的对等机这样做
   769   对于i:=0;i<maxqueuedist-1;i++
   770    tester.fetcher.enqueue(“有效”,blocks[hashes[len(hashes)-3-i])
   771   }
   772   时间.睡眠(100*时间.毫秒)
   773   如果排队:=atomic.loadint32(&enqueued);排队!=blocklimit+maxqueuedist-1_
   774    t.fatalf(“排队的块计数不匹配:有%d,需要%d”,排队,blocklimit+maxqueuedist-1)
   775   }
   776   /插入丢失的片段(和健全性检查导入)
   777   tester.fetcher.enqueue(“有效”,blocks[hashes[len(hashes)-2])
   778   verifyimportcount(t,导入,maxqueuedist)
   779  
   780   //将剩余的块分块插入以确保干净的DOS保护
   781   对于i:=maxqueuedist;i<len(hashes)-1;i++
   782    tester.fetcher.enqueue(“有效”,blocks[hashes[len(hashes)-2-i])
   783    verifyimportevent(t,导入,真)
   784   }
   785   验证导入完成(T,导入)
   786  }
   787