-
Notifications
You must be signed in to change notification settings - Fork 23
/
cgminer.go
295 lines (256 loc) · 8.34 KB
/
cgminer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
package cgminer
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"net"
"strings"
)
type CGMiner struct {
server string
}
type status struct {
Code int
Description string
Status string `json:"STATUS"`
When int64
}
type Summary struct {
Accepted int64
BestShare int64 `json:"Best Share"`
DeviceHardwarePercent float64 `json:"Device Hardware%"`
DeviceRejectedPercent float64 `json:"Device Rejected%"`
DifficultyAccepted float64 `json:"Difficulty Accepted"`
DifficultyRejected float64 `json:"Difficulty Rejected"`
DifficultyStale float64 `json:"Difficulty Stale"`
Discarded int64
Elapsed int64
FoundBlocks int64 `json:"Found Blocks"`
GetFailures int64 `json:"Get Failures"`
Getworks int64
HardwareErrors int64 `json:"Hardware Errors"`
LocalWork int64 `json:"Local Work"`
MHS5s float64 `json:"MHS 5s"`
MHSav float64 `json:"MHS av"`
NetworkBlocks int64 `json:"Network Blocks"`
PoolRejectedPercentage float64 `json:"Pool Rejected%"`
PoolStalePercentage float64 `json:"Pool Stale%"`
Rejected int64
RemoteFailures int64 `json:"Remote Failures"`
Stale int64
TotalMH float64 `json:"Total MH"`
Utilty float64
WorkUtility float64 `json:"Work Utility"`
}
type Devs struct {
GPU int64
Enabled string
Status string
Temperature float64
FanSpeed int `json:"Fan Speed"`
FanPercent int64 `json:"Fan Percent"`
GPUClock int64 `json:"GPU Clock"`
MemoryClock int64 `json:"Memory Clock"`
GPUVoltage float64 `json:"GPU Voltage"`
Powertune int64
MHSav float64 `json:"MHS av"`
MHS5s float64 `json:"MHS 5s"`
Accepted int64
Rejected int64
HardwareErrors int64 `json:"Hardware Errors"`
Utility float64
Intensity string
LastSharePool int64 `json:"Last Share Pool"`
LashShareTime int64 `json:"Lash Share Time"`
TotalMH float64 `json:"TotalMH"`
Diff1Work int64 `json:"Diff1 Work"`
DifficultyAccepted float64 `json:"Difficulty Accepted"`
DifficultyRejected float64 `json:"Difficulty Rejected"`
LastShareDifficulty float64 `json:"Last Share Difficulty"`
LastValidWork int64 `json:"Last Valid Work"`
DeviceHardware float64 `json:"Device Hardware%"`
DeviceRejected float64 `json:"Device Rejected%"`
DeviceElapsed int64 `json:"Device Elapsed"`
}
type Pool struct {
Accepted int64
BestShare int64 `json:"Best Share"`
Diff1Shares int64 `json:"Diff1 Shares"`
DifficultyAccepted float64 `json:"Difficulty Accepted"`
DifficultyRejected float64 `json:"Difficulty Rejected"`
DifficultyStale float64 `json:"Difficulty Stale"`
Discarded int64
GetFailures int64 `json:"Get Failures"`
Getworks int64
HasGBT bool `json:"Has GBT"`
HasStratum bool `json:"Has Stratum"`
LastShareDifficulty float64 `json:"Last Share Difficulty"`
LastShareTime int64 `json:"Last Share Time"`
LongPoll string `json:"Long Poll"`
Pool int64 `json:"POOL"`
PoolRejectedPercentage float64 `json:"Pool Rejected%"`
PoolStalePercentage float64 `json:"Pool Stale%"`
Priority int64
ProxyType string `json:"Proxy Type"`
Proxy string
Quota int64
Rejected int64
RemoteFailures int64 `json:"Remote Failures"`
Stale int64
Status string
StratumActive bool `json:"Stratum Active"`
StratumURL string `json:"Stratum URL"`
URL string
User string
Works int64
}
type summaryResponse struct {
Status []status `json:"STATUS"`
Summary []Summary `json:"SUMMARY"`
Id int64 `json:"id"`
}
type devsResponse struct {
Status []status `json:"STATUS"`
Devs []Devs `json:"DEVS"`
Id int64 `json:"id"`
}
type poolsResponse struct {
Status []status `json:"STATUS"`
Pools []Pool `json:"POOLS"`
Id int64 `json:"id"`
}
type addPoolResponse struct {
Status []status `json:"STATUS"`
Id int64 `json:"id"`
}
// New returns a CGMiner pointer, which is used to communicate with a running
// CGMiner instance. Note that New does not attempt to connect to the miner.
func New(hostname string, port int64) *CGMiner {
miner := new(CGMiner)
server := fmt.Sprintf("%s:%d", hostname, port)
miner.server = server
return miner
}
func (miner *CGMiner) runCommand(command, argument string) (string, error) {
conn, err := net.Dial("tcp", miner.server)
if err != nil {
return "", err
}
defer conn.Close()
type commandRequest struct {
Command string `json:"command"`
Parameter string `json:"parameter,omitempty"`
}
request := &commandRequest{
Command: command,
}
if argument != "" {
request.Parameter = argument
}
requestBody, err := json.Marshal(request)
if err != nil {
return "", err
}
fmt.Fprintf(conn, "%s", requestBody)
result, err := bufio.NewReader(conn).ReadString('\x00')
if err != nil {
return "", err
}
return strings.TrimRight(result, "\x00"), nil
}
// Devs returns basic information on the miner. See the Devs struct.
func (miner *CGMiner) Devs() (*[]Devs, error) {
result, err := miner.runCommand("devs", "")
if err != nil {
return nil, err
}
var devsResponse devsResponse
err = json.Unmarshal([]byte(result), &devsResponse)
if err != nil {
return nil, err
}
var devs = devsResponse.Devs
return &devs, err
}
// Summary returns basic information on the miner. See the Summary struct.
func (miner *CGMiner) Summary() (*Summary, error) {
result, err := miner.runCommand("summary", "")
if err != nil {
return nil, err
}
var summaryResponse summaryResponse
err = json.Unmarshal([]byte(result), &summaryResponse)
if err != nil {
return nil, err
}
if len(summaryResponse.Summary) != 1 {
return nil, errors.New("Received multiple Summary objects")
}
var summary = summaryResponse.Summary[0]
return &summary, err
}
// Pools returns a slice of Pool structs, one per pool.
func (miner *CGMiner) Pools() ([]Pool, error) {
result, err := miner.runCommand("pools", "")
if err != nil {
return nil, err
}
var poolsResponse poolsResponse
err = json.Unmarshal([]byte(result), &poolsResponse)
if err != nil {
return nil, err
}
var pools = poolsResponse.Pools
return pools, nil
}
// AddPool adds the given URL/username/password combination to the miner's
// pool list.
func (miner *CGMiner) AddPool(url, username, password string) error {
// TODO: Don't allow adding a pool that's already in the pool list
// TODO: Escape commas in the URL, username, and password
parameter := fmt.Sprintf("%s,%s,%s", url, username, password)
result, err := miner.runCommand("addpool", parameter)
if err != nil {
return err
}
var addPoolResponse addPoolResponse
err = json.Unmarshal([]byte(result), &addPoolResponse)
if err != nil {
// If there an error here, it's possible that the pool was actually added
return err
}
status := addPoolResponse.Status[0]
if status.Status != "S" {
return errors.New(fmt.Sprintf("%d: %s", status.Code, status.Description))
}
return nil
}
func (miner *CGMiner) Enable(pool *Pool) error {
parameter := fmt.Sprintf("%d", pool.Pool)
_, err := miner.runCommand("enablepool", parameter)
return err
}
func (miner *CGMiner) Disable(pool *Pool) error {
parameter := fmt.Sprintf("%d", pool.Pool)
_, err := miner.runCommand("disablepool", parameter)
return err
}
func (miner *CGMiner) Delete(pool *Pool) error {
parameter := fmt.Sprintf("%d", pool.Pool)
_, err := miner.runCommand("removepool", parameter)
return err
}
func (miner *CGMiner) SwitchPool(pool *Pool) error {
parameter := fmt.Sprintf("%d", pool.Pool)
_, err := miner.runCommand("switchpool", parameter)
return err
}
func (miner *CGMiner) Restart() error {
_, err := miner.runCommand("restart", "")
return err
}
func (miner *CGMiner) Quit() error {
_, err := miner.runCommand("quit", "")
return err
}