Release v0.3.0

This commit is contained in:
Manu Herrera
2020-11-09 10:05:29 -03:00
parent 4e9aa7a3c5
commit 8107c4478b
1265 changed files with 440488 additions and 107809 deletions

View File

@@ -52,14 +52,61 @@ 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 chan *response
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 := receiveFuture(r)
res, err := r.client.waitForGetBlockRes(r.Response, r.hash, false, false)
if err != nil {
return nil, err
}
@@ -97,8 +144,12 @@ func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult {
hash = blockHash.String()
}
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), nil)
return c.sendCmd(cmd)
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.
@@ -111,12 +162,16 @@ func (c *Client) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) {
// FutureGetBlockVerboseResult is a future promise to deliver the result of a
// GetBlockVerboseAsync RPC invocation (or an applicable error).
type FutureGetBlockVerboseResult chan *response
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 := receiveFuture(r)
res, err := r.client.waitForGetBlockRes(r.Response, r.hash, true, false)
if err != nil {
return nil, err
}
@@ -140,9 +195,14 @@ func (c *Client) GetBlockVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockV
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), nil)
return c.sendCmd(cmd)
// 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
@@ -154,19 +214,52 @@ func (c *Client) GetBlockVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockVe
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) FutureGetBlockVerboseResult {
func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseTxResult {
hash := ""
if blockHash != nil {
hash = blockHash.String()
}
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), btcjson.Bool(true))
return c.sendCmd(cmd)
// 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
@@ -174,7 +267,7 @@ func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBloc
//
// See GetBlockVerbose if only transaction hashes are preferred.
// See GetBlock to retrieve a raw block instead.
func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseResult, error) {
func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseTxResult, error) {
return c.GetBlockVerboseTxAsync(blockHash).Receive()
}
@@ -214,6 +307,79 @@ func (c *Client) GetBlockCount() (int64, error) {
return c.GetBlockCountAsync().Receive()
}
// FutureGetChainTxStatsResult is a future promise to deliver the result of a
// GetChainTxStatsAsync RPC invocation (or an applicable error).
type FutureGetChainTxStatsResult chan *response
// Receive waits for the response promised by the future and returns transaction statistics
func (r FutureGetChainTxStatsResult) Receive() (*btcjson.GetChainTxStatsResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
var chainTxStats btcjson.GetChainTxStatsResult
err = json.Unmarshal(res, &chainTxStats)
if err != nil {
return nil, err
}
return &chainTxStats, nil
}
// GetChainTxStatsAsync 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 GetChainTxStats for the blocking version and more details.
func (c *Client) GetChainTxStatsAsync() FutureGetChainTxStatsResult {
cmd := btcjson.NewGetChainTxStatsCmd(nil, nil)
return c.sendCmd(cmd)
}
// GetChainTxStatsNBlocksAsync 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 GetChainTxStatsNBlocks for the blocking version and more details.
func (c *Client) GetChainTxStatsNBlocksAsync(nBlocks int32) FutureGetChainTxStatsResult {
cmd := btcjson.NewGetChainTxStatsCmd(&nBlocks, nil)
return c.sendCmd(cmd)
}
// GetChainTxStatsNBlocksBlockHashAsync 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 GetChainTxStatsNBlocksBlockHash for the blocking version and more details.
func (c *Client) GetChainTxStatsNBlocksBlockHashAsync(nBlocks int32, blockHash chainhash.Hash) FutureGetChainTxStatsResult {
hash := blockHash.String()
cmd := btcjson.NewGetChainTxStatsCmd(&nBlocks, &hash)
return c.sendCmd(cmd)
}
// GetChainTxStats returns statistics about the total number and rate of transactions in the chain.
//
// Size of the window is one month and it ends at chain tip.
func (c *Client) GetChainTxStats() (*btcjson.GetChainTxStatsResult, error) {
return c.GetChainTxStatsAsync().Receive()
}
// GetChainTxStatsNBlocks returns statistics about the total number and rate of transactions in the chain.
//
// The argument specifies size of the window in number of blocks. The window ends at chain tip.
func (c *Client) GetChainTxStatsNBlocks(nBlocks int32) (*btcjson.GetChainTxStatsResult, error) {
return c.GetChainTxStatsNBlocksAsync(nBlocks).Receive()
}
// GetChainTxStatsNBlocksBlockHash returns statistics about the total number and rate of transactions in the chain.
//
// First argument specifies size of the window in number of blocks.
// Second argument is the hash of the block that ends the window.
func (c *Client) GetChainTxStatsNBlocksBlockHash(nBlocks int32, blockHash chainhash.Hash) (*btcjson.GetChainTxStatsResult, error) {
return c.GetChainTxStatsNBlocksBlockHashAsync(nBlocks, blockHash).Receive()
}
// FutureGetDifficultyResult is a future promise to deliver the result of a
// GetDifficultyAsync RPC invocation (or an applicable error).
type FutureGetDifficultyResult chan *response
@@ -649,6 +815,41 @@ 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).
@@ -982,3 +1183,44 @@ 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()
}

