github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/block_validator_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:35</date>
    10  //</624450077959655424>
    11  
    12  
    13  package core
    14  
    15  import (
    16  	"runtime"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/ethereum/go-ethereum/consensus/ethash"
    21  	"github.com/ethereum/go-ethereum/core/types"
    22  	"github.com/ethereum/go-ethereum/core/vm"
    23  	"github.com/ethereum/go-ethereum/ethdb"
    24  	"github.com/ethereum/go-ethereum/params"
    25  )
    26  
    27  //测试简单的头验证对好的和坏的块都有效。
    28  func TestHeaderVerification(t *testing.T) {
    29  //创建一个简单的链来验证
    30  	var (
    31  		testdb    = ethdb.NewMemDatabase()
    32  		gspec     = &Genesis{Config: params.TestChainConfig}
    33  		genesis   = gspec.MustCommit(testdb)
    34  		blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil)
    35  	)
    36  	headers := make([]*types.Header, len(blocks))
    37  	for i, block := range blocks {
    38  		headers[i] = block.Header()
    39  	}
    40  //逐个运行块的头检查程序,检查有效和无效的nonce
    41  	chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
    42  	defer chain.Stop()
    43  
    44  	for i := 0; i < len(blocks); i++ {
    45  		for j, valid := range []bool{true, false} {
    46  			var results <-chan error
    47  
    48  			if valid {
    49  				engine := ethash.NewFaker()
    50  				_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true})
    51  			} else {
    52  				engine := ethash.NewFakeFailer(headers[i].Number.Uint64())
    53  				_, results = engine.VerifyHeaders(chain, []*types.Header{headers[i]}, []bool{true})
    54  			}
    55  //等待验证结果
    56  			select {
    57  			case result := <-results:
    58  				if (result == nil) != valid {
    59  					t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, result, valid)
    60  				}
    61  			case <-time.After(time.Second):
    62  				t.Fatalf("test %d.%d: verification timeout", i, j)
    63  			}
    64  //确保不再返回数据
    65  			select {
    66  			case result := <-results:
    67  				t.Fatalf("test %d.%d: unexpected result returned: %v", i, j, result)
    68  			case <-time.After(25 * time.Millisecond):
    69  			}
    70  		}
    71  		chain.InsertChain(blocks[i : i+1])
    72  	}
    73  }
    74  
    75  //测试并发头验证对好块和坏块都有效。
    76  func TestHeaderConcurrentVerification2(t *testing.T)  { testHeaderConcurrentVerification(t, 2) }
    77  func TestHeaderConcurrentVerification8(t *testing.T)  { testHeaderConcurrentVerification(t, 8) }
    78  func TestHeaderConcurrentVerification32(t *testing.T) { testHeaderConcurrentVerification(t, 32) }
    79  
    80  func testHeaderConcurrentVerification(t *testing.T, threads int) {
    81  //创建一个简单的链来验证
    82  	var (
    83  		testdb    = ethdb.NewMemDatabase()
    84  		gspec     = &Genesis{Config: params.TestChainConfig}
    85  		genesis   = gspec.MustCommit(testdb)
    86  		blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil)
    87  	)
    88  	headers := make([]*types.Header, len(blocks))
    89  	seals := make([]bool, len(blocks))
    90  
    91  	for i, block := range blocks {
    92  		headers[i] = block.Header()
    93  		seals[i] = true
    94  	}
    95  //设置要验证的线程数
    96  	old := runtime.GOMAXPROCS(threads)
    97  	defer runtime.GOMAXPROCS(old)
    98  
    99  //同时为整个区块链运行标题检查器
   100  //还有一个无效的链(如果一个任意块无效,就足够了)。
   101  	for i, valid := range []bool{true, false} {
   102  		var results <-chan error
   103  
   104  		if valid {
   105  			chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil)
   106  			_, results = chain.engine.VerifyHeaders(chain, headers, seals)
   107  			chain.Stop()
   108  		} else {
   109  			chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil)
   110  			_, results = chain.engine.VerifyHeaders(chain, headers, seals)
   111  			chain.Stop()
   112  		}
   113  //等待所有验证结果
   114  		checks := make(map[int]error)
   115  		for j := 0; j < len(blocks); j++ {
   116  			select {
   117  			case result := <-results:
   118  				checks[j] = result
   119  
   120  			case <-time.After(time.Second):
   121  				t.Fatalf("test %d.%d: verification timeout", i, j)
   122  			}
   123  		}
   124  //检查当前检查有效性
   125  		for j := 0; j < len(blocks); j++ {
   126  want := valid || (j < len(blocks)-2) //我们选择了链中最后一个,但只有一个失败。
   127  			if (checks[j] == nil) != want {
   128  				t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, checks[j], want)
   129  			}
   130  			if !want {
   131  //第一个错误后的几个块可能由于并发而通过验证
   132  //工人。我们不关心这个测试中的那些,只关心正确的模块
   133  //出错。
   134  				break
   135  			}
   136  		}
   137  //确保不再返回数据
   138  		select {
   139  		case result := <-results:
   140  			t.Fatalf("test %d: unexpected result returned: %v", i, result)
   141  		case <-time.After(25 * time.Millisecond):
   142  		}
   143  	}
   144  }
   145  
   146  //中止头验证的测试确实阻止了进一步的检查
   147  //运行,以及检查是否没有遗留的Goroutines泄漏。
   148  func TestHeaderConcurrentAbortion2(t *testing.T)  { testHeaderConcurrentAbortion(t, 2) }
   149  func TestHeaderConcurrentAbortion8(t *testing.T)  { testHeaderConcurrentAbortion(t, 8) }
   150  func TestHeaderConcurrentAbortion32(t *testing.T) { testHeaderConcurrentAbortion(t, 32) }
   151  
   152  func testHeaderConcurrentAbortion(t *testing.T, threads int) {
   153  //创建一个简单的链来验证
   154  	var (
   155  		testdb    = ethdb.NewMemDatabase()
   156  		gspec     = &Genesis{Config: params.TestChainConfig}
   157  		genesis   = gspec.MustCommit(testdb)
   158  		blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 1024, nil)
   159  	)
   160  	headers := make([]*types.Header, len(blocks))
   161  	seals := make([]bool, len(blocks))
   162  
   163  	for i, block := range blocks {
   164  		headers[i] = block.Header()
   165  		seals[i] = true
   166  	}
   167  //设置要验证的线程数
   168  	old := runtime.GOMAXPROCS(threads)
   169  	defer runtime.GOMAXPROCS(old)
   170  
   171  //启动验证并立即中止
   172  	chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil)
   173  	defer chain.Stop()
   174  
   175  	abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
   176  	close(abort)
   177  
   178  //耗尽结果通道
   179  	verified := 0
   180  	for depleted := false; !depleted; {
   181  		select {
   182  		case result := <-results:
   183  			if result != nil {
   184  				t.Errorf("header %d: validation failed: %v", verified, result)
   185  			}
   186  			verified++
   187  		case <-time.After(50 * time.Millisecond):
   188  			depleted = true
   189  		}
   190  	}
   191  //检查流产是否因为没有处理过多的战俘而受到尊重。
   192  	if verified > 2*threads {
   193  		t.Errorf("verification count too large: have %d, want below %d", verified, 2*threads)
   194  	}
   195  }
   196