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