|
3 | 3 | package main
|
4 | 4 |
|
5 | 5 | import (
|
6 |
| - "bytes" |
7 |
| - "crypto/tls" |
8 |
| - "crypto/x509" |
9 |
| - "encoding/binary" |
10 |
| - "encoding/hex" |
11 | 6 | "encoding/json"
|
12 | 7 | "fmt"
|
13 |
| - "io" |
14 |
| - "math/big" |
15 |
| - "net" |
16 |
| - "net/http" |
17 |
| - "os" |
18 |
| - "time" |
19 | 8 |
|
20 |
| - "github.com/decred/go-socks/socks" |
21 | 9 | "github.com/decred/gominer/stratum"
|
22 |
| - "github.com/decred/gominer/util" |
23 | 10 | "github.com/decred/gominer/work"
|
24 | 11 | )
|
25 | 12 |
|
26 |
| -// newHTTPClient returns a new HTTP client that is configured according to the |
27 |
| -// proxy and TLS settings in the associated connection configuration. |
28 |
| -func newHTTPClient(cfg *config) (*http.Client, error) { |
29 |
| - // Configure proxy if needed. |
30 |
| - var dial func(network, addr string) (net.Conn, error) |
31 |
| - if cfg.Proxy != "" { |
32 |
| - proxy := &socks.Proxy{ |
33 |
| - Addr: cfg.Proxy, |
34 |
| - Username: cfg.ProxyUser, |
35 |
| - Password: cfg.ProxyPass, |
36 |
| - } |
37 |
| - dial = func(network, addr string) (net.Conn, error) { |
38 |
| - c, err := proxy.Dial(network, addr) |
39 |
| - if err != nil { |
40 |
| - return nil, err |
41 |
| - } |
42 |
| - return c, nil |
43 |
| - } |
44 |
| - } |
45 |
| - |
46 |
| - // Configure TLS if needed. |
47 |
| - var tlsConfig *tls.Config |
48 |
| - if !cfg.NoTLS && cfg.RPCCert != "" { |
49 |
| - pem, err := os.ReadFile(cfg.RPCCert) |
50 |
| - if err != nil { |
51 |
| - return nil, err |
52 |
| - } |
53 |
| - |
54 |
| - pool := x509.NewCertPool() |
55 |
| - pool.AppendCertsFromPEM(pem) |
56 |
| - tlsConfig = &tls.Config{ |
57 |
| - RootCAs: pool, |
58 |
| - InsecureSkipVerify: cfg.TLSSkipVerify, |
59 |
| - } |
60 |
| - } |
61 |
| - |
62 |
| - // Create and return the new HTTP client potentially configured with a |
63 |
| - // proxy and TLS. |
64 |
| - client := http.Client{ |
65 |
| - Transport: &http.Transport{ |
66 |
| - Dial: dial, |
67 |
| - TLSClientConfig: tlsConfig, |
68 |
| - }, |
69 |
| - } |
70 |
| - return &client, nil |
71 |
| -} |
72 |
| - |
73 |
| -type getWorkResponseJson struct { |
74 |
| - Result struct { |
75 |
| - Data string |
76 |
| - Target string |
77 |
| - } |
78 |
| - Error *struct { |
79 |
| - Code int |
80 |
| - Message string |
81 |
| - } |
82 |
| -} |
83 |
| - |
84 |
| -type getWorkSubmitResponseJson struct { |
85 |
| - Result bool |
86 |
| - Error *struct { |
87 |
| - Code int |
88 |
| - Message string |
89 |
| - } |
90 |
| -} |
91 |
| - |
92 |
| -const ( |
93 |
| - MaxIdleConnections int = 20 |
94 |
| - RequestTimeout int = 5 |
95 |
| -) |
96 |
| - |
97 |
| -// GetWork makes a getwork RPC call and returns the result (data and target). |
98 |
| -func GetWork() (*work.Work, error) { |
99 |
| - // Generate a request to the configured RPC server. |
100 |
| - protocol := "http" |
101 |
| - if !cfg.NoTLS { |
102 |
| - protocol = "https" |
103 |
| - } |
104 |
| - url := protocol + "://" + cfg.RPCServer |
105 |
| - jsonStr := []byte(`{"jsonrpc": "2.0", "method": "getwork", "params": [], "id": 1}`) |
106 |
| - bodyBuff := bytes.NewBuffer(jsonStr) |
107 |
| - httpRequest, err := http.NewRequest("POST", url, bodyBuff) |
108 |
| - if err != nil { |
109 |
| - return nil, err |
110 |
| - } |
111 |
| - httpRequest.Close = true |
112 |
| - httpRequest.Header.Set("Content-Type", "application/json") |
113 |
| - |
114 |
| - // Configure basic access authorization. |
115 |
| - httpRequest.SetBasicAuth(cfg.RPCUser, cfg.RPCPassword) |
116 |
| - |
117 |
| - // Create the new HTTP client that is configured according to the user- |
118 |
| - // specified options and submit the request. |
119 |
| - httpClient, err := newHTTPClient(cfg) |
120 |
| - if err != nil { |
121 |
| - return nil, err |
122 |
| - } |
123 |
| - httpResponse, err := httpClient.Do(httpRequest) |
124 |
| - if err != nil { |
125 |
| - return nil, err |
126 |
| - } |
127 |
| - |
128 |
| - body, err := io.ReadAll(httpResponse.Body) |
129 |
| - httpResponse.Body.Close() |
130 |
| - if err != nil { |
131 |
| - err = fmt.Errorf("error reading json reply: %w", err) |
132 |
| - return nil, err |
133 |
| - } |
134 |
| - |
135 |
| - if httpResponse.Status != "200 OK" { |
136 |
| - return nil, fmt.Errorf("http status %s: %s", httpResponse.Status, body) |
137 |
| - } |
138 |
| - |
139 |
| - var res getWorkResponseJson |
140 |
| - err = json.Unmarshal(body, &res) |
141 |
| - if err != nil { |
142 |
| - return nil, err |
143 |
| - } |
144 |
| - |
145 |
| - if res.Error != nil { |
146 |
| - return nil, fmt.Errorf("json error %d: %s", res.Error.Code, |
147 |
| - res.Error.Message) |
148 |
| - } |
149 |
| - |
150 |
| - data, err := hex.DecodeString(res.Result.Data) |
151 |
| - if err != nil { |
152 |
| - return nil, err |
153 |
| - } |
154 |
| - if len(data) != 192 { |
155 |
| - return nil, fmt.Errorf("wrong data length: got %d, expected 192", |
156 |
| - len(data)) |
157 |
| - } |
158 |
| - target, err := hex.DecodeString(res.Result.Target) |
159 |
| - if err != nil { |
160 |
| - return nil, err |
161 |
| - } |
162 |
| - if len(target) != 32 { |
163 |
| - return nil, fmt.Errorf("wrong target length: got %d, expected 32", |
164 |
| - len(target)) |
165 |
| - } |
166 |
| - |
167 |
| - // The bigTarget difficulty is provided in little endian, but big integers |
168 |
| - // expect big endian, so reverse it accordingly. |
169 |
| - bigTarget := new(big.Int).SetBytes(util.Reverse(target)) |
170 |
| - |
171 |
| - var workData [192]byte |
172 |
| - copy(workData[:], data) |
173 |
| - |
174 |
| - const isGetWork = true |
175 |
| - timestamp := binary.LittleEndian.Uint32(workData[128+4*work.TimestampWord:]) |
176 |
| - w := work.NewWork(workData, bigTarget, timestamp, uint32(time.Now().Unix()), |
177 |
| - isGetWork) |
178 |
| - |
179 |
| - w.Target = bigTarget |
180 |
| - |
181 |
| - return w, nil |
182 |
| -} |
183 |
| - |
184 | 13 | // GetPoolWork gets work from a stratum enabled pool.
|
185 | 14 | func GetPoolWork(pool *stratum.Stratum) (*work.Work, error) {
|
186 | 15 | // Get Next work for stratum and mark it as used.
|
@@ -212,65 +41,6 @@ func GetPoolWork(pool *stratum.Stratum) (*work.Work, error) {
|
212 | 41 | return nil, fmt.Errorf("no work available")
|
213 | 42 | }
|
214 | 43 |
|
215 |
| -// GetWork makes a getwork RPC call and returns the result (data and target). |
216 |
| -func GetWorkSubmit(data []byte) (bool, error) { |
217 |
| - // Generate a request to the configured RPC server. |
218 |
| - protocol := "http" |
219 |
| - if !cfg.NoTLS { |
220 |
| - protocol = "https" |
221 |
| - } |
222 |
| - url := protocol + "://" + cfg.RPCServer |
223 |
| - hexData := hex.EncodeToString(data) |
224 |
| - jsonStr := []byte(`{"jsonrpc": "2.0", "method": "getwork", "params": ["` + |
225 |
| - hexData + `"], "id": 1}`) |
226 |
| - bodyBuff := bytes.NewBuffer(jsonStr) |
227 |
| - httpRequest, err := http.NewRequest("POST", url, bodyBuff) |
228 |
| - if err != nil { |
229 |
| - return false, err |
230 |
| - } |
231 |
| - httpRequest.Close = true |
232 |
| - httpRequest.Header.Set("Content-Type", "application/json") |
233 |
| - |
234 |
| - // Configure basic access authorization. |
235 |
| - httpRequest.SetBasicAuth(cfg.RPCUser, cfg.RPCPassword) |
236 |
| - |
237 |
| - // Create the new HTTP client that is configured according to the user- |
238 |
| - // specified options and submit the request. |
239 |
| - httpClient, err := newHTTPClient(cfg) |
240 |
| - if err != nil { |
241 |
| - return false, err |
242 |
| - } |
243 |
| - httpResponse, err := httpClient.Do(httpRequest) |
244 |
| - if err != nil { |
245 |
| - return false, err |
246 |
| - } |
247 |
| - |
248 |
| - body, err := io.ReadAll(httpResponse.Body) |
249 |
| - httpResponse.Body.Close() |
250 |
| - if err != nil { |
251 |
| - err = fmt.Errorf("error reading json reply: %w", err) |
252 |
| - return false, err |
253 |
| - } |
254 |
| - |
255 |
| - if httpResponse.Status != "200 OK" { |
256 |
| - return false, fmt.Errorf("error calling getwork (%s): %s", |
257 |
| - httpResponse.Status, body) |
258 |
| - } |
259 |
| - |
260 |
| - var res getWorkSubmitResponseJson |
261 |
| - err = json.Unmarshal(body, &res) |
262 |
| - if err != nil { |
263 |
| - return false, err |
264 |
| - } |
265 |
| - |
266 |
| - if res.Error != nil { |
267 |
| - return false, fmt.Errorf("json error %d: %s", res.Error.Code, |
268 |
| - res.Error.Message) |
269 |
| - } |
270 |
| - |
271 |
| - return res.Result, nil |
272 |
| -} |
273 |
| - |
274 | 44 | // GetPoolWorkSubmit sends the result to the stratum enabled pool.
|
275 | 45 | func GetPoolWorkSubmit(data []byte, pool *stratum.Stratum) (bool, error) {
|
276 | 46 | pool.Lock()
|
|
0 commit comments