mining.go raw

   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