1 package rpcclient
2 3 import (
4 "encoding/hex"
5 js "encoding/json"
6 "errors"
7 "github.com/p9c/p9/pkg/block"
8 9 "github.com/p9c/p9/pkg/btcjson"
10 "github.com/p9c/p9/pkg/chainhash"
11 )
12 13 // FutureGenerateResult is a future promise to deliver the result of a GenerateAsync RPC invocation (or an applicable
14 // error).
15 type FutureGenerateResult chan *response
16 17 // Receive waits for the response promised by the future and returns a list of block hashes generated by the call.
18 func (r FutureGenerateResult) Receive() ([]*chainhash.Hash, error) {
19 res, e := receiveFuture(r)
20 if e != nil {
21 return nil, e
22 }
23 // Unmarshal result as a list of strings.
24 var result []string
25 e = js.Unmarshal(res, &result)
26 if e != nil {
27 return nil, e
28 }
29 // Convert each block hash to a chainhash.Hash and store a pointer to each.
30 convertedResult := make([]*chainhash.Hash, len(result))
31 for i, hashString := range result {
32 convertedResult[i], e = chainhash.NewHashFromStr(hashString)
33 if e != nil {
34 return nil, e
35 }
36 }
37 return convertedResult, nil
38 }
39 40 // GenerateAsync returns an instance of a type that can be used to get the result of the RPC at some future time by
41 // invoking the Receive function on the returned instance. See Generate for the blocking version and more details.
42 func (c *Client) GenerateAsync(numBlocks uint32) FutureGenerateResult {
43 cmd := btcjson.NewGenerateCmd(numBlocks)
44 return c.sendCmd(cmd)
45 }
46 47 // Generate generates numBlocks blocks and returns their hashes.
48 func (c *Client) Generate(numBlocks uint32) ([]*chainhash.Hash, error) {
49 return c.GenerateAsync(numBlocks).Receive()
50 }
51 52 // FutureGetGenerateResult is a future promise to deliver the result of a GetGenerateAsync RPC invocation (or an
53 // applicable error).
54 type FutureGetGenerateResult chan *response
55 56 // Receive waits for the response promised by the future and returns true if the server is set to mine, otherwise false.
57 func (r FutureGetGenerateResult) Receive() (bool, error) {
58 res, e := receiveFuture(r)
59 if e != nil {
60 return false, e
61 }
62 // Unmarshal result as a boolean.
63 var result bool
64 e = js.Unmarshal(res, &result)
65 if e != nil {
66 return false, e
67 }
68 return result, nil
69 }
70 71 // GetGenerateAsync returns an instance of a type that can be used to get the result of the RPC at some future time by
72 // invoking the Receive function on the returned instance. See GetGenerate for the blocking version and more details.
73 func (c *Client) GetGenerateAsync() FutureGetGenerateResult {
74 cmd := btcjson.NewGetGenerateCmd()
75 return c.sendCmd(cmd)
76 }
77 78 // GetGenerate returns true if the server is set to mine, otherwise false.
79 func (c *Client) GetGenerate() (bool, error) {
80 return c.GetGenerateAsync().Receive()
81 }
82 83 // FutureSetGenerateResult is a future promise to deliver the result of a SetGenerateAsync RPC invocation (or an
84 // applicable error).
85 type FutureSetGenerateResult chan *response
86 87 // Receive waits for the response promised by the future and returns an error if any occurred when setting the server to
88 // generate coins (mine) or not.
89 func (r FutureSetGenerateResult) Receive() (e error) {
90 _, e = receiveFuture(r)
91 return e
92 }
93 94 // SetGenerateAsync returns an instance of a type that can be used to get the result of the RPC at some future time by
95 // invoking the Receive function on the returned instance. See SetGenerate for the blocking version and more details.
96 func (c *Client) SetGenerateAsync(enable bool, numCPUs int) FutureSetGenerateResult {
97 cmd := btcjson.NewSetGenerateCmd(enable, &numCPUs)
98 return c.sendCmd(cmd)
99 }
100 101 // SetGenerate sets the server to generate coins (mine) or not.
102 func (c *Client) SetGenerate(enable bool, numCPUs int) (e error) {
103 return c.SetGenerateAsync(enable, numCPUs).Receive()
104 }
105 106 // FutureGetHashesPerSecResult is a future promise to deliver the result of a GetHashesPerSecAsync RPC invocation (or an
107 // applicable error).
108 type FutureGetHashesPerSecResult chan *response
109 110 // Receive waits for the response promised by the future and returns a recent hashes per second performance measurement
111 // while generating coins (mining). Zero is returned if the server is not mining.
112 func (r FutureGetHashesPerSecResult) Receive() (int64, error) {
113 res, e := receiveFuture(r)
114 if e != nil {
115 return -1, e
116 }
117 // Unmarshal result as an int64.
118 var result int64
119 e = js.Unmarshal(res, &result)
120 if e != nil {
121 return 0, e
122 }
123 return result, nil
124 }
125 126 // GetHashesPerSecAsync returns an instance of a type that can be used to get the result of the RPC at some future time
127 // by invoking the Receive function on the returned instance. See GetHashesPerSec for the blocking version and more
128 // details.
129 func (c *Client) GetHashesPerSecAsync() FutureGetHashesPerSecResult {
130 cmd := btcjson.NewGetHashesPerSecCmd()
131 return c.sendCmd(cmd)
132 }
133 134 // GetHashesPerSec returns a recent hashes per second performance measurement while generating coins (mining). Zero is
135 // returned if the server is not mining.
136 func (c *Client) GetHashesPerSec() (int64, error) {
137 return c.GetHashesPerSecAsync().Receive()
138 }
139 140 // FutureGetMiningInfoResult is a future promise to deliver the result of a GetMiningInfoAsync RPC invocation (or an
141 // applicable error).
142 type FutureGetMiningInfoResult chan *response
143 144 // Receive waits for the response promised by the future and returns the mining information.
145 func (r FutureGetMiningInfoResult) Receive() (*btcjson.GetMiningInfoResult, error) {
146 res, e := receiveFuture(r)
147 if e != nil {
148 return nil, e
149 }
150 // Unmarshal result as a getmininginfo result object.
151 var infoResult btcjson.GetMiningInfoResult
152 e = js.Unmarshal(res, &infoResult)
153 if e != nil {
154 return nil, e
155 }
156 return &infoResult, nil
157 }
158 159 // GetMiningInfoAsync returns an instance of a type that can be used to get the result of the RPC at some future time by
160 // invoking the Receive function on the returned instance. See GetMiningInfo for the blocking version and more details.
161 func (c *Client) GetMiningInfoAsync() FutureGetMiningInfoResult {
162 cmd := btcjson.NewGetMiningInfoCmd()
163 return c.sendCmd(cmd)
164 }
165 166 // GetMiningInfo returns mining information.
167 func (c *Client) GetMiningInfo() (*btcjson.GetMiningInfoResult, error) {
168 return c.GetMiningInfoAsync().Receive()
169 }
170 171 // FutureGetNetworkHashPS is a future promise to deliver the result of a GetNetworkHashPSAsync RPC invocation (or an
172 // applicable error).
173 type FutureGetNetworkHashPS chan *response
174 175 // Receive waits for the response promised by the future and returns the estimated network hashes per second for the
176 // block heights provided by the parameters.
177 func (r FutureGetNetworkHashPS) Receive() (int64, error) {
178 res, e := receiveFuture(r)
179 if e != nil {
180 return -1, e
181 }
182 // Unmarshal result as an int64.
183 var result int64
184 e = js.Unmarshal(res, &result)
185 if e != nil {
186 return 0, e
187 }
188 return result, nil
189 }
190 191 // GetNetworkHashPSAsync returns an instance of a type that can be used to get the result of the RPC at some future time
192 // by invoking the Receive function on the returned instance. See GetNetworkHashPS for the blocking version and more
193 // details.
194 func (c *Client) GetNetworkHashPSAsync() FutureGetNetworkHashPS {
195 cmd := btcjson.NewGetNetworkHashPSCmd(nil, nil)
196 return c.sendCmd(cmd)
197 }
198 199 // GetNetworkHashPS returns the estimated network hashes per second using the default number of blocks and the most
200 // recent block height. GetNetworkHashPS2 to override the number of blocks to use and GetNetworkHashPS3 to override the
201 // height at which to calculate the estimate.
202 func (c *Client) GetNetworkHashPS() (int64, error) {
203 return c.GetNetworkHashPSAsync().Receive()
204 }
205 206 // GetNetworkHashPS2Async returns an instance of a type that can be used to get the result of the RPC at some future
207 // time by invoking the Receive function on the returned instance. See GetNetworkHashPS2 for the blocking version and
208 // more details.
209 func (c *Client) GetNetworkHashPS2Async(blocks int) FutureGetNetworkHashPS {
210 cmd := btcjson.NewGetNetworkHashPSCmd(&blocks, nil)
211 return c.sendCmd(cmd)
212 }
213 214 // GetNetworkHashPS2 returns the estimated network hashes per second for the specified previous number of blocks working
215 // backwards from the most recent block height.
216 //
217 // The blocks parameter can also be -1 in which case the number of blocks since the last difficulty change will be used.
218 //
219 // See GetNetworkHashPS to use defaults and GetNetworkHashPS3 to override the height at which to calculate the estimate.
220 func (c *Client) GetNetworkHashPS2(blocks int) (int64, error) {
221 return c.GetNetworkHashPS2Async(blocks).Receive()
222 }
223 224 // GetNetworkHashPS3Async returns an instance of a type that can be used to get the result of the RPC at some future
225 // time by invoking the Receive function on the returned instance.
226 //
227 // See GetNetworkHashPS3 for the blocking version and more details.
228 func (c *Client) GetNetworkHashPS3Async(blocks, height int) FutureGetNetworkHashPS {
229 cmd := btcjson.NewGetNetworkHashPSCmd(&blocks, &height)
230 return c.sendCmd(cmd)
231 }
232 233 // GetNetworkHashPS3 returns the estimated network hashes per second for the specified previous number of blocks working
234 // backwards from the specified block height.
235 //
236 // The blocks parameter can also be -1 in which case the number of blocks since the last difficulty change will be used.
237 //
238 // See GetNetworkHashPS and GetNetworkHashPS2 to use defaults.
239 func (c *Client) GetNetworkHashPS3(blocks, height int) (int64, error) {
240 return c.GetNetworkHashPS3Async(blocks, height).Receive()
241 }
242 243 // FutureGetWork is a future promise to deliver the result of a GetWorkAsync RPC invocation (or an applicable error).
244 type FutureGetWork chan *response
245 246 // Receive waits for the response promised by the future and returns the hash data to work on.
247 func (r FutureGetWork) Receive() (*btcjson.GetWorkResult, error) {
248 res, e := receiveFuture(r)
249 if e != nil {
250 return nil, e
251 }
252 // Unmarshal result as a getwork result object.
253 var result btcjson.GetWorkResult
254 e = js.Unmarshal(res, &result)
255 if e != nil {
256 return nil, e
257 }
258 return &result, nil
259 }
260 261 // GetWorkAsync returns an instance of a type that can be used to get the result of the RPC at some future time by
262 // invoking the Receive function on the returned instance.
263 //
264 // See GetWork for the blocking version and more details.
265 func (c *Client) GetWorkAsync() FutureGetWork {
266 cmd := btcjson.NewGetWorkCmd(nil)
267 return c.sendCmd(cmd)
268 }
269 270 // GetWork returns hash data to work on. See GetWorkSubmit to submit the found solution.
271 func (c *Client) GetWork() (*btcjson.GetWorkResult, error) {
272 return c.GetWorkAsync().Receive()
273 }
274 275 // FutureGetWorkSubmit is a future promise to deliver the result of a GetWorkSubmitAsync RPC invocation (or an
276 // applicable error).
277 type FutureGetWorkSubmit chan *response
278 279 // Receive waits for the response promised by the future and returns whether or not the submitted block header was
280 // accepted.
281 func (r FutureGetWorkSubmit) Receive() (bool, error) {
282 res, e := receiveFuture(r)
283 if e != nil {
284 return false, e
285 }
286 // Unmarshal result as a boolean.
287 var accepted bool
288 e = js.Unmarshal(res, &accepted)
289 if e != nil {
290 return false, e
291 }
292 return accepted, nil
293 }
294 295 // GetWorkSubmitAsync returns an instance of a type that can be used to get the result of the RPC at some future time by
296 // invoking the Receive function on the returned instance. See GetWorkSubmit for the blocking version and more details.
297 func (c *Client) GetWorkSubmitAsync(data string) FutureGetWorkSubmit {
298 cmd := btcjson.NewGetWorkCmd(&data)
299 return c.sendCmd(cmd)
300 }
301 302 // GetWorkSubmit submits a block header which is a solution to previously requested data and returns whether or not the
303 // solution was accepted. See GetWork to request data to work on.
304 func (c *Client) GetWorkSubmit(data string) (bool, error) {
305 return c.GetWorkSubmitAsync(data).Receive()
306 }
307 308 // FutureSubmitBlockResult is a future promise to deliver the result of a SubmitBlockAsync RPC invocation (or an
309 // applicable error).
310 type FutureSubmitBlockResult chan *response
311 312 // Receive waits for the response promised by the future and returns an error if any occurred when submitting the block.
313 func (r FutureSubmitBlockResult) Receive() (e error) {
314 res, e := receiveFuture(r)
315 if e != nil {
316 return e
317 }
318 if string(res) != "null" {
319 var result string
320 e = js.Unmarshal(res, &result)
321 if e != nil {
322 return e
323 }
324 return errors.New(result)
325 }
326 return nil
327 }
328 329 // SubmitBlockAsync returns an instance of a type that can be used to get the result of the RPC at some future time by
330 // invoking the Receive function on the returned instance. See SubmitBlock for the blocking version and more details.
331 func (c *Client) SubmitBlockAsync(block *block.Block, options *btcjson.SubmitBlockOptions) FutureSubmitBlockResult {
332 blockHex := ""
333 if block != nil {
334 blockBytes, e := block.Bytes()
335 if e != nil {
336 return newFutureError(e)
337 }
338 blockHex = hex.EncodeToString(blockBytes)
339 }
340 cmd := btcjson.NewSubmitBlockCmd(blockHex, options)
341 return c.sendCmd(cmd)
342 }
343 344 // SubmitBlock attempts to submit a new block into the bitcoin network.
345 func (c *Client) SubmitBlock(block *block.Block, options *btcjson.SubmitBlockOptions) (e error) {
346 return c.SubmitBlockAsync(block, options).Receive()
347 }
348 349 // TODO(davec): Implement GetBlockTemplate
350