aboutsummaryrefslogtreecommitdiffstats
path: root/consensus/ethash/sealer_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'consensus/ethash/sealer_test.go')
-rw-r--r--consensus/ethash/sealer_test.go115
1 files changed, 115 insertions, 0 deletions
diff --git a/consensus/ethash/sealer_test.go b/consensus/ethash/sealer_test.go
new file mode 100644
index 000000000..6d8a77049
--- /dev/null
+++ b/consensus/ethash/sealer_test.go
@@ -0,0 +1,115 @@
+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 := header.HashNoNonce().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, 1024)
+
+ 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)
+ }
+ }
+}