144 lines
2.7 KiB
Go
144 lines
2.7 KiB
Go
package proxy
|
|
|
|
import (
|
|
"bufio"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"net"
|
|
)
|
|
|
|
type minerRequest struct {
|
|
ID int64 `json:"id"`
|
|
Method string `json:"method"`
|
|
Params json.RawMessage `json:"params"`
|
|
}
|
|
|
|
// Start begins the read loop in a goroutine and arms the login timeout timer.
|
|
//
|
|
// m.Start()
|
|
func (m *Miner) Start() {
|
|
if m == nil || m.conn == nil {
|
|
return
|
|
}
|
|
|
|
go func() {
|
|
reader := bufio.NewReader(m.conn)
|
|
for {
|
|
line, errorValue := reader.ReadBytes('\n')
|
|
if errorValue != nil {
|
|
m.Close()
|
|
return
|
|
}
|
|
m.rx += uint64(len(line))
|
|
m.Touch()
|
|
}
|
|
}()
|
|
}
|
|
|
|
// ForwardJob encodes the job as a stratum job notification and writes it to the miner.
|
|
//
|
|
// m.ForwardJob(job, "cn/r")
|
|
func (m *Miner) ForwardJob(job Job, algo string) {
|
|
if m == nil || m.conn == nil {
|
|
return
|
|
}
|
|
|
|
blob := job.Blob
|
|
if m.extNH {
|
|
blob = job.BlobWithFixedByte(m.fixedByte)
|
|
}
|
|
|
|
m.diff = job.DifficultyFromTarget()
|
|
m.state = MinerStateReady
|
|
m.Touch()
|
|
|
|
params := map[string]interface{}{
|
|
"blob": blob,
|
|
"job_id": job.JobID,
|
|
"target": job.Target,
|
|
"id": m.rpcID,
|
|
}
|
|
if algo != "" {
|
|
params["algo"] = algo
|
|
}
|
|
|
|
m.writeJSON(map[string]interface{}{
|
|
"jsonrpc": "2.0",
|
|
"method": "job",
|
|
"params": params,
|
|
})
|
|
}
|
|
|
|
// ReplyWithError sends a JSON-RPC error response for the given request id.
|
|
//
|
|
// m.ReplyWithError(2, "Low difficulty share")
|
|
func (m *Miner) ReplyWithError(id int64, message string) {
|
|
m.writeJSON(map[string]interface{}{
|
|
"id": id,
|
|
"jsonrpc": "2.0",
|
|
"error": map[string]interface{}{
|
|
"code": -1,
|
|
"message": message,
|
|
},
|
|
})
|
|
}
|
|
|
|
// Success sends a JSON-RPC success response with the given status string.
|
|
//
|
|
// m.Success(2, "OK")
|
|
func (m *Miner) Success(id int64, status string) {
|
|
m.writeJSON(map[string]interface{}{
|
|
"id": id,
|
|
"jsonrpc": "2.0",
|
|
"error": nil,
|
|
"result": map[string]string{
|
|
"status": status,
|
|
},
|
|
})
|
|
}
|
|
|
|
// Close initiates graceful TCP shutdown. Safe to call multiple times.
|
|
//
|
|
// m.Close()
|
|
func (m *Miner) Close() {
|
|
if m == nil || m.conn == nil || m.state == MinerStateClosing {
|
|
return
|
|
}
|
|
|
|
m.state = MinerStateClosing
|
|
_ = m.conn.Close()
|
|
}
|
|
|
|
func (m *Miner) writeJSON(value interface{}) {
|
|
if m == nil || m.conn == nil {
|
|
return
|
|
}
|
|
|
|
data, errorValue := json.Marshal(value)
|
|
if errorValue != nil {
|
|
return
|
|
}
|
|
|
|
m.sendMu.Lock()
|
|
defer m.sendMu.Unlock()
|
|
|
|
data = append(data, '\n')
|
|
written, errorValue := m.conn.Write(data)
|
|
if errorValue == nil {
|
|
m.tx += uint64(written)
|
|
}
|
|
}
|
|
|
|
func newRPCID() string {
|
|
value := make([]byte, 16)
|
|
_, _ = rand.Read(value)
|
|
return hex.EncodeToString(value)
|
|
}
|
|
|
|
func (m *Miner) RemoteAddr() net.Addr {
|
|
if m == nil || m.conn == nil {
|
|
return nil
|
|
}
|
|
return m.conn.RemoteAddr()
|
|
}
|