lbcd/rpcclient/chain.go
Wilmer Paulino 742935e3a9
rpcclient: send legacy GetBlock request for backwards compatibility
Without this, users of this library wouldn't be able to issue GetBlock
requests to nodes which haven't updated to support the latest request
format, namely the use of a single `int` parameter to denote verbosity
instead of two `bool`s.
2020-05-14 18:05:46 -07:00

1153 lines
38 KiB
Go

// Copyright (c) 2014-2017 The btcsuite developers
// Copyright (c) 2015-2017 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package rpcclient
import (
"bytes"
"encoding/hex"
"encoding/json"
"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
)
// FutureGetBestBlockHashResult is a future promise to deliver the result of a
// GetBestBlockAsync RPC invocation (or an applicable error).
type FutureGetBestBlockHashResult chan *response
// Receive waits for the response promised by the future and returns the hash of
// the best block in the longest block chain.
func (r FutureGetBestBlockHashResult) Receive() (*chainhash.Hash, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a string.
var txHashStr string
err = json.Unmarshal(res, &txHashStr)
if err != nil {
return nil, err
}
return chainhash.NewHashFromStr(txHashStr)
}
// GetBestBlockHashAsync 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 GetBestBlockHash for the blocking version and more details.
func (c *Client) GetBestBlockHashAsync() FutureGetBestBlockHashResult {
cmd := btcjson.NewGetBestBlockHashCmd()
return c.sendCmd(cmd)
}
// GetBestBlockHash returns the hash of the best block in the longest block
// chain.
func (c *Client) GetBestBlockHash() (*chainhash.Hash, error) {
return c.GetBestBlockHashAsync().Receive()
}
// legacyGetBlockRequest constructs and sends a legacy getblock request which
// contains two separate bools to denote verbosity, in contract to a single int
// parameter.
func (c *Client) legacyGetBlockRequest(hash string, verbose,
verboseTx bool) ([]byte, error) {
hashJSON, err := json.Marshal(hash)
if err != nil {
return nil, err
}
verboseJSON, err := json.Marshal(btcjson.Bool(verbose))
if err != nil {
return nil, err
}
verboseTxJSON, err := json.Marshal(btcjson.Bool(verboseTx))
if err != nil {
return nil, err
}
return c.RawRequest("getblock", []json.RawMessage{
hashJSON, verboseJSON, verboseTxJSON,
})
}
// waitForGetBlockRes waits for the response of a getblock request. If the
// response indicates an invalid parameter was provided, a legacy style of the
// request is resent and its response is returned instead.
func (c *Client) waitForGetBlockRes(respChan chan *response, hash string,
verbose, verboseTx bool) ([]byte, error) {
res, err := receiveFuture(respChan)
// If we receive an invalid parameter error, then we may be
// communicating with a btcd node which only understands the legacy
// request, so we'll try that.
if err, ok := err.(*btcjson.RPCError); ok &&
err.Code == btcjson.ErrRPCInvalidParams.Code {
return c.legacyGetBlockRequest(hash, verbose, verboseTx)
}
// Otherwise, we can return the response as is.
return res, err
}
// FutureGetBlockResult is a future promise to deliver the result of a
// GetBlockAsync RPC invocation (or an applicable error).
type FutureGetBlockResult struct {
client *Client
hash string
Response chan *response
}
// Receive waits for the response promised by the future and returns the raw
// block requested from the server given its hash.
func (r FutureGetBlockResult) Receive() (*wire.MsgBlock, error) {
res, err := r.client.waitForGetBlockRes(r.Response, r.hash, false, false)
if err != nil {
return nil, err
}
// Unmarshal result as a string.
var blockHex string
err = json.Unmarshal(res, &blockHex)
if err != nil {
return nil, err
}
// Decode the serialized block hex to raw bytes.
serializedBlock, err := hex.DecodeString(blockHex)
if err != nil {
return nil, err
}
// Deserialize the block and return it.
var msgBlock wire.MsgBlock
err = msgBlock.Deserialize(bytes.NewReader(serializedBlock))
if err != nil {
return nil, err
}
return &msgBlock, nil
}
// GetBlockAsync 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 GetBlock for the blocking version and more details.
func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(0))
return FutureGetBlockResult{
client: c,
hash: hash,
Response: c.sendCmd(cmd),
}
}
// GetBlock returns a raw block from the server given its hash.
//
// See GetBlockVerbose to retrieve a data structure with information about the
// block instead.
func (c *Client) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) {
return c.GetBlockAsync(blockHash).Receive()
}
// FutureGetBlockVerboseResult is a future promise to deliver the result of a
// GetBlockVerboseAsync RPC invocation (or an applicable error).
type FutureGetBlockVerboseResult struct {
client *Client
hash string
Response chan *response
}
// Receive waits for the response promised by the future and returns the data
// structure from the server with information about the requested block.
func (r FutureGetBlockVerboseResult) Receive() (*btcjson.GetBlockVerboseResult, error) {
res, err := r.client.waitForGetBlockRes(r.Response, r.hash, true, false)
if err != nil {
return nil, err
}
// Unmarshal the raw result into a BlockResult.
var blockResult btcjson.GetBlockVerboseResult
err = json.Unmarshal(res, &blockResult)
if err != nil {
return nil, err
}
return &blockResult, nil
}
// GetBlockVerboseAsync 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 GetBlockVerbose for the blocking version and more details.
func (c *Client) GetBlockVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
// From the bitcoin-cli getblock documentation:
// "If verbosity is 1, returns an Object with information about block ."
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(1))
return FutureGetBlockVerboseResult{
client: c,
hash: hash,
Response: c.sendCmd(cmd),
}
}
// GetBlockVerbose returns a data structure from the server with information
// about a block given its hash.
//
// See GetBlockVerboseTx to retrieve transaction data structures as well.
// See GetBlock to retrieve a raw block instead.
func (c *Client) GetBlockVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseResult, error) {
return c.GetBlockVerboseAsync(blockHash).Receive()
}
// FutureGetBlockVerboseTxResult is a future promise to deliver the result of a
// GetBlockVerboseTxResult RPC invocation (or an applicable error).
type FutureGetBlockVerboseTxResult struct {
client *Client
hash string
Response chan *response
}
// Receive waits for the response promised by the future and returns a verbose
// version of the block including detailed information about its transactions.
func (r FutureGetBlockVerboseTxResult) Receive() (*btcjson.GetBlockVerboseTxResult, error) {
res, err := r.client.waitForGetBlockRes(r.Response, r.hash, true, true)
if err != nil {
return nil, err
}
var blockResult btcjson.GetBlockVerboseTxResult
err = json.Unmarshal(res, &blockResult)
if err != nil {
return nil, err
}
return &blockResult, nil
}
// GetBlockVerboseTxAsync 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 GetBlockVerboseTx or the blocking version and more details.
func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseTxResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
// From the bitcoin-cli getblock documentation:
//
// If verbosity is 2, returns an Object with information about block
// and information about each transaction.
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(2))
return FutureGetBlockVerboseTxResult{
client: c,
hash: hash,
Response: c.sendCmd(cmd),
}
}
// GetBlockVerboseTx returns a data structure from the server with information
// about a block and its transactions given its hash.
//
// See GetBlockVerbose if only transaction hashes are preferred.
// See GetBlock to retrieve a raw block instead.
func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseTxResult, error) {
return c.GetBlockVerboseTxAsync(blockHash).Receive()
}
// FutureGetBlockCountResult is a future promise to deliver the result of a
// GetBlockCountAsync RPC invocation (or an applicable error).
type FutureGetBlockCountResult chan *response
// Receive waits for the response promised by the future and returns the number
// of blocks in the longest block chain.
func (r FutureGetBlockCountResult) Receive() (int64, error) {
res, err := receiveFuture(r)
if err != nil {
return 0, err
}
// Unmarshal the result as an int64.
var count int64
err = json.Unmarshal(res, &count)
if err != nil {
return 0, err
}
return count, nil
}
// GetBlockCountAsync 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 GetBlockCount for the blocking version and more details.
func (c *Client) GetBlockCountAsync() FutureGetBlockCountResult {
cmd := btcjson.NewGetBlockCountCmd()
return c.sendCmd(cmd)
}
// GetBlockCount returns the number of blocks in the longest block chain.
func (c *Client) GetBlockCount() (int64, error) {
return c.GetBlockCountAsync().Receive()
}
// FutureGetDifficultyResult is a future promise to deliver the result of a
// GetDifficultyAsync RPC invocation (or an applicable error).
type FutureGetDifficultyResult chan *response
// Receive waits for the response promised by the future and returns the
// proof-of-work difficulty as a multiple of the minimum difficulty.
func (r FutureGetDifficultyResult) Receive() (float64, error) {
res, err := receiveFuture(r)
if err != nil {
return 0, err
}
// Unmarshal the result as a float64.
var difficulty float64
err = json.Unmarshal(res, &difficulty)
if err != nil {
return 0, err
}
return difficulty, nil
}
// GetDifficultyAsync 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 GetDifficulty for the blocking version and more details.
func (c *Client) GetDifficultyAsync() FutureGetDifficultyResult {
cmd := btcjson.NewGetDifficultyCmd()
return c.sendCmd(cmd)
}
// GetDifficulty returns the proof-of-work difficulty as a multiple of the
// minimum difficulty.
func (c *Client) GetDifficulty() (float64, error) {
return c.GetDifficultyAsync().Receive()
}
// FutureGetBlockChainInfoResult is a promise to deliver the result of a
// GetBlockChainInfoAsync RPC invocation (or an applicable error).
type FutureGetBlockChainInfoResult struct {
client *Client
Response chan *response
}
// unmarshalPartialGetBlockChainInfoResult unmarshals the response into an
// instance of GetBlockChainInfoResult without populating the SoftForks and
// UnifiedSoftForks fields.
func unmarshalPartialGetBlockChainInfoResult(res []byte) (*btcjson.GetBlockChainInfoResult, error) {
var chainInfo btcjson.GetBlockChainInfoResult
if err := json.Unmarshal(res, &chainInfo); err != nil {
return nil, err
}
return &chainInfo, nil
}
// unmarshalGetBlockChainInfoResultSoftForks properly unmarshals the softforks
// related fields into the GetBlockChainInfoResult instance.
func unmarshalGetBlockChainInfoResultSoftForks(chainInfo *btcjson.GetBlockChainInfoResult,
version BackendVersion, res []byte) error {
switch version {
// Versions of bitcoind on or after v0.19.0 use the unified format.
case BitcoindPost19:
var softForks btcjson.UnifiedSoftForks
if err := json.Unmarshal(res, &softForks); err != nil {
return err
}
chainInfo.UnifiedSoftForks = &softForks
// All other versions use the original format.
default:
var softForks btcjson.SoftForks
if err := json.Unmarshal(res, &softForks); err != nil {
return err
}
chainInfo.SoftForks = &softForks
}
return nil
}
// Receive waits for the response promised by the future and returns chain info
// result provided by the server.
func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResult, error) {
res, err := receiveFuture(r.Response)
if err != nil {
return nil, err
}
chainInfo, err := unmarshalPartialGetBlockChainInfoResult(res)
if err != nil {
return nil, err
}
// Inspect the version to determine how we'll need to parse the
// softforks from the response.
version, err := r.client.BackendVersion()
if err != nil {
return nil, err
}
err = unmarshalGetBlockChainInfoResultSoftForks(chainInfo, version, res)
if err != nil {
return nil, err
}
return chainInfo, nil
}
// GetBlockChainInfoAsync 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 GetBlockChainInfo for the blocking version and more details.
func (c *Client) GetBlockChainInfoAsync() FutureGetBlockChainInfoResult {
cmd := btcjson.NewGetBlockChainInfoCmd()
return FutureGetBlockChainInfoResult{
client: c,
Response: c.sendCmd(cmd),
}
}
// GetBlockChainInfo returns information related to the processing state of
// various chain-specific details such as the current difficulty from the tip
// of the main chain.
func (c *Client) GetBlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) {
return c.GetBlockChainInfoAsync().Receive()
}
// FutureGetBlockHashResult is a future promise to deliver the result of a
// GetBlockHashAsync RPC invocation (or an applicable error).
type FutureGetBlockHashResult chan *response
// Receive waits for the response promised by the future and returns the hash of
// the block in the best block chain at the given height.
func (r FutureGetBlockHashResult) Receive() (*chainhash.Hash, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal the result as a string-encoded sha.
var txHashStr string
err = json.Unmarshal(res, &txHashStr)
if err != nil {
return nil, err
}
return chainhash.NewHashFromStr(txHashStr)
}
// GetBlockHashAsync 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 GetBlockHash for the blocking version and more details.
func (c *Client) GetBlockHashAsync(blockHeight int64) FutureGetBlockHashResult {
cmd := btcjson.NewGetBlockHashCmd(blockHeight)
return c.sendCmd(cmd)
}
// GetBlockHash returns the hash of the block in the best block chain at the
// given height.
func (c *Client) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) {
return c.GetBlockHashAsync(blockHeight).Receive()
}
// FutureGetBlockHeaderResult is a future promise to deliver the result of a
// GetBlockHeaderAsync RPC invocation (or an applicable error).
type FutureGetBlockHeaderResult chan *response
// Receive waits for the response promised by the future and returns the
// blockheader requested from the server given its hash.
func (r FutureGetBlockHeaderResult) Receive() (*wire.BlockHeader, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a string.
var bhHex string
err = json.Unmarshal(res, &bhHex)
if err != nil {
return nil, err
}
serializedBH, err := hex.DecodeString(bhHex)
if err != nil {
return nil, err
}
// Deserialize the blockheader and return it.
var bh wire.BlockHeader
err = bh.Deserialize(bytes.NewReader(serializedBH))
if err != nil {
return nil, err
}
return &bh, err
}
// GetBlockHeaderAsync 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 GetBlockHeader for the blocking version and more details.
func (c *Client) GetBlockHeaderAsync(blockHash *chainhash.Hash) FutureGetBlockHeaderResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewGetBlockHeaderCmd(hash, btcjson.Bool(false))
return c.sendCmd(cmd)
}
// GetBlockHeader returns the blockheader from the server given its hash.
//
// See GetBlockHeaderVerbose to retrieve a data structure with information about the
// block instead.
func (c *Client) GetBlockHeader(blockHash *chainhash.Hash) (*wire.BlockHeader, error) {
return c.GetBlockHeaderAsync(blockHash).Receive()
}
// FutureGetBlockHeaderVerboseResult is a future promise to deliver the result of a
// GetBlockAsync RPC invocation (or an applicable error).
type FutureGetBlockHeaderVerboseResult chan *response
// Receive waits for the response promised by the future and returns the
// data structure of the blockheader requested from the server given its hash.
func (r FutureGetBlockHeaderVerboseResult) Receive() (*btcjson.GetBlockHeaderVerboseResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a string.
var bh btcjson.GetBlockHeaderVerboseResult
err = json.Unmarshal(res, &bh)
if err != nil {
return nil, err
}
return &bh, nil
}
// GetBlockHeaderVerboseAsync 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 GetBlockHeader for the blocking version and more details.
func (c *Client) GetBlockHeaderVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockHeaderVerboseResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewGetBlockHeaderCmd(hash, btcjson.Bool(true))
return c.sendCmd(cmd)
}
// GetBlockHeaderVerbose returns a data structure with information about the
// blockheader from the server given its hash.
//
// See GetBlockHeader to retrieve a blockheader instead.
func (c *Client) GetBlockHeaderVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockHeaderVerboseResult, error) {
return c.GetBlockHeaderVerboseAsync(blockHash).Receive()
}
// FutureGetMempoolEntryResult is a future promise to deliver the result of a
// GetMempoolEntryAsync RPC invocation (or an applicable error).
type FutureGetMempoolEntryResult chan *response
// Receive waits for the response promised by the future and returns a data
// structure with information about the transaction in the memory pool given
// its hash.
func (r FutureGetMempoolEntryResult) Receive() (*btcjson.GetMempoolEntryResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal the result as an array of strings.
var mempoolEntryResult btcjson.GetMempoolEntryResult
err = json.Unmarshal(res, &mempoolEntryResult)
if err != nil {
return nil, err
}
return &mempoolEntryResult, nil
}
// GetMempoolEntryAsync 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 GetMempoolEntry for the blocking version and more details.
func (c *Client) GetMempoolEntryAsync(txHash string) FutureGetMempoolEntryResult {
cmd := btcjson.NewGetMempoolEntryCmd(txHash)
return c.sendCmd(cmd)
}
// GetMempoolEntry returns a data structure with information about the
// transaction in the memory pool given its hash.
func (c *Client) GetMempoolEntry(txHash string) (*btcjson.GetMempoolEntryResult, error) {
return c.GetMempoolEntryAsync(txHash).Receive()
}
// FutureGetRawMempoolResult is a future promise to deliver the result of a
// GetRawMempoolAsync RPC invocation (or an applicable error).
type FutureGetRawMempoolResult chan *response
// Receive waits for the response promised by the future and returns the hashes
// of all transactions in the memory pool.
func (r FutureGetRawMempoolResult) Receive() ([]*chainhash.Hash, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal the result as an array of strings.
var txHashStrs []string
err = json.Unmarshal(res, &txHashStrs)
if err != nil {
return nil, err
}
// Create a slice of ShaHash arrays from the string slice.
txHashes := make([]*chainhash.Hash, 0, len(txHashStrs))
for _, hashStr := range txHashStrs {
txHash, err := chainhash.NewHashFromStr(hashStr)
if err != nil {
return nil, err
}
txHashes = append(txHashes, txHash)
}
return txHashes, nil
}
// GetRawMempoolAsync 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 GetRawMempool for the blocking version and more details.
func (c *Client) GetRawMempoolAsync() FutureGetRawMempoolResult {
cmd := btcjson.NewGetRawMempoolCmd(btcjson.Bool(false))
return c.sendCmd(cmd)
}
// GetRawMempool returns the hashes of all transactions in the memory pool.
//
// See GetRawMempoolVerbose to retrieve data structures with information about
// the transactions instead.
func (c *Client) GetRawMempool() ([]*chainhash.Hash, error) {
return c.GetRawMempoolAsync().Receive()
}
// FutureGetRawMempoolVerboseResult is a future promise to deliver the result of
// a GetRawMempoolVerboseAsync RPC invocation (or an applicable error).
type FutureGetRawMempoolVerboseResult chan *response
// Receive waits for the response promised by the future and returns a map of
// transaction hashes to an associated data structure with information about the
// transaction for all transactions in the memory pool.
func (r FutureGetRawMempoolVerboseResult) Receive() (map[string]btcjson.GetRawMempoolVerboseResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal the result as a map of strings (tx shas) to their detailed
// results.
var mempoolItems map[string]btcjson.GetRawMempoolVerboseResult
err = json.Unmarshal(res, &mempoolItems)
if err != nil {
return nil, err
}
return mempoolItems, nil
}
// GetRawMempoolVerboseAsync 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 GetRawMempoolVerbose for the blocking version and more details.
func (c *Client) GetRawMempoolVerboseAsync() FutureGetRawMempoolVerboseResult {
cmd := btcjson.NewGetRawMempoolCmd(btcjson.Bool(true))
return c.sendCmd(cmd)
}
// GetRawMempoolVerbose returns a map of transaction hashes to an associated
// data structure with information about the transaction for all transactions in
// the memory pool.
//
// See GetRawMempool to retrieve only the transaction hashes instead.
func (c *Client) GetRawMempoolVerbose() (map[string]btcjson.GetRawMempoolVerboseResult, error) {
return c.GetRawMempoolVerboseAsync().Receive()
}
// FutureEstimateFeeResult is a future promise to deliver the result of a
// EstimateFeeAsync RPC invocation (or an applicable error).
type FutureEstimateFeeResult chan *response
// Receive waits for the response promised by the future and returns the info
// provided by the server.
func (r FutureEstimateFeeResult) Receive() (float64, error) {
res, err := receiveFuture(r)
if err != nil {
return -1, err
}
// Unmarshal result as a getinfo result object.
var fee float64
err = json.Unmarshal(res, &fee)
if err != nil {
return -1, err
}
return fee, nil
}
// EstimateFeeAsync 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 EstimateFee for the blocking version and more details.
func (c *Client) EstimateFeeAsync(numBlocks int64) FutureEstimateFeeResult {
cmd := btcjson.NewEstimateFeeCmd(numBlocks)
return c.sendCmd(cmd)
}
// EstimateFee provides an estimated fee in bitcoins per kilobyte.
func (c *Client) EstimateFee(numBlocks int64) (float64, error) {
return c.EstimateFeeAsync(numBlocks).Receive()
}
// FutureEstimateFeeResult is a future promise to deliver the result of a
// EstimateSmartFeeAsync RPC invocation (or an applicable error).
type FutureEstimateSmartFeeResult chan *response
// Receive waits for the response promised by the future and returns the
// estimated fee.
func (r FutureEstimateSmartFeeResult) Receive() (*btcjson.EstimateSmartFeeResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
var verified btcjson.EstimateSmartFeeResult
err = json.Unmarshal(res, &verified)
if err != nil {
return nil, err
}
return &verified, nil
}
// EstimateSmartFeeAsync 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 EstimateSmartFee for the blocking version and more details.
func (c *Client) EstimateSmartFeeAsync(confTarget int64, mode *btcjson.EstimateSmartFeeMode) FutureEstimateSmartFeeResult {
cmd := btcjson.NewEstimateSmartFeeCmd(confTarget, mode)
return c.sendCmd(cmd)
}
// EstimateSmartFee requests the server to estimate a fee level based on the given parameters.
func (c *Client) EstimateSmartFee(confTarget int64, mode *btcjson.EstimateSmartFeeMode) (*btcjson.EstimateSmartFeeResult, error) {
return c.EstimateSmartFeeAsync(confTarget, mode).Receive()
}
// FutureVerifyChainResult is a future promise to deliver the result of a
// VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync
// invocation (or an applicable error).
type FutureVerifyChainResult chan *response
// Receive waits for the response promised by the future and returns whether
// or not the chain verified based on the check level and number of blocks
// to verify specified in the original call.
func (r FutureVerifyChainResult) Receive() (bool, error) {
res, err := receiveFuture(r)
if err != nil {
return false, err
}
// Unmarshal the result as a boolean.
var verified bool
err = json.Unmarshal(res, &verified)
if err != nil {
return false, err
}
return verified, nil
}
// VerifyChainAsync 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 VerifyChain for the blocking version and more details.
func (c *Client) VerifyChainAsync() FutureVerifyChainResult {
cmd := btcjson.NewVerifyChainCmd(nil, nil)
return c.sendCmd(cmd)
}
// VerifyChain requests the server to verify the block chain database using
// the default check level and number of blocks to verify.
//
// See VerifyChainLevel and VerifyChainBlocks to override the defaults.
func (c *Client) VerifyChain() (bool, error) {
return c.VerifyChainAsync().Receive()
}
// VerifyChainLevelAsync 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 VerifyChainLevel for the blocking version and more details.
func (c *Client) VerifyChainLevelAsync(checkLevel int32) FutureVerifyChainResult {
cmd := btcjson.NewVerifyChainCmd(&checkLevel, nil)
return c.sendCmd(cmd)
}
// VerifyChainLevel requests the server to verify the block chain database using
// the passed check level and default number of blocks to verify.
//
// The check level controls how thorough the verification is with higher numbers
// increasing the amount of checks done as consequently how long the
// verification takes.
//
// See VerifyChain to use the default check level and VerifyChainBlocks to
// override the number of blocks to verify.
func (c *Client) VerifyChainLevel(checkLevel int32) (bool, error) {
return c.VerifyChainLevelAsync(checkLevel).Receive()
}
// VerifyChainBlocksAsync 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 VerifyChainBlocks for the blocking version and more details.
func (c *Client) VerifyChainBlocksAsync(checkLevel, numBlocks int32) FutureVerifyChainResult {
cmd := btcjson.NewVerifyChainCmd(&checkLevel, &numBlocks)
return c.sendCmd(cmd)
}
// VerifyChainBlocks requests the server to verify the block chain database
// using the passed check level and number of blocks to verify.
//
// The check level controls how thorough the verification is with higher numbers
// increasing the amount of checks done as consequently how long the
// verification takes.
//
// The number of blocks refers to the number of blocks from the end of the
// current longest chain.
//
// See VerifyChain and VerifyChainLevel to use defaults.
func (c *Client) VerifyChainBlocks(checkLevel, numBlocks int32) (bool, error) {
return c.VerifyChainBlocksAsync(checkLevel, numBlocks).Receive()
}
// FutureGetTxOutResult is a future promise to deliver the result of a
// GetTxOutAsync RPC invocation (or an applicable error).
type FutureGetTxOutResult chan *response
// Receive waits for the response promised by the future and returns a
// transaction given its hash.
func (r FutureGetTxOutResult) Receive() (*btcjson.GetTxOutResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// take care of the special case where the output has been spent already
// it should return the string "null"
if string(res) == "null" {
return nil, nil
}
// Unmarshal result as an gettxout result object.
var txOutInfo *btcjson.GetTxOutResult
err = json.Unmarshal(res, &txOutInfo)
if err != nil {
return nil, err
}
return txOutInfo, nil
}
// GetTxOutAsync 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 GetTxOut for the blocking version and more details.
func (c *Client) GetTxOutAsync(txHash *chainhash.Hash, index uint32, mempool bool) FutureGetTxOutResult {
hash := ""
if txHash != nil {
hash = txHash.String()
}
cmd := btcjson.NewGetTxOutCmd(hash, index, &mempool)
return c.sendCmd(cmd)
}
// GetTxOut returns the transaction output info if it's unspent and
// nil, otherwise.
func (c *Client) GetTxOut(txHash *chainhash.Hash, index uint32, mempool bool) (*btcjson.GetTxOutResult, error) {
return c.GetTxOutAsync(txHash, index, mempool).Receive()
}
// FutureRescanBlocksResult is a future promise to deliver the result of a
// RescanBlocksAsync RPC invocation (or an applicable error).
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
type FutureRescanBlocksResult chan *response
// Receive waits for the response promised by the future and returns the
// discovered rescanblocks data.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (r FutureRescanBlocksResult) Receive() ([]btcjson.RescannedBlock, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
var rescanBlocksResult []btcjson.RescannedBlock
err = json.Unmarshal(res, &rescanBlocksResult)
if err != nil {
return nil, err
}
return rescanBlocksResult, nil
}
// RescanBlocksAsync 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 RescanBlocks for the blocking version and more details.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) RescanBlocksAsync(blockHashes []chainhash.Hash) FutureRescanBlocksResult {
strBlockHashes := make([]string, len(blockHashes))
for i := range blockHashes {
strBlockHashes[i] = blockHashes[i].String()
}
cmd := btcjson.NewRescanBlocksCmd(strBlockHashes)
return c.sendCmd(cmd)
}
// RescanBlocks rescans the blocks identified by blockHashes, in order, using
// the client's loaded transaction filter. The blocks do not need to be on the
// main chain, but they do need to be adjacent to each other.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) RescanBlocks(blockHashes []chainhash.Hash) ([]btcjson.RescannedBlock, error) {
return c.RescanBlocksAsync(blockHashes).Receive()
}
// FutureInvalidateBlockResult is a future promise to deliver the result of a
// InvalidateBlockAsync RPC invocation (or an applicable error).
type FutureInvalidateBlockResult chan *response
// Receive waits for the response promised by the future and returns the raw
// block requested from the server given its hash.
func (r FutureInvalidateBlockResult) Receive() error {
_, err := receiveFuture(r)
return err
}
// InvalidateBlockAsync 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 InvalidateBlock for the blocking version and more details.
func (c *Client) InvalidateBlockAsync(blockHash *chainhash.Hash) FutureInvalidateBlockResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewInvalidateBlockCmd(hash)
return c.sendCmd(cmd)
}
// InvalidateBlock invalidates a specific block.
func (c *Client) InvalidateBlock(blockHash *chainhash.Hash) error {
return c.InvalidateBlockAsync(blockHash).Receive()
}
// FutureGetCFilterResult is a future promise to deliver the result of a
// GetCFilterAsync RPC invocation (or an applicable error).
type FutureGetCFilterResult chan *response
// Receive waits for the response promised by the future and returns the raw
// filter requested from the server given its block hash.
func (r FutureGetCFilterResult) Receive() (*wire.MsgCFilter, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a string.
var filterHex string
err = json.Unmarshal(res, &filterHex)
if err != nil {
return nil, err
}
// Decode the serialized cf hex to raw bytes.
serializedFilter, err := hex.DecodeString(filterHex)
if err != nil {
return nil, err
}
// Assign the filter bytes to the correct field of the wire message.
// We aren't going to set the block hash or extended flag, since we
// don't actually get that back in the RPC response.
var msgCFilter wire.MsgCFilter
msgCFilter.Data = serializedFilter
return &msgCFilter, nil
}
// GetCFilterAsync 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 GetCFilter for the blocking version and more details.
func (c *Client) GetCFilterAsync(blockHash *chainhash.Hash,
filterType wire.FilterType) FutureGetCFilterResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewGetCFilterCmd(hash, filterType)
return c.sendCmd(cmd)
}
// GetCFilter returns a raw filter from the server given its block hash.
func (c *Client) GetCFilter(blockHash *chainhash.Hash,
filterType wire.FilterType) (*wire.MsgCFilter, error) {
return c.GetCFilterAsync(blockHash, filterType).Receive()
}
// FutureGetCFilterHeaderResult is a future promise to deliver the result of a
// GetCFilterHeaderAsync RPC invocation (or an applicable error).
type FutureGetCFilterHeaderResult chan *response
// Receive waits for the response promised by the future and returns the raw
// filter header requested from the server given its block hash.
func (r FutureGetCFilterHeaderResult) Receive() (*wire.MsgCFHeaders, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a string.
var headerHex string
err = json.Unmarshal(res, &headerHex)
if err != nil {
return nil, err
}
// Assign the decoded header into a hash
headerHash, err := chainhash.NewHashFromStr(headerHex)
if err != nil {
return nil, err
}
// Assign the hash to a headers message and return it.
msgCFHeaders := wire.MsgCFHeaders{PrevFilterHeader: *headerHash}
return &msgCFHeaders, nil
}
// GetCFilterHeaderAsync 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 GetCFilterHeader for the blocking version and more details.
func (c *Client) GetCFilterHeaderAsync(blockHash *chainhash.Hash,
filterType wire.FilterType) FutureGetCFilterHeaderResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewGetCFilterHeaderCmd(hash, filterType)
return c.sendCmd(cmd)
}
// GetCFilterHeader returns a raw filter header from the server given its block
// hash.
func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash,
filterType wire.FilterType) (*wire.MsgCFHeaders, error) {
return c.GetCFilterHeaderAsync(blockHash, filterType).Receive()
}
// FutureGetBlockStatsResult is a future promise to deliver the result of a
// GetBlockStatsAsync RPC invocation (or an applicable error).
type FutureGetBlockStatsResult chan *response
// Receive waits for the response promised by the future and returns statistics
// of a block at a certain height.
func (r FutureGetBlockStatsResult) Receive() (*btcjson.GetBlockStatsResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
var blockStats btcjson.GetBlockStatsResult
err = json.Unmarshal(res, &blockStats)
if err != nil {
return nil, err
}
return &blockStats, nil
}
// GetBlockStatsAsync 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 GetBlockStats or the blocking version and more details.
func (c *Client) GetBlockStatsAsync(hashOrHeight interface{}, stats *[]string) FutureGetBlockStatsResult {
if hash, ok := hashOrHeight.(*chainhash.Hash); ok {
hashOrHeight = hash.String()
}
cmd := btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: hashOrHeight}, stats)
return c.sendCmd(cmd)
}
// GetBlockStats returns block statistics. First argument specifies height or hash of the target block.
// Second argument allows to select certain stats to return.
func (c *Client) GetBlockStats(hashOrHeight interface{}, stats *[]string) (*btcjson.GetBlockStatsResult, error) {
return c.GetBlockStatsAsync(hashOrHeight, stats).Receive()
}