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