View File

@@ -0,0 +1,38 @@
// Copyright (c) 2017 The Namecoin developers
// Copyright (c) 2019 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package rpcclient
import (
"bufio"
"fmt"
"os"
"strings"
)
func readCookieFile(path string) (username, password string, err error) {
f, err := os.Open(path)
if err != nil {
return
}
defer f.Close()
scanner := bufio.NewScanner(f)
scanner.Scan()
err = scanner.Err()
if err != nil {
return
}
s := scanner.Text()
parts := strings.SplitN(s, ":", 2)
if len(parts) != 2 {
err = fmt.Errorf("malformed cookie file")
return
}
username, password = parts[0], parts[1]
return
}

View File

@@ -106,7 +106,7 @@ Some of the commands are extensions specific to a particular RPC server. For
example, the DebugLevel call is an extension only provided by btcd (and
btcwallet passthrough). Therefore if you call one of these commands against
an RPC server that doesn't provide them, you will get an unimplemented error
from the server. An effort has been made to call out which commmands are
from the server. An effort has been made to call out which commands are
extensions in their documentation.
Also, it is important to realize that btcd intentionally separates the wallet

View File

@@ -19,12 +19,14 @@ import (
"net"
"net/http"
"net/url"
"os"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/go-socks/socks"
"github.com/btcsuite/websocket"
)
@@ -138,6 +140,10 @@ type Client struct {
// config holds the connection configuration assoiated with this client.
config *ConnConfig
// chainParams holds the params for the chain that this client is using,
// and is used for many wallet methods.
chainParams *chaincfg.Params
// wsConn is the underlying websocket connection when not in HTTP POST
// mode.
wsConn *websocket.Conn
@@ -283,31 +289,29 @@ func (c *Client) trackRegisteredNtfns(cmd interface{}) {
}
}
type (
// inMessage is the first type that an incoming message is unmarshaled
// into. It supports both requests (for notification support) and
// responses. The partially-unmarshaled message is a notification if
// the embedded ID (from the response) is nil. Otherwise, it is a
// response.
inMessage struct {
ID *float64 `json:"id"`
*rawNotification
*rawResponse
}
// inMessage is the first type that an incoming message is unmarshaled
// into. It supports both requests (for notification support) and
// responses. The partially-unmarshaled message is a notification if
// the embedded ID (from the response) is nil. Otherwise, it is a
// response.
type inMessage struct {
ID *float64 `json:"id"`
*rawNotification
*rawResponse
}
// rawNotification is a partially-unmarshaled JSON-RPC notification.
rawNotification struct {
Method string `json:"method"`
Params []json.RawMessage `json:"params"`
}
// rawNotification is a partially-unmarshaled JSON-RPC notification.
type rawNotification struct {
Method string `json:"method"`
Params []json.RawMessage `json:"params"`
}
// rawResponse is a partially-unmarshaled JSON-RPC response. For this
// to be valid (according to JSON-RPC 1.0 spec), ID may not be nil.
rawResponse struct {
Result json.RawMessage `json:"result"`
Error *btcjson.RPCError `json:"error"`
}
)
// rawResponse is a partially-unmarshaled JSON-RPC response. For this
// to be valid (according to JSON-RPC 1.0 spec), ID may not be nil.
type rawResponse struct {
Result json.RawMessage `json:"result"`
Error *btcjson.RPCError `json:"error"`
}
// response is the raw bytes of a JSON-RPC result, or the error if the response
// error object was non-null.
@@ -848,7 +852,12 @@ func (c *Client) sendPost(jReq *jsonRequest) {
httpReq.Header.Set("Content-Type", "application/json")
// Configure basic access authorization.
httpReq.SetBasicAuth(c.config.User, c.config.Pass)
user, pass, err := c.config.getAuth()
if err != nil {
jReq.responseChan <- &response{result: nil, err: err}
return
}
httpReq.SetBasicAuth(user, pass)
log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id)
c.sendPostRequest(httpReq, jReq)
@@ -1093,6 +1102,22 @@ type ConnConfig struct {
// Pass is the passphrase to use to authenticate to the RPC server.
Pass string
// CookiePath is the path to a cookie file containing the username and
// passphrase to use to authenticate to the RPC server. It is used
// instead of User and Pass if non-empty.
CookiePath string
cookieLastCheckTime time.Time
cookieLastModTime time.Time
cookieLastUser string
cookieLastPass string
cookieLastErr error
// Params is the string representing the network that the server
// is running. If there is no parameter set in the config, then
// mainnet will be used by default.
Params string
// DisableTLS specifies whether transport layer security should be
// disabled. It is recommended to always use TLS if the RPC server
// supports it as otherwise your username and password is sent across
@@ -1141,6 +1166,43 @@ type ConnConfig struct {
EnableBCInfoHacks bool
}
// getAuth returns the username and passphrase that will actually be used for
// this connection. This will be the result of checking the cookie if a cookie
// path is configured; if not, it will be the user-configured username and
// passphrase.
func (config *ConnConfig) getAuth() (username, passphrase string, err error) {
// Try username+passphrase auth first.
if config.Pass != "" {
return config.User, config.Pass, nil
}
// If no username or passphrase is set, try cookie auth.
return config.retrieveCookie()
}
// retrieveCookie returns the cookie username and passphrase.
func (config *ConnConfig) retrieveCookie() (username, passphrase string, err error) {
if !config.cookieLastCheckTime.IsZero() && time.Now().Before(config.cookieLastCheckTime.Add(30*time.Second)) {
return config.cookieLastUser, config.cookieLastPass, config.cookieLastErr
}
config.cookieLastCheckTime = time.Now()
st, err := os.Stat(config.CookiePath)
if err != nil {
config.cookieLastErr = err
return config.cookieLastUser, config.cookieLastPass, config.cookieLastErr
}
modTime := st.ModTime()
if !modTime.Equal(config.cookieLastModTime) {
config.cookieLastModTime = modTime
config.cookieLastUser, config.cookieLastPass, config.cookieLastErr = readCookieFile(config.CookiePath)
}
return config.cookieLastUser, config.cookieLastPass, config.cookieLastErr
}
// newHTTPClient returns a new http client that is configured according to the
// proxy and TLS settings in the associated connection configuration.
func newHTTPClient(config *ConnConfig) (*http.Client, error) {
@@ -1210,7 +1272,11 @@ func dial(config *ConnConfig) (*websocket.Conn, error) {
// The RPC server requires basic authorization, so create a custom
// request header with the Authorization header set.
login := config.User + ":" + config.Pass
user, pass, err := config.getAuth()
if err != nil {
return nil, err
}
login := user + ":" + pass
auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
requestHeader := make(http.Header)
requestHeader.Add("Authorization", auth)
@@ -1290,6 +1356,23 @@ func New(config *ConnConfig, ntfnHandlers *NotificationHandlers) (*Client, error
shutdown: make(chan struct{}),
}
// Default network is mainnet, no parameters are necessary but if mainnet
// is specified it will be the param
switch config.Params {
case "":
fallthrough
case chaincfg.MainNetParams.Name:
client.chainParams = &chaincfg.MainNetParams
case chaincfg.TestNet3Params.Name:
client.chainParams = &chaincfg.TestNet3Params
case chaincfg.RegressionNetParams.Name:
client.chainParams = &chaincfg.RegressionNetParams
case chaincfg.SimNetParams.Name:
client.chainParams = &chaincfg.SimNetParams
default:
return nil, fmt.Errorf("rpcclient.New: Unknown chain %s", config.Params)
}
if start {
log.Infof("Established connection to RPC server %s",
config.Host)

View File

@@ -61,6 +61,53 @@ func (c *Client) Generate(numBlocks uint32) ([]*chainhash.Hash, error) {
return c.GenerateAsync(numBlocks).Receive()
}
// FutureGenerateToAddressResult is a future promise to deliver the result of a
// GenerateToAddressResult RPC invocation (or an applicable error).
type FutureGenerateToAddressResult chan *response
// Receive waits for the response promised by the future and returns the hashes of
// of the generated blocks.
func (f FutureGenerateToAddressResult) Receive() ([]*chainhash.Hash, error) {
res, err := receiveFuture(f)
if err != nil {
return nil, err
}
// Unmarshal result as a list of strings.
var result []string
err = json.Unmarshal(res, &result)
if err != nil {
return nil, err
}
// Convert each block hash to a chainhash.Hash and store a pointer to
// each.
convertedResult := make([]*chainhash.Hash, len(result))
for i, hashString := range result {
convertedResult[i], err = chainhash.NewHashFromStr(hashString)
if err != nil {
return nil, err
}
}
return convertedResult, nil
}
// GenerateToAddressAsync 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 GenerateToAddress for the blocking version and more details.
func (c *Client) GenerateToAddressAsync(numBlocks int64, address btcutil.Address, maxTries *int64) FutureGenerateToAddressResult {
cmd := btcjson.NewGenerateToAddressCmd(numBlocks, address.EncodeAddress(), maxTries)
return c.sendCmd(cmd)
}
// GenerateToAddress generates numBlocks blocks to the given address and returns their hashes.
func (c *Client) GenerateToAddress(numBlocks int64, address btcutil.Address, maxTries *int64) ([]*chainhash.Hash, error) {
return c.GenerateToAddressAsync(numBlocks, address, maxTries).Receive()
}
// FutureGetGenerateResult is a future promise to deliver the result of a
// GetGenerateAsync RPC invocation (or an applicable error).
type FutureGetGenerateResult chan *response

View File

@@ -95,7 +95,7 @@ type NotificationHandlers struct {
// NotifyBlocks has been made to register for the notification and the
// function is non-nil.
//
// NOTE: Deprecated. Use OnFilteredBlockConnected instead.
// Deprecated: Use OnFilteredBlockConnected instead.
OnBlockConnected func(hash *chainhash.Hash, height int32, t time.Time)
// OnFilteredBlockConnected is invoked when a block is connected to the
@@ -111,7 +111,7 @@ type NotificationHandlers struct {
// NotifyBlocks has been made to register for the notification and the
// function is non-nil.
//
// NOTE: Deprecated. Use OnFilteredBlockDisconnected instead.
// Deprecated: Use OnFilteredBlockDisconnected instead.
OnBlockDisconnected func(hash *chainhash.Hash, height int32, t time.Time)
// OnFilteredBlockDisconnected is invoked when a block is disconnected
@@ -127,7 +127,7 @@ type NotificationHandlers struct {
// preceding call to NotifyReceived, Rescan, or RescanEndHeight has been
// made to register for the notification and the function is non-nil.
//
// NOTE: Deprecated. Use OnRelevantTxAccepted instead.
// Deprecated: Use OnRelevantTxAccepted instead.
OnRecvTx func(transaction *btcutil.Tx, details *btcjson.BlockDetails)
// OnRedeemingTx is invoked when a transaction that spends a registered
@@ -141,7 +141,7 @@ type NotificationHandlers struct {
// funds to the registered addresses. This means it is possible for
// this to invoked indirectly as the result of a NotifyReceived call.
//
// NOTE: Deprecated. Use OnRelevantTxAccepted instead.
// Deprecated: Use OnRelevantTxAccepted instead.
OnRedeemingTx func(transaction *btcutil.Tx, details *btcjson.BlockDetails)
// OnRelevantTxAccepted is invoked when an unmined transaction passes
@@ -157,14 +157,14 @@ type NotificationHandlers struct {
// result of a rescan request, due to how btcd may send various rescan
// notifications after the rescan request has already returned.
//
// NOTE: Deprecated. Not used with RescanBlocks.
// Deprecated: Not used with RescanBlocks.
OnRescanFinished func(hash *chainhash.Hash, height int32, blkTime time.Time)
// OnRescanProgress is invoked periodically when a rescan is underway.
// It will only be invoked if a preceding call to Rescan or
// RescanEndHeight has been made and the function is non-nil.
//
// NOTE: Deprecated. Not used with RescanBlocks.
// Deprecated: Not used with RescanBlocks.
OnRescanProgress func(hash *chainhash.Hash, height int32, blkTime time.Time)
// OnTxAccepted is invoked when a transaction is accepted into the
@@ -905,7 +905,7 @@ func (c *Client) NotifyBlocks() error {
// FutureNotifySpentResult is a future promise to deliver the result of a
// NotifySpentAsync RPC invocation (or an applicable error).
//
// NOTE: Deprecated. Use FutureLoadTxFilterResult instead.
// Deprecated: Use FutureLoadTxFilterResult instead.
type FutureNotifySpentResult chan *response
// Receive waits for the response promised by the future and returns an error
@@ -951,7 +951,7 @@ func newOutPointFromWire(op *wire.OutPoint) btcjson.OutPoint {
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilterAsync instead.
// Deprecated: Use LoadTxFilterAsync instead.
func (c *Client) NotifySpentAsync(outpoints []*wire.OutPoint) FutureNotifySpentResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
@@ -983,7 +983,7 @@ func (c *Client) NotifySpentAsync(outpoints []*wire.OutPoint) FutureNotifySpentR
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilter instead.
// Deprecated: Use LoadTxFilter instead.
func (c *Client) NotifySpent(outpoints []*wire.OutPoint) error {
return c.NotifySpentAsync(outpoints).Receive()
}
@@ -1040,7 +1040,7 @@ func (c *Client) NotifyNewTransactions(verbose bool) error {
// FutureNotifyReceivedResult is a future promise to deliver the result of a
// NotifyReceivedAsync RPC invocation (or an applicable error).
//
// NOTE: Deprecated. Use FutureLoadTxFilterResult instead.
// Deprecated: Use FutureLoadTxFilterResult instead.
type FutureNotifyReceivedResult chan *response
// Receive waits for the response promised by the future and returns an error
@@ -1078,7 +1078,7 @@ func (c *Client) notifyReceivedInternal(addresses []string) FutureNotifyReceived
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilterAsync instead.
// Deprecated: Use LoadTxFilterAsync instead.
func (c *Client) NotifyReceivedAsync(addresses []btcutil.Address) FutureNotifyReceivedResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
@@ -1118,7 +1118,7 @@ func (c *Client) NotifyReceivedAsync(addresses []btcutil.Address) FutureNotifyRe
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use LoadTxFilter instead.
// Deprecated: Use LoadTxFilter instead.
func (c *Client) NotifyReceived(addresses []btcutil.Address) error {
return c.NotifyReceivedAsync(addresses).Receive()
}
@@ -1126,7 +1126,7 @@ func (c *Client) NotifyReceived(addresses []btcutil.Address) error {
// FutureRescanResult is a future promise to deliver the result of a RescanAsync
// or RescanEndHeightAsync RPC invocation (or an applicable error).
//
// NOTE: Deprecated. Use FutureRescanBlocksResult instead.
// Deprecated: Use FutureRescanBlocksResult instead.
type FutureRescanResult chan *response
// Receive waits for the response promised by the future and returns an error
@@ -1150,7 +1150,7 @@ func (r FutureRescanResult) Receive() error {
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use RescanBlocksAsync instead.
// Deprecated: Use RescanBlocksAsync instead.
func (c *Client) RescanAsync(startBlock *chainhash.Hash,
addresses []btcutil.Address,
outpoints []*wire.OutPoint) FutureRescanResult {
@@ -1215,7 +1215,7 @@ func (c *Client) RescanAsync(startBlock *chainhash.Hash,
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use RescanBlocks instead.
// Deprecated: Use RescanBlocks instead.
func (c *Client) Rescan(startBlock *chainhash.Hash,
addresses []btcutil.Address,
outpoints []*wire.OutPoint) error {
@@ -1231,7 +1231,7 @@ func (c *Client) Rescan(startBlock *chainhash.Hash,
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use RescanBlocksAsync instead.
// Deprecated: Use RescanBlocksAsync instead.
func (c *Client) RescanEndBlockAsync(startBlock *chainhash.Hash,
addresses []btcutil.Address, outpoints []*wire.OutPoint,
endBlock *chainhash.Hash) FutureRescanResult {
@@ -1293,7 +1293,7 @@ func (c *Client) RescanEndBlockAsync(startBlock *chainhash.Hash,
//
// NOTE: This is a btcd extension and requires a websocket connection.
//
// NOTE: Deprecated. Use RescanBlocks instead.
// Deprecated: Use RescanBlocks instead.
func (c *Client) RescanEndHeight(startBlock *chainhash.Hash,
addresses []btcutil.Address, outpoints []*wire.OutPoint,
endBlock *chainhash.Hash) error {

View File

@@ -205,6 +205,47 @@ func (c *Client) DecodeRawTransaction(serializedTx []byte) (*btcjson.TxRawResult
return c.DecodeRawTransactionAsync(serializedTx).Receive()
}
// FutureFundRawTransactionResult is a future promise to deliver the result
// of a FutureFundRawTransactionAsync RPC invocation (or an applicable error).
type FutureFundRawTransactionResult chan *response
// Receive waits for the response promised by the future and returns information
// about a funding attempt
func (r FutureFundRawTransactionResult) Receive() (*btcjson.FundRawTransactionResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
var marshalled btcjson.FundRawTransactionResult
if err := json.Unmarshal(res, &marshalled); err != nil {
return nil, err
}
return &marshalled, nil
}
// FundRawTransactionAsync 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 FundRawTransaction for the blocking version and more details.
func (c *Client) FundRawTransactionAsync(tx *wire.MsgTx, opts btcjson.FundRawTransactionOpts, isWitness *bool) FutureFundRawTransactionResult {
var txBuf bytes.Buffer
if err := tx.Serialize(&txBuf); err != nil {
return newFutureError(err)
}
cmd := btcjson.NewFundRawTransactionCmd(txBuf.Bytes(), opts, isWitness)
return c.sendCmd(cmd)
}
// FundRawTransaction returns the result of trying to fund the given transaction with
// funds from the node wallet
func (c *Client) FundRawTransaction(tx *wire.MsgTx, opts btcjson.FundRawTransactionOpts, isWitness *bool) (*btcjson.FundRawTransactionResult, error) {
return c.FundRawTransactionAsync(tx, opts, isWitness).Receive()
}
// FutureCreateRawTransactionResult is a future promise to deliver the result
// of a CreateRawTransactionAsync RPC invocation (or an applicable error).
type FutureCreateRawTransactionResult chan *response
@@ -233,8 +274,13 @@ func (r FutureCreateRawTransactionResult) Receive() (*wire.MsgTx, error) {
// Deserialize the transaction and return it.
var msgTx wire.MsgTx
if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil {
return nil, err
// we try both the new and old encoding format
witnessErr := msgTx.Deserialize(bytes.NewReader(serializedTx))
if witnessErr != nil {
legacyErr := msgTx.DeserializeNoWitness(bytes.NewReader(serializedTx))
if legacyErr != nil {
return nil, legacyErr
}
}
return &msgTx, nil
}
@@ -256,7 +302,8 @@ func (c *Client) CreateRawTransactionAsync(inputs []btcjson.TransactionInput,
}
// CreateRawTransaction returns a new transaction spending the provided inputs
// and sending to the provided addresses.
// and sending to the provided addresses. If the inputs are either nil or an
// empty slice, it is interpreted as an empty slice.
func (c *Client) CreateRawTransaction(inputs []btcjson.TransactionInput,
amounts map[btcutil.Address]btcutil.Amount, lockTime *int64) (*wire.MsgTx, error) {

View File

@@ -20,7 +20,8 @@ import (
// *****************************
// FutureGetTransactionResult is a future promise to deliver the result
// of a GetTransactionAsync RPC invocation (or an applicable error).
// of a GetTransactionAsync or GetTransactionWatchOnlyAsync RPC invocation
// (or an applicable error).
type FutureGetTransactionResult chan *response
// Receive waits for the response promised by the future and returns detailed
@@ -63,6 +64,28 @@ func (c *Client) GetTransaction(txHash *chainhash.Hash) (*btcjson.GetTransaction
return c.GetTransactionAsync(txHash).Receive()
}
// GetTransactionWatchOnlyAsync 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 GetTransactionWatchOnly for the blocking version and more details.
func (c *Client) GetTransactionWatchOnlyAsync(txHash *chainhash.Hash, watchOnly bool) FutureGetTransactionResult {
hash := ""
if txHash != nil {
hash = txHash.String()
}
cmd := btcjson.NewGetTransactionCmd(hash, &watchOnly)
return c.sendCmd(cmd)
}
// GetTransactionWatchOnly returns detailed information about a wallet
// transaction, and allow including watch-only addresses in balance
// calculation and details.
func (c *Client) GetTransactionWatchOnly(txHash *chainhash.Hash, watchOnly bool) (*btcjson.GetTransactionResult, error) {
return c.GetTransactionWatchOnlyAsync(txHash, watchOnly).Receive()
}
// FutureListTransactionsResult is a future promise to deliver the result of a
// ListTransactionsAsync, ListTransactionsCountAsync, or
// ListTransactionsCountFromAsync RPC invocation (or an applicable error).
@@ -753,13 +776,16 @@ func (c *Client) SendManyComment(fromAccount string,
// FutureAddMultisigAddressResult is a future promise to deliver the result of a
// AddMultisigAddressAsync RPC invocation (or an applicable error).
type FutureAddMultisigAddressResult chan *response
type FutureAddMultisigAddressResult struct {
responseChannel chan *response
network *chaincfg.Params
}
// Receive waits for the response promised by the future and returns the
// multisignature address that requires the specified number of signatures for
// the provided addresses.
func (r FutureAddMultisigAddressResult) Receive() (btcutil.Address, error) {
res, err := receiveFuture(r)
res, err := receiveFuture(r.responseChannel)
if err != nil {
return nil, err
}
@@ -771,7 +797,7 @@ func (r FutureAddMultisigAddressResult) Receive() (btcutil.Address, error) {
return nil, err
}
return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams)
return btcutil.DecodeAddress(addr, r.network)
}
// AddMultisigAddressAsync returns an instance of a type that can be used to get
@@ -786,14 +812,17 @@ func (c *Client) AddMultisigAddressAsync(requiredSigs int, addresses []btcutil.A
}
cmd := btcjson.NewAddMultisigAddressCmd(requiredSigs, addrs, &account)
return c.sendCmd(cmd)
result := FutureAddMultisigAddressResult{
network: c.chainParams,
responseChannel: c.sendCmd(cmd),
}
return result
}
// AddMultisigAddress adds a multisignature address that requires the specified
// number of signatures for the provided addresses to the wallet.
func (c *Client) AddMultisigAddress(requiredSigs int, addresses []btcutil.Address, account string) (btcutil.Address, error) {
return c.AddMultisigAddressAsync(requiredSigs, addresses,
account).Receive()
return c.AddMultisigAddressAsync(requiredSigs, addresses, account).Receive()
}
// FutureCreateMultisigResult is a future promise to deliver the result of a
@@ -868,12 +897,15 @@ func (c *Client) CreateNewAccount(account string) error {
// FutureGetNewAddressResult is a future promise to deliver the result of a
// GetNewAddressAsync RPC invocation (or an applicable error).
type FutureGetNewAddressResult chan *response
type FutureGetNewAddressResult struct {
responseChannel chan *response
network *chaincfg.Params
}
// Receive waits for the response promised by the future and returns a new
// address.
func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) {
res, err := receiveFuture(r)
res, err := receiveFuture(r.responseChannel)
if err != nil {
return nil, err
}
@@ -885,7 +917,7 @@ func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) {
return nil, err
}
return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams)
return btcutil.DecodeAddress(addr, r.network)
}
// GetNewAddressAsync returns an instance of a type that can be used to get the
@@ -895,23 +927,31 @@ func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) {
// See GetNewAddress for the blocking version and more details.
func (c *Client) GetNewAddressAsync(account string) FutureGetNewAddressResult {
cmd := btcjson.NewGetNewAddressCmd(&account)
return c.sendCmd(cmd)
result := FutureGetNewAddressResult{
network: c.chainParams,
responseChannel: c.sendCmd(cmd),
}
return result
}
// GetNewAddress returns a new address.
// GetNewAddress returns a new address, and decodes based on the client's
// chain params.
func (c *Client) GetNewAddress(account string) (btcutil.Address, error) {
return c.GetNewAddressAsync(account).Receive()
}
// FutureGetRawChangeAddressResult is a future promise to deliver the result of
// a GetRawChangeAddressAsync RPC invocation (or an applicable error).
type FutureGetRawChangeAddressResult chan *response
type FutureGetRawChangeAddressResult struct {
responseChannel chan *response
network *chaincfg.Params
}
// Receive waits for the response promised by the future and returns a new
// address for receiving change that will be associated with the provided
// account. Note that this is only for raw transactions and NOT for normal use.
func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) {
res, err := receiveFuture(r)
res, err := receiveFuture(r.responseChannel)
if err != nil {
return nil, err
}
@@ -923,7 +963,7 @@ func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) {
return nil, err
}
return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams)
return btcutil.DecodeAddress(addr, r.network)
}
// GetRawChangeAddressAsync returns an instance of a type that can be used to
@@ -933,7 +973,11 @@ func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) {
// See GetRawChangeAddress for the blocking version and more details.
func (c *Client) GetRawChangeAddressAsync(account string) FutureGetRawChangeAddressResult {
cmd := btcjson.NewGetRawChangeAddressCmd(&account)
return c.sendCmd(cmd)
result := FutureGetRawChangeAddressResult{
network: c.chainParams,
responseChannel: c.sendCmd(cmd),
}
return result
}
// GetRawChangeAddress returns a new address for receiving change that will be
@@ -945,12 +989,15 @@ func (c *Client) GetRawChangeAddress(account string) (btcutil.Address, error) {
// FutureAddWitnessAddressResult is a future promise to deliver the result of
// a AddWitnessAddressAsync RPC invocation (or an applicable error).
type FutureAddWitnessAddressResult chan *response
type FutureAddWitnessAddressResult struct {
responseChannel chan *response
network *chaincfg.Params
}
// Receive waits for the response promised by the future and returns the new
// address.
func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) {
res, err := receiveFuture(r)
res, err := receiveFuture(r.responseChannel)
if err != nil {
return nil, err
}
@@ -962,7 +1009,7 @@ func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) {
return nil, err
}
return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams)
return btcutil.DecodeAddress(addr, r.network)
}
// AddWitnessAddressAsync returns an instance of a type that can be used to get
@@ -972,7 +1019,11 @@ func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) {
// See AddWitnessAddress for the blocking version and more details.
func (c *Client) AddWitnessAddressAsync(address string) FutureAddWitnessAddressResult {
cmd := btcjson.NewAddWitnessAddressCmd(address)
return c.sendCmd(cmd)
response := FutureAddWitnessAddressResult{
network: c.chainParams,
responseChannel: c.sendCmd(cmd),
}
return response
}
// AddWitnessAddress adds a witness address for a script and returns the new
@@ -983,12 +1034,15 @@ func (c *Client) AddWitnessAddress(address string) (btcutil.Address, error) {
// FutureGetAccountAddressResult is a future promise to deliver the result of a
// GetAccountAddressAsync RPC invocation (or an applicable error).
type FutureGetAccountAddressResult chan *response
type FutureGetAccountAddressResult struct {
responseChannel chan *response
network *chaincfg.Params
}
// Receive waits for the response promised by the future and returns the current
// Bitcoin address for receiving payments to the specified account.
func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) {
res, err := receiveFuture(r)
res, err := receiveFuture(r.responseChannel)
if err != nil {
return nil, err
}
@@ -1000,7 +1054,7 @@ func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) {
return nil, err
}
return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams)
return btcutil.DecodeAddress(addr, r.network)
}
// GetAccountAddressAsync returns an instance of a type that can be used to get
@@ -1010,7 +1064,11 @@ func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) {
// See GetAccountAddress for the blocking version and more details.
func (c *Client) GetAccountAddressAsync(account string) FutureGetAccountAddressResult {
cmd := btcjson.NewGetAccountAddressCmd(account)
return c.sendCmd(cmd)
result := FutureGetAccountAddressResult{
network: c.chainParams,
responseChannel: c.sendCmd(cmd),
}
return result
}
// GetAccountAddress returns the current Bitcoin address for receiving payments
@@ -1086,12 +1144,15 @@ func (c *Client) SetAccount(address btcutil.Address, account string) error {
// FutureGetAddressesByAccountResult is a future promise to deliver the result
// of a GetAddressesByAccountAsync RPC invocation (or an applicable error).
type FutureGetAddressesByAccountResult chan *response
type FutureGetAddressesByAccountResult struct {
responseChannel chan *response
network *chaincfg.Params
}
// Receive waits for the response promised by the future and returns the list of
// addresses associated with the passed account.
func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error) {
res, err := receiveFuture(r)
res, err := receiveFuture(r.responseChannel)
if err != nil {
return nil, err
}
@@ -1103,17 +1164,15 @@ func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error)
return nil, err
}
addrs := make([]btcutil.Address, 0, len(addrStrings))
for _, addrStr := range addrStrings {
addr, err := btcutil.DecodeAddress(addrStr,
&chaincfg.MainNetParams)
addresses := make([]btcutil.Address, len(addrStrings))
for i, addrString := range addrStrings {
addresses[i], err = btcutil.DecodeAddress(addrString, r.network)
if err != nil {
return nil, err
}
addrs = append(addrs, addr)
}
return addrs, nil
return addresses, nil
}
// GetAddressesByAccountAsync returns an instance of a type that can be used to
@@ -1123,7 +1182,11 @@ func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error)
// See GetAddressesByAccount for the blocking version and more details.
func (c *Client) GetAddressesByAccountAsync(account string) FutureGetAddressesByAccountResult {
cmd := btcjson.NewGetAddressesByAccountCmd(account)
return c.sendCmd(cmd)
result := FutureGetAddressesByAccountResult{
network: c.chainParams,
responseChannel: c.sendCmd(cmd),
}
return result
}
// GetAddressesByAccount returns the list of addresses associated with the
@@ -1507,6 +1570,43 @@ func (c *Client) GetBalanceMinConf(account string, minConfirms int) (btcutil.Amo
return c.GetBalanceMinConfAsync(account, minConfirms).Receive()
}
// FutureGetBalancesResult is a future promise to deliver the result of a
// GetBalancesAsync RPC invocation (or an applicable error).
type FutureGetBalancesResult chan *response
// Receive waits for the response promised by the future and returns the
// available balances from the server.
func (r FutureGetBalancesResult) Receive() (*btcjson.GetBalancesResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a floating point number.
var balances btcjson.GetBalancesResult
err = json.Unmarshal(res, &balances)
if err != nil {
return nil, err
}
return &balances, nil
}
// GetBalancesAsync 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 GetBalances for the blocking version and more details.
func (c *Client) GetBalancesAsync() FutureGetBalancesResult {
cmd := btcjson.NewGetBalancesCmd()
return c.sendCmd(cmd)
}
// GetBalances returns the available balances from the server.
func (c *Client) GetBalances() (*btcjson.GetBalancesResult, error) {
return c.GetBalancesAsync().Receive()
}
// FutureGetReceivedByAccountResult is a future promise to deliver the result of
// a GetReceivedByAccountAsync or GetReceivedByAccountMinConfAsync RPC
// invocation (or an applicable error).