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