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