github.com/luckypickle/go-ethereum-vet@v1.14.2/consensus/ethash/sealer_test.go (about) 1 package ethash 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "math/big" 7 "net" 8 "net/http" 9 "testing" 10 "time" 11 12 "github.com/luckypickle/go-ethereum-vet/common" 13 "github.com/luckypickle/go-ethereum-vet/core/types" 14 ) 15 16 // Tests whether remote HTTP servers are correctly notified of new work. 17 func TestRemoteNotify(t *testing.T) { 18 // Start a simple webserver to capture notifications 19 sink := make(chan [3]string) 20 21 server := &http.Server{ 22 Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 23 blob, err := ioutil.ReadAll(req.Body) 24 if err != nil { 25 t.Fatalf("failed to read miner notification: %v", err) 26 } 27 var work [3]string 28 if err := json.Unmarshal(blob, &work); err != nil { 29 t.Fatalf("failed to unmarshal miner notification: %v", err) 30 } 31 sink <- work 32 }), 33 } 34 // Open a custom listener to extract its local address 35 listener, err := net.Listen("tcp", "localhost:0") 36 if err != nil { 37 t.Fatalf("failed to open notification server: %v", err) 38 } 39 defer listener.Close() 40 41 go server.Serve(listener) 42 43 // Create the custom ethash engine 44 ethash := NewTester([]string{"http://" + listener.Addr().String()}) 45 defer ethash.Close() 46 47 // Stream a work task and ensure the notification bubbles out 48 header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)} 49 block := types.NewBlockWithHeader(header) 50 51 ethash.Seal(nil, block, nil) 52 select { 53 case work := <-sink: 54 if want := header.HashNoNonce().Hex(); work[0] != want { 55 t.Errorf("work packet hash mismatch: have %s, want %s", work[0], want) 56 } 57 if want := common.BytesToHash(SeedHash(header.Number.Uint64())).Hex(); work[1] != want { 58 t.Errorf("work packet seed mismatch: have %s, want %s", work[1], want) 59 } 60 target := new(big.Int).Div(new(big.Int).Lsh(big.NewInt(1), 256), header.Difficulty) 61 if want := common.BytesToHash(target.Bytes()).Hex(); work[2] != want { 62 t.Errorf("work packet target mismatch: have %s, want %s", work[2], want) 63 } 64 case <-time.After(time.Second): 65 t.Fatalf("notification timed out") 66 } 67 } 68 69 // Tests that pushing work packages fast to the miner doesn't cause any daa race 70 // issues in the notifications. 71 func TestRemoteMultiNotify(t *testing.T) { 72 // Start a simple webserver to capture notifications 73 sink := make(chan [3]string, 64) 74 75 server := &http.Server{ 76 Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 77 blob, err := ioutil.ReadAll(req.Body) 78 if err != nil { 79 t.Fatalf("failed to read miner notification: %v", err) 80 } 81 var work [3]string 82 if err := json.Unmarshal(blob, &work); err != nil { 83 t.Fatalf("failed to unmarshal miner notification: %v", err) 84 } 85 sink <- work 86 }), 87 } 88 // Open a custom listener to extract its local address 89 listener, err := net.Listen("tcp", "localhost:0") 90 if err != nil { 91 t.Fatalf("failed to open notification server: %v", err) 92 } 93 defer listener.Close() 94 95 go server.Serve(listener) 96 97 // Create the custom ethash engine 98 ethash := NewTester([]string{"http://" + listener.Addr().String()}) 99 defer ethash.Close() 100 101 // Stream a lot of work task and ensure all the notifications bubble out 102 for i := 0; i < cap(sink); i++ { 103 header := &types.Header{Number: big.NewInt(int64(i)), Difficulty: big.NewInt(100)} 104 block := types.NewBlockWithHeader(header) 105 106 ethash.Seal(nil, block, nil) 107 } 108 for i := 0; i < cap(sink); i++ { 109 select { 110 case <-sink: 111 case <-time.After(250 * time.Millisecond): 112 t.Fatalf("notification %d timed out", i) 113 } 114 } 115 }