| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- package ethash
- import (
- "encoding/json"
- "io/ioutil"
- "math/big"
- "net"
- "net/http"
- "testing"
- "time"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- )
- // Tests whether remote HTTP servers are correctly notified of new work.
- func TestRemoteNotify(t *testing.T) {
- // Start a simple webserver to capture notifications
- sink := make(chan [3]string)
- server := &http.Server{
- Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- blob, err := ioutil.ReadAll(req.Body)
- if err != nil {
- t.Fatalf("failed to read miner notification: %v", err)
- }
- var work [3]string
- if err := json.Unmarshal(blob, &work); err != nil {
- t.Fatalf("failed to unmarshal miner notification: %v", err)
- }
- sink <- work
- }),
- }
- // Open a custom listener to extract its local address
- listener, err := net.Listen("tcp", "localhost:0")
- if err != nil {
- t.Fatalf("failed to open notification server: %v", err)
- }
- defer listener.Close()
- go server.Serve(listener)
- // Create the custom ethash engine
- ethash := NewTester([]string{"http://" + listener.Addr().String()})
- defer ethash.Close()
- // Stream a work task and ensure the notification bubbles out
- header := &types.Header{Number: big.NewInt(1), Difficulty: big.NewInt(100)}
- block := types.NewBlockWithHeader(header)
- ethash.Seal(nil, block, nil)
- select {
- case work := <-sink:
- if want := ethash.SealHash(header).Hex(); work[0] != want {
- t.Errorf("work packet hash mismatch: have %s, want %s", work[0], want)
- }
- if want := common.BytesToHash(SeedHash(header.Number.Uint64())).Hex(); work[1] != want {
- t.Errorf("work packet seed mismatch: have %s, want %s", work[1], want)
- }
- target := new(big.Int).Div(new(big.Int).Lsh(big.NewInt(1), 256), header.Difficulty)
- if want := common.BytesToHash(target.Bytes()).Hex(); work[2] != want {
- t.Errorf("work packet target mismatch: have %s, want %s", work[2], want)
- }
- case <-time.After(time.Second):
- t.Fatalf("notification timed out")
- }
- }
- // Tests that pushing work packages fast to the miner doesn't cause any daa race
- // issues in the notifications.
- func TestRemoteMultiNotify(t *testing.T) {
- // Start a simple webserver to capture notifications
- sink := make(chan [3]string, 64)
- server := &http.Server{
- Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- blob, err := ioutil.ReadAll(req.Body)
- if err != nil {
- t.Fatalf("failed to read miner notification: %v", err)
- }
- var work [3]string
- if err := json.Unmarshal(blob, &work); err != nil {
- t.Fatalf("failed to unmarshal miner notification: %v", err)
- }
- sink <- work
- }),
- }
- // Open a custom listener to extract its local address
- listener, err := net.Listen("tcp", "localhost:0")
- if err != nil {
- t.Fatalf("failed to open notification server: %v", err)
- }
- defer listener.Close()
- go server.Serve(listener)
- // Create the custom ethash engine
- ethash := NewTester([]string{"http://" + listener.Addr().String()})
- defer ethash.Close()
- // Stream a lot of work task and ensure all the notifications bubble out
- for i := 0; i < cap(sink); i++ {
- header := &types.Header{Number: big.NewInt(int64(i)), Difficulty: big.NewInt(100)}
- block := types.NewBlockWithHeader(header)
- ethash.Seal(nil, block, nil)
- }
- for i := 0; i < cap(sink); i++ {
- select {
- case <-sink:
- case <-time.After(250 * time.Millisecond):
- t.Fatalf("notification %d timed out", i)
- }
- }
- }
|