github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/fetcher/fetcher_test.go (about)

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