mirror of https://github.com/ethereum/go-ethereum
Merge pull request #17347 from karalabe/miner-notify
cmd, consensus/ethash, eth: miner push notificationspull/16490/merge
commit
d8328a96b4
@ -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) |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue