2014-05-07 18:14:39 +02:00
|
|
|
// Copyright (c) 2014 Conformal Systems LLC.
|
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package btcrpcclient
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
|
|
|
"github.com/conformal/btcjson"
|
|
|
|
"github.com/conformal/btcutil"
|
|
|
|
)
|
|
|
|
|
|
|
|
// FutureGetGenerateResult is a future promise to deliver the result of a
|
|
|
|
// GetGenerateAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureGetGenerateResult chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns true if the
|
|
|
|
// server is set to mine, otherwise false.
|
|
|
|
func (r FutureGetGenerateResult) Receive() (bool, error) {
|
|
|
|
reply, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the returned data is the expected type.
|
|
|
|
result, ok := reply.(bool)
|
|
|
|
if !ok {
|
|
|
|
return false, fmt.Errorf("unexpected response type for "+
|
|
|
|
"getgenerate: %T\n", reply)
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetGenerateAsync returns an instance of a type that can be used to get
|
|
|
|
// the result of the RPC at some future time by invoking the Receive function on
|
|
|
|
// the returned instance.
|
|
|
|
//
|
|
|
|
// See GetGenerate for the blocking version and more details.
|
|
|
|
func (c *Client) GetGenerateAsync() FutureGetGenerateResult {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetGenerateCmd(id)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetGenerate returns true if the server is set to mine, otherwise false.
|
|
|
|
func (c *Client) GetGenerate() (bool, error) {
|
|
|
|
return c.GetGenerateAsync().Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// FutureSetGenerateResult is a future promise to deliver the result of a
|
|
|
|
// SetGenerateAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureSetGenerateResult chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns an error if
|
|
|
|
// any occurred when setting the server to generate coins (mine) or not.
|
|
|
|
func (r FutureSetGenerateResult) Receive() error {
|
|
|
|
_, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetGenerateAsync returns an instance of a type that can be used to get the
|
|
|
|
// result of the RPC at some future time by invoking the Receive function on the
|
|
|
|
// returned instance.
|
|
|
|
//
|
|
|
|
// See SetGenerate for the blocking version and more details.
|
|
|
|
func (c *Client) SetGenerateAsync(enable bool, numCPUs int) FutureSetGenerateResult {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewSetGenerateCmd(id, enable, numCPUs)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetGenerate sets the server to generate coins (mine) or not.
|
|
|
|
func (c *Client) SetGenerate(enable bool, numCPUs int) error {
|
|
|
|
return c.SetGenerateAsync(enable, numCPUs).Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// FutureGetHashesPerSecResult is a future promise to deliver the result of a
|
|
|
|
// GetHashesPerSecAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureGetHashesPerSecResult chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns a recent
|
|
|
|
// hashes per second performance measurement while generating coins (mining).
|
|
|
|
// Zero is returned if the server is not mining.
|
|
|
|
func (r FutureGetHashesPerSecResult) Receive() (int64, error) {
|
|
|
|
reply, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return -1, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the returned data is the expected type.
|
|
|
|
result, ok := reply.(int64)
|
|
|
|
if !ok {
|
|
|
|
return -1, fmt.Errorf("unexpected response type for "+
|
|
|
|
"getnetworkhashps: %T\n", reply)
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetHashesPerSecAsync returns an instance of a type that can be used to get
|
|
|
|
// the result of the RPC at some future time by invoking the Receive function on
|
|
|
|
// the returned instance.
|
|
|
|
//
|
|
|
|
// See GetHashesPerSec for the blocking version and more details.
|
|
|
|
func (c *Client) GetHashesPerSecAsync() FutureGetHashesPerSecResult {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetHashesPerSecCmd(id)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetHashesPerSec returns a recent hashes per second performance measurement
|
|
|
|
// while generating coins (mining). Zero is returned if the server is not
|
|
|
|
// mining.
|
|
|
|
func (c *Client) GetHashesPerSec() (int64, error) {
|
|
|
|
return c.GetHashesPerSecAsync().Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// FutureGetMiningInfoResult is a future promise to deliver the result of a
|
|
|
|
// GetMiningInfoAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureGetMiningInfoResult chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns the mining
|
|
|
|
// information.
|
|
|
|
func (r FutureGetMiningInfoResult) Receive() (*btcjson.GetMiningInfoResult, error) {
|
|
|
|
reply, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the returned data is the expected type.
|
2014-05-05 21:23:18 +02:00
|
|
|
result, ok := reply.(*btcjson.GetMiningInfoResult)
|
2014-05-07 18:14:39 +02:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("unexpected response type for "+
|
|
|
|
"getmininginfo: %T\n", reply)
|
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:18 +02:00
|
|
|
return result, nil
|
2014-05-07 18:14:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetMiningInfoAsync returns an instance of a type that can be used to get
|
|
|
|
// the result of the RPC at some future time by invoking the Receive function on
|
|
|
|
// the returned instance.
|
|
|
|
//
|
|
|
|
// See GetMiningInfo for the blocking version and more details.
|
|
|
|
func (c *Client) GetMiningInfoAsync() FutureGetMiningInfoResult {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetMiningInfoCmd(id)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetMiningInfo returns mining information.
|
|
|
|
func (c *Client) GetMiningInfo() (*btcjson.GetMiningInfoResult, error) {
|
|
|
|
return c.GetMiningInfoAsync().Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// FutureGetNetworkHashPS is a future promise to deliver the result of a
|
|
|
|
// GetNetworkHashPSAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureGetNetworkHashPS chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns the
|
|
|
|
// estimated network hashes per second for the block heights provided by the
|
|
|
|
// parameters.
|
|
|
|
func (r FutureGetNetworkHashPS) Receive() (int64, error) {
|
|
|
|
reply, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return -1, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the returned data is the expected type.
|
|
|
|
result, ok := reply.(int64)
|
|
|
|
if !ok {
|
|
|
|
return -1, fmt.Errorf("unexpected response type for "+
|
|
|
|
"getnetworkhashps: %T\n", reply)
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNetworkHashPSAsync returns an instance of a type that can be used to get
|
|
|
|
// the result of the RPC at some future time by invoking the Receive function on
|
|
|
|
// the returned instance.
|
|
|
|
//
|
|
|
|
// See GetNetworkHashPS for the blocking version and more details.
|
|
|
|
func (c *Client) GetNetworkHashPSAsync() FutureGetNetworkHashPS {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetNetworkHashPSCmd(id)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNetworkHashPS returns the estimated network hashes per second using the
|
|
|
|
// default number of blocks and the most recent block height.
|
|
|
|
//
|
|
|
|
// See GetNetworkHashPS2 to override the number of blocks to use and
|
|
|
|
// GetNetworkHashPS3 to override the height at which to calculate the estimate.
|
|
|
|
func (c *Client) GetNetworkHashPS() (int64, error) {
|
|
|
|
return c.GetNetworkHashPSAsync().Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNetworkHashPS2Async returns an instance of a type that can be used to get
|
|
|
|
// the result of the RPC at some future time by invoking the Receive function on
|
|
|
|
// the returned instance.
|
|
|
|
//
|
|
|
|
// See GetNetworkHashPS2 for the blocking version and more details.
|
|
|
|
func (c *Client) GetNetworkHashPS2Async(blocks int) FutureGetNetworkHashPS {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetNetworkHashPSCmd(id, blocks)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNetworkHashPS2 returns the estimated network hashes per second for the
|
|
|
|
// specified previous number of blocks working backwards from the most recent
|
|
|
|
// block height. The blocks parameter can also be -1 in which case the number
|
|
|
|
// of blocks since the last difficulty change will be used.
|
|
|
|
//
|
|
|
|
// See GetNetworkHashPS to use defaults and GetNetworkHashPS3 to override the
|
|
|
|
// height at which to calculate the estimate.
|
|
|
|
func (c *Client) GetNetworkHashPS2(blocks int) (int64, error) {
|
|
|
|
return c.GetNetworkHashPS2Async(blocks).Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNetworkHashPS3Async returns an instance of a type that can be used to get
|
|
|
|
// the result of the RPC at some future time by invoking the Receive function on
|
|
|
|
// the returned instance.
|
|
|
|
//
|
|
|
|
// See GetNetworkHashPS3 for the blocking version and more details.
|
|
|
|
func (c *Client) GetNetworkHashPS3Async(blocks, height int) FutureGetNetworkHashPS {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetNetworkHashPSCmd(id, blocks, height)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNetworkHashPS3 returns the estimated network hashes per second for the
|
|
|
|
// specified previous number of blocks working backwards from the specified
|
|
|
|
// block height. The blocks parameter can also be -1 in which case the number
|
|
|
|
// of blocks since the last difficulty change will be used.
|
|
|
|
//
|
|
|
|
// See GetNetworkHashPS and GetNetworkHashPS2 to use defaults.
|
|
|
|
func (c *Client) GetNetworkHashPS3(blocks, height int) (int64, error) {
|
|
|
|
return c.GetNetworkHashPS3Async(blocks, height).Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// FutureGetWork is a future promise to deliver the result of a
|
|
|
|
// GetWorkAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureGetWork chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns the hash
|
|
|
|
// data to work on.
|
|
|
|
func (r FutureGetWork) Receive() (*btcjson.GetWorkResult, error) {
|
|
|
|
reply, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the returned data is the expected type.
|
2014-05-05 21:23:18 +02:00
|
|
|
result, ok := reply.(*btcjson.GetWorkResult)
|
2014-05-07 18:14:39 +02:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("unexpected response type for "+
|
2014-05-03 08:46:20 +02:00
|
|
|
"getwork (request data): %T\n", reply)
|
2014-05-07 18:14:39 +02:00
|
|
|
}
|
|
|
|
|
2014-05-05 21:23:18 +02:00
|
|
|
return result, nil
|
2014-05-07 18:14:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetWorkAsync returns an instance of a type that can be used to get the result
|
|
|
|
// of the RPC at some future time by invoking the Receive function on the
|
|
|
|
// returned instance.
|
|
|
|
//
|
|
|
|
// See GetWork for the blocking version and more details.
|
|
|
|
func (c *Client) GetWorkAsync() FutureGetWork {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetWorkCmd(id)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetWork returns hash data to work on.
|
2014-05-03 08:46:20 +02:00
|
|
|
//
|
|
|
|
// See GetWorkSubmit to submit the found solution.
|
2014-05-07 18:14:39 +02:00
|
|
|
func (c *Client) GetWork() (*btcjson.GetWorkResult, error) {
|
|
|
|
return c.GetWorkAsync().Receive()
|
|
|
|
}
|
|
|
|
|
2014-05-03 08:46:20 +02:00
|
|
|
// FutureGetWorkSubmit is a future promise to deliver the result of a
|
|
|
|
// GetWorkSubmitAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureGetWorkSubmit chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns whether
|
|
|
|
// or not the submitted block header was accepted.
|
|
|
|
func (r FutureGetWorkSubmit) Receive() (bool, error) {
|
|
|
|
reply, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the returned data is the expected type.
|
|
|
|
accepted, ok := reply.(bool)
|
|
|
|
if !ok {
|
|
|
|
return false, fmt.Errorf("unexpected response type for "+
|
|
|
|
"getwork (submit data): %T\n", reply)
|
|
|
|
}
|
|
|
|
|
|
|
|
return accepted, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetWorkSubmitAsync returns an instance of a type that can be used to get the
|
|
|
|
// result of the RPC at some future time by invoking the Receive function on the
|
|
|
|
// returned instance.
|
|
|
|
//
|
|
|
|
// See GetWorkSubmit for the blocking version and more details.
|
|
|
|
func (c *Client) GetWorkSubmitAsync(data string) FutureGetWorkSubmit {
|
|
|
|
id := c.NextID()
|
|
|
|
cmd, err := btcjson.NewGetWorkCmd(id, data)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetWorkSubmit submits a block header which is a solution to previously
|
|
|
|
// requested data and returns whether or not the solution was accepted.
|
|
|
|
//
|
|
|
|
// See GetWork to request data to work on.
|
|
|
|
func (c *Client) GetWorkSubmit(data string) (bool, error) {
|
|
|
|
return c.GetWorkSubmitAsync(data).Receive()
|
|
|
|
}
|
|
|
|
|
2014-05-07 18:14:39 +02:00
|
|
|
// FutureSubmitBlockResult is a future promise to deliver the result of a
|
|
|
|
// SubmitBlockAsync RPC invocation (or an applicable error).
|
|
|
|
type FutureSubmitBlockResult chan *futureResult
|
|
|
|
|
|
|
|
// Receive waits for the response promised by the future and returns an error if
|
|
|
|
// any occurred when submitting the block.
|
|
|
|
func (r FutureSubmitBlockResult) Receive() error {
|
|
|
|
_, err := receiveFuture(r)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// SubmitBlockAsync returns an instance of a type that can be used to get the
|
|
|
|
// result of the RPC at some future time by invoking the Receive function on the
|
|
|
|
// returned instance.
|
|
|
|
//
|
|
|
|
// See SubmitBlock for the blocking version and more details.
|
|
|
|
func (c *Client) SubmitBlockAsync(block *btcutil.Block, options *btcjson.SubmitBlockOptions) FutureSubmitBlockResult {
|
2014-05-22 02:53:46 +02:00
|
|
|
blockHex := ""
|
|
|
|
if block != nil {
|
|
|
|
blockBytes, err := block.Bytes()
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
blockHex = hex.EncodeToString(blockBytes)
|
2014-05-07 18:14:39 +02:00
|
|
|
}
|
|
|
|
|
2014-05-22 02:53:46 +02:00
|
|
|
id := c.NextID()
|
2014-05-07 18:14:39 +02:00
|
|
|
cmd, err := btcjson.NewSubmitBlockCmd(id, blockHex, options)
|
|
|
|
if err != nil {
|
|
|
|
return newFutureError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.sendCmd(cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SubmitBlock attempts to submit a new block into the bitcoin network.
|
|
|
|
func (c *Client) SubmitBlock(block *btcutil.Block, options *btcjson.SubmitBlockOptions) error {
|
|
|
|
return c.SubmitBlockAsync(block, options).Receive()
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(davec): Implement GetBlockTemplate
|