github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/consensus/ethash/sealer_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:34</date> 10 //</624450075241746432> 11 12 package ethash 13 14 import ( 15 "encoding/json" 16 "io/ioutil" 17 "math/big" 18 "net" 19 "net/http" 20 "testing" 21 "time" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/core/types" 25 ) 26 27 //测试是否正确通知远程HTTP服务器新工作。 28 func TestRemoteNotify(t *testing.T) { 29 //启动简单的Web服务器以捕获通知 30 sink := make(chan [3]string) 31 32 server := &http.Server{ 33 Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 34 blob, err := ioutil.ReadAll(req.Body) 35 if err != nil { 36 t.Fatalf("failed to read miner notification: %v", err) 37 } 38 var work [3]string 39 if err := json.Unmarshal(blob, &work); err != nil { 40 t.Fatalf("failed to unmarshal miner notification: %v", err) 41 } 42 sink <- work 43 }), 44 } 45 //打开自定义侦听器以提取其本地地址 46 listener, err := net.Listen("tcp", "localhost:0") 47 if err != nil { 48 t.Fatalf("failed to open notification server: %v", err) 49 } 50 defer listener.Close() 51 52 go server.Serve(listener) 53 54 //等待服务器开始侦听 55 var tries int 56 for tries = 0; tries < 10; tries++ { 57 conn, _ := net.DialTimeout("tcp", listener.Addr().String(), 1*time.Second) 58 if conn != nil { 59 break 60 } 61 } 62 if tries == 10 { 63 t.Fatal("tcp listener not ready for more than 10 seconds") 64 } 65 66 //创建自定义ethash引擎 67 ethash := NewTester([]string{"http://“+listener.addr().string(),false) 68 defer ethash.Close() 69 70 //流式处理工作任务并确保通知冒泡 71 header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} 72 block := types.NewBlockWithHeader(header) 73 74 ethash.Seal(nil, block, nil, nil) 75 select { 76 case work := <-sink: 77 if want := ethash.SealHash(header).Hex(); work[0] != want { 78 t.Errorf("work packet hash mismatch: have %s, want %s", work[0], want) 79 } 80 if want := common.BytesToHash(SeedHash(header.Number.Uint64())).Hex(); work[1] != want { 81 t.Errorf("work packet seed mismatch: have %s, want %s", work[1], want) 82 } 83 target := new(big.Int).Div(new(big.Int).Lsh(big.NewInt(1), 256), header.Difficulty) 84 if want := common.BytesToHash(target.Bytes()).Hex(); work[2] != want { 85 t.Errorf("work packet target mismatch: have %s, want %s", work[2], want) 86 } 87 case <-time.After(3 * time.Second): 88 t.Fatalf("notification timed out") 89 } 90 } 91 92 // 93 //通知中的问题。 94 func TestRemoteMultiNotify(t *testing.T) { 95 //启动简单的Web服务器以捕获通知 96 sink := make(chan [3]string, 64) 97 98 server := &http.Server{ 99 Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 100 blob, err := ioutil.ReadAll(req.Body) 101 if err != nil { 102 t.Fatalf("failed to read miner notification: %v", err) 103 } 104 var work [3]string 105 if err := json.Unmarshal(blob, &work); err != nil { 106 t.Fatalf("failed to unmarshal miner notification: %v", err) 107 } 108 sink <- work 109 }), 110 } 111 //打开自定义侦听器以提取其本地地址 112 listener, err := net.Listen("tcp", "localhost:0") 113 if err != nil { 114 t.Fatalf("failed to open notification server: %v", err) 115 } 116 defer listener.Close() 117 118 go server.Serve(listener) 119 120 //创建自定义ethash引擎 121 ethash := NewTester([]string{"http://“+listener.addr().string(),false) 122 defer ethash.Close() 123 124 //流式处理大量工作任务并确保所有通知都冒泡出来 125 for i := 0; i < cap(sink); i++ { 126 header := &types.Header{Number: big.NewInt(int64(i)), Difficulty: big.NewInt(100)} 127 block := types.NewBlockWithHeader(header) 128 129 ethash.Seal(nil, block, nil, nil) 130 } 131 for i := 0; i < cap(sink); i++ { 132 select { 133 case <-sink: 134 case <-time.After(3 * time.Second): 135 t.Fatalf("notification %d timed out", i) 136 } 137 } 138 } 139 140 //测试陈旧溶液是否正确处理。 141 func TestStaleSubmission(t *testing.T) { 142 ethash := NewTester(nil, true) 143 defer ethash.Close() 144 api := &API{ethash} 145 146 fakeNonce, fakeDigest := types.BlockNonce{0x01, 0x02, 0x03}, common.HexToHash("deadbeef") 147 148 testcases := []struct { 149 headers []*types.Header 150 submitIndex int 151 submitRes bool 152 }{ 153 //案例1:提交最新挖掘包的解决方案 154 { 155 []*types.Header{ 156 {ParentHash: common.BytesToHash([]byte{0xa}), Number: big.NewInt(1), Difficulty: big.NewInt(100000000)}, 157 }, 158 0, 159 true, 160 }, 161 // 162 { 163 []*types.Header{ 164 {ParentHash: common.BytesToHash([]byte{0xb}), Number: big.NewInt(2), Difficulty: big.NewInt(100000000)}, 165 {ParentHash: common.BytesToHash([]byte{0xb}), Number: big.NewInt(2), Difficulty: big.NewInt(100000001)}, 166 }, 167 0, 168 true, 169 }, 170 //案例3:提交陈旧但可接受的解决方案 171 { 172 []*types.Header{ 173 {ParentHash: common.BytesToHash([]byte{0xc}), Number: big.NewInt(3), Difficulty: big.NewInt(100000000)}, 174 {ParentHash: common.BytesToHash([]byte{0xd}), Number: big.NewInt(9), Difficulty: big.NewInt(100000000)}, 175 }, 176 0, 177 true, 178 }, 179 //案例4:提交非常老的解决方案 180 { 181 []*types.Header{ 182 {ParentHash: common.BytesToHash([]byte{0xe}), Number: big.NewInt(10), Difficulty: big.NewInt(100000000)}, 183 {ParentHash: common.BytesToHash([]byte{0xf}), Number: big.NewInt(17), Difficulty: big.NewInt(100000000)}, 184 }, 185 0, 186 false, 187 }, 188 } 189 results := make(chan *types.Block, 16) 190 191 for id, c := range testcases { 192 for _, h := range c.headers { 193 ethash.Seal(nil, types.NewBlockWithHeader(h), results, nil) 194 } 195 if res := api.SubmitWork(fakeNonce, ethash.SealHash(c.headers[c.submitIndex]), fakeDigest); res != c.submitRes { 196 t.Errorf("case %d submit result mismatch, want %t, get %t", id+1, c.submitRes, res) 197 } 198 if !c.submitRes { 199 continue 200 } 201 select { 202 case res := <-results: 203 if res.Header().Nonce != fakeNonce { 204 t.Errorf("case %d block nonce mismatch, want %s, get %s", id+1, fakeNonce, res.Header().Nonce) 205 } 206 if res.Header().MixDigest != fakeDigest { 207 t.Errorf("case %d block digest mismatch, want %s, get %s", id+1, fakeDigest, res.Header().MixDigest) 208 } 209 if res.Header().Difficulty.Uint64() != c.headers[c.submitIndex].Difficulty.Uint64() { 210 t.Errorf("case %d block difficulty mismatch, want %d, get %d", id+1, c.headers[c.submitIndex].Difficulty, res.Header().Difficulty) 211 } 212 if res.Header().Number.Uint64() != c.headers[c.submitIndex].Number.Uint64() { 213 t.Errorf("case %d block number mismatch, want %d, get %d", id+1, c.headers[c.submitIndex].Number.Uint64(), res.Header().Number.Uint64()) 214 } 215 if res.Header().ParentHash != c.headers[c.submitIndex].ParentHash { 216 t.Errorf("case %d block parent hash mismatch, want %s, get %s", id+1, c.headers[c.submitIndex].ParentHash.Hex(), res.Header().ParentHash.Hex()) 217 } 218 case <-time.NewTimer(time.Second).C: 219 t.Errorf("case %d fetch ethash result timeout", id+1) 220 } 221 } 222 } 223