mirror of
https://github.com/muun/recovery.git
synced 2025-11-10 14:09:50 -05:00
Release v0.3.0
This commit is contained in:
13
vendor/github.com/btcsuite/btcd/blockchain/chainio.go
generated
vendored
13
vendor/github.com/btcsuite/btcd/blockchain/chainio.go
generated
vendored
@@ -1149,18 +1149,9 @@ func (b *BlockChain) initChainState() error {
|
||||
|
||||
blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName)
|
||||
|
||||
// Determine how many blocks will be loaded into the index so we can
|
||||
// allocate the right amount.
|
||||
var blockCount int32
|
||||
cursor := blockIndexBucket.Cursor()
|
||||
for ok := cursor.First(); ok; ok = cursor.Next() {
|
||||
blockCount++
|
||||
}
|
||||
blockNodes := make([]blockNode, blockCount)
|
||||
|
||||
var i int32
|
||||
var lastNode *blockNode
|
||||
cursor = blockIndexBucket.Cursor()
|
||||
cursor := blockIndexBucket.Cursor()
|
||||
for ok := cursor.First(); ok; ok = cursor.Next() {
|
||||
header, status, err := deserializeBlockRow(cursor.Value())
|
||||
if err != nil {
|
||||
@@ -1193,7 +1184,7 @@ func (b *BlockChain) initChainState() error {
|
||||
|
||||
// Initialize the block node for the block, connect it,
|
||||
// and add it to the block index.
|
||||
node := &blockNodes[i]
|
||||
node := new(blockNode)
|
||||
initBlockNode(node, header, parent)
|
||||
node.status = status
|
||||
b.index.addNode(node)
|
||||
|
||||
16
vendor/github.com/btcsuite/btcd/blockchain/utxoviewpoint.go
generated
vendored
16
vendor/github.com/btcsuite/btcd/blockchain/utxoviewpoint.go
generated
vendored
@@ -111,6 +111,22 @@ func (entry *UtxoEntry) Clone() *UtxoEntry {
|
||||
}
|
||||
}
|
||||
|
||||
// NewUtxoEntry returns a new UtxoEntry built from the arguments.
|
||||
func NewUtxoEntry(
|
||||
txOut *wire.TxOut, blockHeight int32, isCoinbase bool) *UtxoEntry {
|
||||
var cbFlag txoFlags
|
||||
if isCoinbase {
|
||||
cbFlag |= tfCoinBase
|
||||
}
|
||||
|
||||
return &UtxoEntry{
|
||||
amount: txOut.Value,
|
||||
pkScript: txOut.PkScript,
|
||||
blockHeight: blockHeight,
|
||||
packedFlags: cbFlag,
|
||||
}
|
||||
}
|
||||
|
||||
// UtxoViewpoint represents a view into the set of unspent transaction outputs
|
||||
// from a specific point of view in the chain. For example, it could be for
|
||||
// the end of the main chain, some point in the history of the main chain, or
|
||||
|
||||
20
vendor/github.com/btcsuite/btcd/btcec/field.go
generated
vendored
20
vendor/github.com/btcsuite/btcd/btcec/field.go
generated
vendored
@@ -226,20 +226,24 @@ func (f *fieldVal) SetBytes(b *[32]byte) *fieldVal {
|
||||
return f
|
||||
}
|
||||
|
||||
// SetByteSlice packs the passed big-endian value into the internal field value
|
||||
// representation. Only the first 32-bytes are used. As a result, it is up to
|
||||
// the caller to ensure numbers of the appropriate size are used or the value
|
||||
// will be truncated.
|
||||
// SetByteSlice interprets the provided slice as a 256-bit big-endian unsigned
|
||||
// integer (meaning it is truncated to the first 32 bytes), packs it into the
|
||||
// internal field value representation, and returns the updated field value.
|
||||
//
|
||||
// Note that since passing a slice with more than 32 bytes is truncated, it is
|
||||
// possible that the truncated value is less than the field prime. It is up to
|
||||
// the caller to decide whether it needs to provide numbers of the appropriate
|
||||
// size or if it is acceptable to use this function with the described
|
||||
// truncation behavior.
|
||||
//
|
||||
// The field value is returned to support chaining. This enables syntax like:
|
||||
// f := new(fieldVal).SetByteSlice(byteSlice)
|
||||
func (f *fieldVal) SetByteSlice(b []byte) *fieldVal {
|
||||
var b32 [32]byte
|
||||
for i := 0; i < len(b); i++ {
|
||||
if i < 32 {
|
||||
b32[i+(32-len(b))] = b[i]
|
||||
}
|
||||
if len(b) > 32 {
|
||||
b = b[:32]
|
||||
}
|
||||
copy(b32[32-len(b):], b)
|
||||
return f.SetBytes(&b32)
|
||||
}
|
||||
|
||||
|
||||
18
vendor/github.com/btcsuite/btcd/btcjson/btcdextcmds.go
generated
vendored
18
vendor/github.com/btcsuite/btcd/btcjson/btcdextcmds.go
generated
vendored
@@ -59,6 +59,23 @@ func NewDebugLevelCmd(levelSpec string) *DebugLevelCmd {
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateToAddressCmd defines the generatetoaddress JSON-RPC command.
|
||||
type GenerateToAddressCmd struct {
|
||||
NumBlocks int64
|
||||
Address string
|
||||
MaxTries *int64 `jsonrpcdefault:"1000000"`
|
||||
}
|
||||
|
||||
// NewGenerateToAddressCmd returns a new instance which can be used to issue a
|
||||
// generatetoaddress JSON-RPC command.
|
||||
func NewGenerateToAddressCmd(numBlocks int64, address string, maxTries *int64) *GenerateToAddressCmd {
|
||||
return &GenerateToAddressCmd{
|
||||
NumBlocks: numBlocks,
|
||||
Address: address,
|
||||
MaxTries: maxTries,
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateCmd defines the generate JSON-RPC command.
|
||||
type GenerateCmd struct {
|
||||
NumBlocks uint32
|
||||
@@ -131,6 +148,7 @@ func init() {
|
||||
MustRegisterCmd("debuglevel", (*DebugLevelCmd)(nil), flags)
|
||||
MustRegisterCmd("node", (*NodeCmd)(nil), flags)
|
||||
MustRegisterCmd("generate", (*GenerateCmd)(nil), flags)
|
||||
MustRegisterCmd("generatetoaddress", (*GenerateToAddressCmd)(nil), flags)
|
||||
MustRegisterCmd("getbestblock", (*GetBestBlockCmd)(nil), flags)
|
||||
MustRegisterCmd("getcurrentnet", (*GetCurrentNetCmd)(nil), flags)
|
||||
MustRegisterCmd("getheaders", (*GetHeadersCmd)(nil), flags)
|
||||
|
||||
114
vendor/github.com/btcsuite/btcd/btcjson/chainsvrcmds.go
generated
vendored
114
vendor/github.com/btcsuite/btcd/btcjson/chainsvrcmds.go
generated
vendored
@@ -8,6 +8,7 @@
|
||||
package btcjson
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
@@ -63,10 +64,15 @@ type CreateRawTransactionCmd struct {
|
||||
// NewCreateRawTransactionCmd returns a new instance which can be used to issue
|
||||
// a createrawtransaction JSON-RPC command.
|
||||
//
|
||||
// Amounts are in BTC.
|
||||
// Amounts are in BTC. Passing in nil and the empty slice as inputs is equivalent,
|
||||
// both gets interpreted as the empty slice.
|
||||
func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]float64,
|
||||
lockTime *int64) *CreateRawTransactionCmd {
|
||||
|
||||
// to make sure we're serializing this to the empty list and not null, we
|
||||
// explicitly initialize the list
|
||||
if inputs == nil {
|
||||
inputs = []TransactionInput{}
|
||||
}
|
||||
return &CreateRawTransactionCmd{
|
||||
Inputs: inputs,
|
||||
Amounts: amounts,
|
||||
@@ -74,6 +80,37 @@ func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]fl
|
||||
}
|
||||
}
|
||||
|
||||
// FundRawTransactionOpts are the different options that can be passed to rawtransaction
|
||||
type FundRawTransactionOpts struct {
|
||||
ChangeAddress *string `json:"changeAddress,omitempty"`
|
||||
ChangePosition *int `json:"changePosition,omitempty"`
|
||||
ChangeType *string `json:"change_type,omitempty"`
|
||||
IncludeWatching *bool `json:"includeWatching,omitempty"`
|
||||
LockUnspents *bool `json:"lockUnspents,omitempty"`
|
||||
FeeRate *float64 `json:"feeRate,omitempty"` // BTC/kB
|
||||
SubtractFeeFromOutputs []int `json:"subtractFeeFromOutputs,omitempty"`
|
||||
Replaceable *bool `json:"replaceable,omitempty"`
|
||||
ConfTarget *int `json:"conf_target,omitempty"`
|
||||
EstimateMode *EstimateSmartFeeMode `json:"estimate_mode,omitempty"`
|
||||
}
|
||||
|
||||
// FundRawTransactionCmd defines the fundrawtransaction JSON-RPC command
|
||||
type FundRawTransactionCmd struct {
|
||||
HexTx string
|
||||
Options FundRawTransactionOpts
|
||||
IsWitness *bool
|
||||
}
|
||||
|
||||
// NewFundRawTransactionCmd returns a new instance which can be used to issue
|
||||
// a fundrawtransaction JSON-RPC command
|
||||
func NewFundRawTransactionCmd(serializedTx []byte, opts FundRawTransactionOpts, isWitness *bool) *FundRawTransactionCmd {
|
||||
return &FundRawTransactionCmd{
|
||||
HexTx: hex.EncodeToString(serializedTx),
|
||||
Options: opts,
|
||||
IsWitness: isWitness,
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeRawTransactionCmd defines the decoderawtransaction JSON-RPC command.
|
||||
type DecodeRawTransactionCmd struct {
|
||||
HexTx string
|
||||
@@ -130,8 +167,7 @@ func NewGetBestBlockHashCmd() *GetBestBlockHashCmd {
|
||||
// GetBlockCmd defines the getblock JSON-RPC command.
|
||||
type GetBlockCmd struct {
|
||||
Hash string
|
||||
Verbose *bool `jsonrpcdefault:"true"`
|
||||
VerboseTx *bool `jsonrpcdefault:"false"`
|
||||
Verbosity *int `jsonrpcdefault:"1"`
|
||||
}
|
||||
|
||||
// NewGetBlockCmd returns a new instance which can be used to issue a getblock
|
||||
@@ -139,11 +175,10 @@ type GetBlockCmd struct {
|
||||
//
|
||||
// The parameters which are pointers indicate they are optional. Passing nil
|
||||
// for optional parameters will use the default value.
|
||||
func NewGetBlockCmd(hash string, verbose, verboseTx *bool) *GetBlockCmd {
|
||||
func NewGetBlockCmd(hash string, verbosity *int) *GetBlockCmd {
|
||||
return &GetBlockCmd{
|
||||
Hash: hash,
|
||||
Verbose: verbose,
|
||||
VerboseTx: verboseTx,
|
||||
Verbosity: verbosity,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +228,50 @@ func NewGetBlockHeaderCmd(hash string, verbose *bool) *GetBlockHeaderCmd {
|
||||
}
|
||||
}
|
||||
|
||||
// HashOrHeight defines a type that can be used as hash_or_height value in JSON-RPC commands.
|
||||
type HashOrHeight struct {
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface
|
||||
func (h HashOrHeight) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(h.Value)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface
|
||||
func (h *HashOrHeight) UnmarshalJSON(data []byte) error {
|
||||
var unmarshalled interface{}
|
||||
if err := json.Unmarshal(data, &unmarshalled); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v := unmarshalled.(type) {
|
||||
case float64:
|
||||
h.Value = int(v)
|
||||
case string:
|
||||
h.Value = v
|
||||
default:
|
||||
return fmt.Errorf("invalid hash_or_height value: %v", unmarshalled)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBlockStatsCmd defines the getblockstats JSON-RPC command.
|
||||
type GetBlockStatsCmd struct {
|
||||
HashOrHeight HashOrHeight
|
||||
Stats *[]string
|
||||
}
|
||||
|
||||
// NewGetBlockStatsCmd returns a new instance which can be used to issue a
|
||||
// getblockstats JSON-RPC command. Either height or hash must be specified.
|
||||
func NewGetBlockStatsCmd(hashOrHeight HashOrHeight, stats *[]string) *GetBlockStatsCmd {
|
||||
return &GetBlockStatsCmd{
|
||||
HashOrHeight: hashOrHeight,
|
||||
Stats: stats,
|
||||
}
|
||||
}
|
||||
|
||||
// TemplateRequest is a request object as defined in BIP22
|
||||
// (https://en.bitcoin.it/wiki/BIP_0022), it is optionally provided as an
|
||||
// pointer argument to GetBlockTemplateCmd.
|
||||
@@ -321,6 +400,24 @@ func NewGetChainTipsCmd() *GetChainTipsCmd {
|
||||
return &GetChainTipsCmd{}
|
||||
}
|
||||
|
||||
// GetChainTxStatsCmd defines the getchaintxstats JSON-RPC command.
|
||||
type GetChainTxStatsCmd struct {
|
||||
NBlocks *int32
|
||||
BlockHash *string
|
||||
}
|
||||
|
||||
// NewGetChainTxStatsCmd returns a new instance which can be used to issue a
|
||||
// getchaintxstats JSON-RPC command.
|
||||
//
|
||||
// The parameters which are pointers indicate they are optional. Passing nil
|
||||
// for optional parameters will use the default value.
|
||||
func NewGetChainTxStatsCmd(nBlocks *int32, blockHash *string) *GetChainTxStatsCmd {
|
||||
return &GetChainTxStatsCmd{
|
||||
NBlocks: nBlocks,
|
||||
BlockHash: blockHash,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConnectionCountCmd defines the getconnectioncount JSON-RPC command.
|
||||
type GetConnectionCountCmd struct{}
|
||||
|
||||
@@ -791,6 +888,7 @@ func init() {
|
||||
|
||||
MustRegisterCmd("addnode", (*AddNodeCmd)(nil), flags)
|
||||
MustRegisterCmd("createrawtransaction", (*CreateRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("fundrawtransaction", (*FundRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("decoderawtransaction", (*DecodeRawTransactionCmd)(nil), flags)
|
||||
MustRegisterCmd("decodescript", (*DecodeScriptCmd)(nil), flags)
|
||||
MustRegisterCmd("getaddednodeinfo", (*GetAddedNodeInfoCmd)(nil), flags)
|
||||
@@ -800,10 +898,12 @@ func init() {
|
||||
MustRegisterCmd("getblockcount", (*GetBlockCountCmd)(nil), flags)
|
||||
MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags)
|
||||
MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags)
|
||||
MustRegisterCmd("getblockstats", (*GetBlockStatsCmd)(nil), flags)
|
||||
MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags)
|
||||
MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags)
|
||||
MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags)
|
||||
MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags)
|
||||
MustRegisterCmd("getchaintxstats", (*GetChainTxStatsCmd)(nil), flags)
|
||||
MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags)
|
||||
MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags)
|
||||
MustRegisterCmd("getgenerate", (*GetGenerateCmd)(nil), flags)
|
||||
|
||||
182
vendor/github.com/btcsuite/btcd/btcjson/chainsvrresults.go
generated
vendored
182
vendor/github.com/btcsuite/btcd/btcjson/chainsvrresults.go
generated
vendored
@@ -4,7 +4,14 @@
|
||||
|
||||
package btcjson
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// GetBlockHeaderVerboseResult models the data from the getblockheader command when
|
||||
// the verbose flag is set. When the verbose flag is not set, getblockheader
|
||||
@@ -24,9 +31,44 @@ type GetBlockHeaderVerboseResult struct {
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
}
|
||||
|
||||
// GetBlockStatsResult models the data from the getblockstats command.
|
||||
type GetBlockStatsResult struct {
|
||||
AverageFee int64 `json:"avgfee"`
|
||||
AverageFeeRate int64 `json:"avgfeerate"`
|
||||
AverageTxSize int64 `json:"avgtxsize"`
|
||||
FeeratePercentiles []int64 `json:"feerate_percentiles"`
|
||||
Hash string `json:"blockhash"`
|
||||
Height int64 `json:"height"`
|
||||
Ins int64 `json:"ins"`
|
||||
MaxFee int64 `json:"maxfee"`
|
||||
MaxFeeRate int64 `json:"maxfeerate"`
|
||||
MaxTxSize int64 `json:"maxtxsize"`
|
||||
MedianFee int64 `json:"medianfee"`
|
||||
MedianTime int64 `json:"mediantime"`
|
||||
MedianTxSize int64 `json:"mediantxsize"`
|
||||
MinFee int64 `json:"minfee"`
|
||||
MinFeeRate int64 `json:"minfeerate"`
|
||||
MinTxSize int64 `json:"mintxsize"`
|
||||
Outs int64 `json:"outs"`
|
||||
SegWitTotalSize int64 `json:"swtotal_size"`
|
||||
SegWitTotalWeight int64 `json:"swtotal_weight"`
|
||||
SegWitTxs int64 `json:"swtxs"`
|
||||
Subsidy int64 `json:"subsidy"`
|
||||
Time int64 `json:"time"`
|
||||
TotalOut int64 `json:"total_out"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
TotalWeight int64 `json:"total_weight"`
|
||||
Txs int64 `json:"txs"`
|
||||
UTXOIncrease int64 `json:"utxo_increase"`
|
||||
UTXOSizeIncrease int64 `json:"utxo_size_inc"`
|
||||
}
|
||||
|
||||
// GetBlockVerboseResult models the data from the getblock command when the
|
||||
// verbose flag is set. When the verbose flag is not set, getblock returns a
|
||||
// hex-encoded string.
|
||||
// verbose flag is set to 1. When the verbose flag is set to 0, getblock returns a
|
||||
// hex-encoded string. When the verbose flag is set to 1, getblock returns an object
|
||||
// whose tx field is an array of transaction hashes. When the verbose flag is set to 2,
|
||||
// getblock returns an object whose tx field is an array of raw transactions.
|
||||
// Use GetBlockVerboseTxResult to unmarshal data received from passing verbose=2 to getblock.
|
||||
type GetBlockVerboseResult struct {
|
||||
Hash string `json:"hash"`
|
||||
Confirmations int64 `json:"confirmations"`
|
||||
@@ -38,7 +80,7 @@ type GetBlockVerboseResult struct {
|
||||
VersionHex string `json:"versionHex"`
|
||||
MerkleRoot string `json:"merkleroot"`
|
||||
Tx []string `json:"tx,omitempty"`
|
||||
RawTx []TxRawResult `json:"rawtx,omitempty"`
|
||||
RawTx []TxRawResult `json:"rawtx,omitempty"` // Note: this field is always empty when verbose != 2.
|
||||
Time int64 `json:"time"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
Bits string `json:"bits"`
|
||||
@@ -47,6 +89,43 @@ type GetBlockVerboseResult struct {
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
}
|
||||
|
||||
// GetBlockVerboseTxResult models the data from the getblock command when the
|
||||
// verbose flag is set to 2. When the verbose flag is set to 0, getblock returns a
|
||||
// hex-encoded string. When the verbose flag is set to 1, getblock returns an object
|
||||
// whose tx field is an array of transaction hashes. When the verbose flag is set to 2,
|
||||
// getblock returns an object whose tx field is an array of raw transactions.
|
||||
// Use GetBlockVerboseResult to unmarshal data received from passing verbose=1 to getblock.
|
||||
type GetBlockVerboseTxResult struct {
|
||||
Hash string `json:"hash"`
|
||||
Confirmations int64 `json:"confirmations"`
|
||||
StrippedSize int32 `json:"strippedsize"`
|
||||
Size int32 `json:"size"`
|
||||
Weight int32 `json:"weight"`
|
||||
Height int64 `json:"height"`
|
||||
Version int32 `json:"version"`
|
||||
VersionHex string `json:"versionHex"`
|
||||
MerkleRoot string `json:"merkleroot"`
|
||||
Tx []TxRawResult `json:"tx,omitempty"`
|
||||
Time int64 `json:"time"`
|
||||
Nonce uint32 `json:"nonce"`
|
||||
Bits string `json:"bits"`
|
||||
Difficulty float64 `json:"difficulty"`
|
||||
PreviousHash string `json:"previousblockhash"`
|
||||
NextHash string `json:"nextblockhash,omitempty"`
|
||||
}
|
||||
|
||||
// GetChainTxStatsResult models the data from the getchaintxstats command.
|
||||
type GetChainTxStatsResult struct {
|
||||
Time int64 `json:"time"`
|
||||
TxCount int64 `json:"txcount"`
|
||||
WindowFinalBlockHash string `json:"window_final_block_hash"`
|
||||
WindowFinalBlockHeight int32 `json:"window_final_block_height"`
|
||||
WindowBlockCount int32 `json:"window_block_count"`
|
||||
WindowTxCount int32 `json:"window_tx_count"`
|
||||
WindowInterval int32 `json:"window_interval"`
|
||||
TxRate float64 `json:"txrate"`
|
||||
}
|
||||
|
||||
// CreateMultiSigResult models the data returned from the createmultisig
|
||||
// command.
|
||||
type CreateMultiSigResult struct {
|
||||
@@ -206,23 +285,35 @@ type GetBlockTemplateResult struct {
|
||||
RejectReasion string `json:"reject-reason,omitempty"`
|
||||
}
|
||||
|
||||
// GetMempoolEntryResult models the data returned from the getmempoolentry's
|
||||
// fee field
|
||||
|
||||
type MempoolFees struct {
|
||||
Base float64 `json:"base"`
|
||||
Modified float64 `json:"modified"`
|
||||
Ancestor float64 `json:"ancestor"`
|
||||
Descendant float64 `json:"descendant"`
|
||||
}
|
||||
|
||||
// GetMempoolEntryResult models the data returned from the getmempoolentry
|
||||
// command.
|
||||
type GetMempoolEntryResult struct {
|
||||
Size int32 `json:"size"`
|
||||
Fee float64 `json:"fee"`
|
||||
ModifiedFee float64 `json:"modifiedfee"`
|
||||
Time int64 `json:"time"`
|
||||
Height int64 `json:"height"`
|
||||
StartingPriority float64 `json:"startingpriority"`
|
||||
CurrentPriority float64 `json:"currentpriority"`
|
||||
DescendantCount int64 `json:"descendantcount"`
|
||||
DescendantSize int64 `json:"descendantsize"`
|
||||
DescendantFees float64 `json:"descendantfees"`
|
||||
AncestorCount int64 `json:"ancestorcount"`
|
||||
AncestorSize int64 `json:"ancestorsize"`
|
||||
AncestorFees float64 `json:"ancestorfees"`
|
||||
Depends []string `json:"depends"`
|
||||
VSize int32 `json:"vsize"`
|
||||
Size int32 `json:"size"`
|
||||
Weight int64 `json:"weight"`
|
||||
Fee float64 `json:"fee"`
|
||||
ModifiedFee float64 `json:"modifiedfee"`
|
||||
Time int64 `json:"time"`
|
||||
Height int64 `json:"height"`
|
||||
DescendantCount int64 `json:"descendantcount"`
|
||||
DescendantSize int64 `json:"descendantsize"`
|
||||
DescendantFees float64 `json:"descendantfees"`
|
||||
AncestorCount int64 `json:"ancestorcount"`
|
||||
AncestorSize int64 `json:"ancestorsize"`
|
||||
AncestorFees float64 `json:"ancestorfees"`
|
||||
WTxId string `json:"wtxid"`
|
||||
Fees MempoolFees `json:"fees"`
|
||||
Depends []string `json:"depends"`
|
||||
}
|
||||
|
||||
// GetMempoolInfoResult models the data returned from the getmempoolinfo
|
||||
@@ -584,3 +675,58 @@ type ValidateAddressChainResult struct {
|
||||
IsValid bool `json:"isvalid"`
|
||||
Address string `json:"address,omitempty"`
|
||||
}
|
||||
|
||||
// EstimateSmartFeeResult models the data returned buy the chain server
|
||||
// estimatesmartfee command
|
||||
type EstimateSmartFeeResult struct {
|
||||
FeeRate *float64 `json:"feerate,omitempty"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
Blocks int64 `json:"blocks"`
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = &FundRawTransactionResult{}
|
||||
|
||||
type rawFundRawTransactionResult struct {
|
||||
Transaction string `json:"hex"`
|
||||
Fee float64 `json:"fee"`
|
||||
ChangePosition int `json:"changepos"`
|
||||
}
|
||||
|
||||
// FundRawTransactionResult is the result of the fundrawtransaction JSON-RPC call
|
||||
type FundRawTransactionResult struct {
|
||||
Transaction *wire.MsgTx
|
||||
Fee btcutil.Amount
|
||||
ChangePosition int // the position of the added change output, or -1
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals the result of the fundrawtransaction JSON-RPC call
|
||||
func (f *FundRawTransactionResult) UnmarshalJSON(data []byte) error {
|
||||
var rawRes rawFundRawTransactionResult
|
||||
if err := json.Unmarshal(data, &rawRes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBytes, err := hex.DecodeString(rawRes.Transaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var msgTx wire.MsgTx
|
||||
witnessErr := msgTx.Deserialize(bytes.NewReader(txBytes))
|
||||
if witnessErr != nil {
|
||||
legacyErr := msgTx.DeserializeNoWitness(bytes.NewReader(txBytes))
|
||||
if legacyErr != nil {
|
||||
return legacyErr
|
||||
}
|
||||
}
|
||||
|
||||
fee, err := btcutil.NewAmount(rawRes.Fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.Transaction = &msgTx
|
||||
f.Fee = fee
|
||||
f.ChangePosition = rawRes.ChangePosition
|
||||
return nil
|
||||
}
|
||||
|
||||
20
vendor/github.com/btcsuite/btcd/btcjson/chainsvrwscmds.go
generated
vendored
20
vendor/github.com/btcsuite/btcd/btcjson/chainsvrwscmds.go
generated
vendored
@@ -80,7 +80,7 @@ func NewStopNotifyNewTransactionsCmd() *StopNotifyNewTransactionsCmd {
|
||||
|
||||
// NotifyReceivedCmd defines the notifyreceived JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
|
||||
// Deprecated: Use LoadTxFilterCmd instead.
|
||||
type NotifyReceivedCmd struct {
|
||||
Addresses []string
|
||||
}
|
||||
@@ -88,7 +88,7 @@ type NotifyReceivedCmd struct {
|
||||
// NewNotifyReceivedCmd returns a new instance which can be used to issue a
|
||||
// notifyreceived JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
|
||||
// Deprecated: Use NewLoadTxFilterCmd instead.
|
||||
func NewNotifyReceivedCmd(addresses []string) *NotifyReceivedCmd {
|
||||
return &NotifyReceivedCmd{
|
||||
Addresses: addresses,
|
||||
@@ -128,7 +128,7 @@ func NewLoadTxFilterCmd(reload bool, addresses []string, outPoints []OutPoint) *
|
||||
|
||||
// NotifySpentCmd defines the notifyspent JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
|
||||
// Deprecated: Use LoadTxFilterCmd instead.
|
||||
type NotifySpentCmd struct {
|
||||
OutPoints []OutPoint
|
||||
}
|
||||
@@ -136,7 +136,7 @@ type NotifySpentCmd struct {
|
||||
// NewNotifySpentCmd returns a new instance which can be used to issue a
|
||||
// notifyspent JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
|
||||
// Deprecated: Use NewLoadTxFilterCmd instead.
|
||||
func NewNotifySpentCmd(outPoints []OutPoint) *NotifySpentCmd {
|
||||
return &NotifySpentCmd{
|
||||
OutPoints: outPoints,
|
||||
@@ -145,7 +145,7 @@ func NewNotifySpentCmd(outPoints []OutPoint) *NotifySpentCmd {
|
||||
|
||||
// StopNotifyReceivedCmd defines the stopnotifyreceived JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
|
||||
// Deprecated: Use LoadTxFilterCmd instead.
|
||||
type StopNotifyReceivedCmd struct {
|
||||
Addresses []string
|
||||
}
|
||||
@@ -153,7 +153,7 @@ type StopNotifyReceivedCmd struct {
|
||||
// NewStopNotifyReceivedCmd returns a new instance which can be used to issue a
|
||||
// stopnotifyreceived JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
|
||||
// Deprecated: Use NewLoadTxFilterCmd instead.
|
||||
func NewStopNotifyReceivedCmd(addresses []string) *StopNotifyReceivedCmd {
|
||||
return &StopNotifyReceivedCmd{
|
||||
Addresses: addresses,
|
||||
@@ -162,7 +162,7 @@ func NewStopNotifyReceivedCmd(addresses []string) *StopNotifyReceivedCmd {
|
||||
|
||||
// StopNotifySpentCmd defines the stopnotifyspent JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use LoadTxFilterCmd instead.
|
||||
// Deprecated: Use LoadTxFilterCmd instead.
|
||||
type StopNotifySpentCmd struct {
|
||||
OutPoints []OutPoint
|
||||
}
|
||||
@@ -170,7 +170,7 @@ type StopNotifySpentCmd struct {
|
||||
// NewStopNotifySpentCmd returns a new instance which can be used to issue a
|
||||
// stopnotifyspent JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewLoadTxFilterCmd instead.
|
||||
// Deprecated: Use NewLoadTxFilterCmd instead.
|
||||
func NewStopNotifySpentCmd(outPoints []OutPoint) *StopNotifySpentCmd {
|
||||
return &StopNotifySpentCmd{
|
||||
OutPoints: outPoints,
|
||||
@@ -179,7 +179,7 @@ func NewStopNotifySpentCmd(outPoints []OutPoint) *StopNotifySpentCmd {
|
||||
|
||||
// RescanCmd defines the rescan JSON-RPC command.
|
||||
//
|
||||
// NOTE: Deprecated. Use RescanBlocksCmd instead.
|
||||
// Deprecated: Use RescanBlocksCmd instead.
|
||||
type RescanCmd struct {
|
||||
BeginBlock string
|
||||
Addresses []string
|
||||
@@ -193,7 +193,7 @@ type RescanCmd struct {
|
||||
// The parameters which are pointers indicate they are optional. Passing nil
|
||||
// for optional parameters will use the default value.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewRescanBlocksCmd instead.
|
||||
// Deprecated: Use NewRescanBlocksCmd instead.
|
||||
func NewRescanCmd(beginBlock string, addresses []string, outPoints []OutPoint, endBlock *string) *RescanCmd {
|
||||
return &RescanCmd{
|
||||
BeginBlock: beginBlock,
|
||||
|
||||
36
vendor/github.com/btcsuite/btcd/btcjson/chainsvrwsntfns.go
generated
vendored
36
vendor/github.com/btcsuite/btcd/btcjson/chainsvrwsntfns.go
generated
vendored
@@ -12,14 +12,14 @@ const (
|
||||
// BlockConnectedNtfnMethod is the legacy, deprecated method used for
|
||||
// notifications from the chain server that a block has been connected.
|
||||
//
|
||||
// NOTE: Deprecated. Use FilteredBlockConnectedNtfnMethod instead.
|
||||
// Deprecated: Use FilteredBlockConnectedNtfnMethod instead.
|
||||
BlockConnectedNtfnMethod = "blockconnected"
|
||||
|
||||
// BlockDisconnectedNtfnMethod is the legacy, deprecated method used for
|
||||
// notifications from the chain server that a block has been
|
||||
// disconnected.
|
||||
//
|
||||
// NOTE: Deprecated. Use FilteredBlockDisconnectedNtfnMethod instead.
|
||||
// Deprecated: Use FilteredBlockDisconnectedNtfnMethod instead.
|
||||
BlockDisconnectedNtfnMethod = "blockdisconnected"
|
||||
|
||||
// FilteredBlockConnectedNtfnMethod is the new method used for
|
||||
@@ -35,7 +35,7 @@ const (
|
||||
// notifications from the chain server that a transaction which pays to
|
||||
// a registered address has been processed.
|
||||
//
|
||||
// NOTE: Deprecated. Use RelevantTxAcceptedNtfnMethod and
|
||||
// Deprecated: Use RelevantTxAcceptedNtfnMethod and
|
||||
// FilteredBlockConnectedNtfnMethod instead.
|
||||
RecvTxNtfnMethod = "recvtx"
|
||||
|
||||
@@ -43,7 +43,7 @@ const (
|
||||
// notifications from the chain server that a transaction which spends a
|
||||
// registered outpoint has been processed.
|
||||
//
|
||||
// NOTE: Deprecated. Use RelevantTxAcceptedNtfnMethod and
|
||||
// Deprecated: Use RelevantTxAcceptedNtfnMethod and
|
||||
// FilteredBlockConnectedNtfnMethod instead.
|
||||
RedeemingTxNtfnMethod = "redeemingtx"
|
||||
|
||||
@@ -51,14 +51,14 @@ const (
|
||||
// notifications from the chain server that a legacy, deprecated rescan
|
||||
// operation has finished.
|
||||
//
|
||||
// NOTE: Deprecated. Not used with rescanblocks command.
|
||||
// Deprecated: Not used with rescanblocks command.
|
||||
RescanFinishedNtfnMethod = "rescanfinished"
|
||||
|
||||
// RescanProgressNtfnMethod is the legacy, deprecated method used for
|
||||
// notifications from the chain server that a legacy, deprecated rescan
|
||||
// operation this is underway has made progress.
|
||||
//
|
||||
// NOTE: Deprecated. Not used with rescanblocks command.
|
||||
// Deprecated: Not used with rescanblocks command.
|
||||
RescanProgressNtfnMethod = "rescanprogress"
|
||||
|
||||
// TxAcceptedNtfnMethod is the method used for notifications from the
|
||||
@@ -79,7 +79,7 @@ const (
|
||||
|
||||
// BlockConnectedNtfn defines the blockconnected JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use FilteredBlockConnectedNtfn instead.
|
||||
// Deprecated: Use FilteredBlockConnectedNtfn instead.
|
||||
type BlockConnectedNtfn struct {
|
||||
Hash string
|
||||
Height int32
|
||||
@@ -89,7 +89,7 @@ type BlockConnectedNtfn struct {
|
||||
// NewBlockConnectedNtfn returns a new instance which can be used to issue a
|
||||
// blockconnected JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewFilteredBlockConnectedNtfn instead.
|
||||
// Deprecated: Use NewFilteredBlockConnectedNtfn instead.
|
||||
func NewBlockConnectedNtfn(hash string, height int32, time int64) *BlockConnectedNtfn {
|
||||
return &BlockConnectedNtfn{
|
||||
Hash: hash,
|
||||
@@ -100,7 +100,7 @@ func NewBlockConnectedNtfn(hash string, height int32, time int64) *BlockConnecte
|
||||
|
||||
// BlockDisconnectedNtfn defines the blockdisconnected JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use FilteredBlockDisconnectedNtfn instead.
|
||||
// Deprecated: Use FilteredBlockDisconnectedNtfn instead.
|
||||
type BlockDisconnectedNtfn struct {
|
||||
Hash string
|
||||
Height int32
|
||||
@@ -110,7 +110,7 @@ type BlockDisconnectedNtfn struct {
|
||||
// NewBlockDisconnectedNtfn returns a new instance which can be used to issue a
|
||||
// blockdisconnected JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewFilteredBlockDisconnectedNtfn instead.
|
||||
// Deprecated: Use NewFilteredBlockDisconnectedNtfn instead.
|
||||
func NewBlockDisconnectedNtfn(hash string, height int32, time int64) *BlockDisconnectedNtfn {
|
||||
return &BlockDisconnectedNtfn{
|
||||
Hash: hash,
|
||||
@@ -163,7 +163,7 @@ type BlockDetails struct {
|
||||
|
||||
// RecvTxNtfn defines the recvtx JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn
|
||||
// Deprecated: Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn
|
||||
// instead.
|
||||
type RecvTxNtfn struct {
|
||||
HexTx string
|
||||
@@ -173,7 +173,7 @@ type RecvTxNtfn struct {
|
||||
// NewRecvTxNtfn returns a new instance which can be used to issue a recvtx
|
||||
// JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewRelevantTxAcceptedNtfn and
|
||||
// Deprecated: Use NewRelevantTxAcceptedNtfn and
|
||||
// NewFilteredBlockConnectedNtfn instead.
|
||||
func NewRecvTxNtfn(hexTx string, block *BlockDetails) *RecvTxNtfn {
|
||||
return &RecvTxNtfn{
|
||||
@@ -184,7 +184,7 @@ func NewRecvTxNtfn(hexTx string, block *BlockDetails) *RecvTxNtfn {
|
||||
|
||||
// RedeemingTxNtfn defines the redeemingtx JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn
|
||||
// Deprecated: Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn
|
||||
// instead.
|
||||
type RedeemingTxNtfn struct {
|
||||
HexTx string
|
||||
@@ -194,7 +194,7 @@ type RedeemingTxNtfn struct {
|
||||
// NewRedeemingTxNtfn returns a new instance which can be used to issue a
|
||||
// redeemingtx JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Use NewRelevantTxAcceptedNtfn and
|
||||
// Deprecated: Use NewRelevantTxAcceptedNtfn and
|
||||
// NewFilteredBlockConnectedNtfn instead.
|
||||
func NewRedeemingTxNtfn(hexTx string, block *BlockDetails) *RedeemingTxNtfn {
|
||||
return &RedeemingTxNtfn{
|
||||
@@ -205,7 +205,7 @@ func NewRedeemingTxNtfn(hexTx string, block *BlockDetails) *RedeemingTxNtfn {
|
||||
|
||||
// RescanFinishedNtfn defines the rescanfinished JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Not used with rescanblocks command.
|
||||
// Deprecated: Not used with rescanblocks command.
|
||||
type RescanFinishedNtfn struct {
|
||||
Hash string
|
||||
Height int32
|
||||
@@ -215,7 +215,7 @@ type RescanFinishedNtfn struct {
|
||||
// NewRescanFinishedNtfn returns a new instance which can be used to issue a
|
||||
// rescanfinished JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Not used with rescanblocks command.
|
||||
// Deprecated: Not used with rescanblocks command.
|
||||
func NewRescanFinishedNtfn(hash string, height int32, time int64) *RescanFinishedNtfn {
|
||||
return &RescanFinishedNtfn{
|
||||
Hash: hash,
|
||||
@@ -226,7 +226,7 @@ func NewRescanFinishedNtfn(hash string, height int32, time int64) *RescanFinishe
|
||||
|
||||
// RescanProgressNtfn defines the rescanprogress JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Not used with rescanblocks command.
|
||||
// Deprecated: Not used with rescanblocks command.
|
||||
type RescanProgressNtfn struct {
|
||||
Hash string
|
||||
Height int32
|
||||
@@ -236,7 +236,7 @@ type RescanProgressNtfn struct {
|
||||
// NewRescanProgressNtfn returns a new instance which can be used to issue a
|
||||
// rescanprogress JSON-RPC notification.
|
||||
//
|
||||
// NOTE: Deprecated. Not used with rescanblocks command.
|
||||
// Deprecated: Not used with rescanblocks command.
|
||||
func NewRescanProgressNtfn(hash string, height int32, time int64) *RescanProgressNtfn {
|
||||
return &RescanProgressNtfn{
|
||||
Hash: hash,
|
||||
|
||||
4
vendor/github.com/btcsuite/btcd/btcjson/jsonrpc.go
generated
vendored
4
vendor/github.com/btcsuite/btcd/btcjson/jsonrpc.go
generated
vendored
@@ -22,10 +22,10 @@ type RPCError struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// Guarantee RPCError satisifies the builtin error interface.
|
||||
// Guarantee RPCError satisfies the builtin error interface.
|
||||
var _, _ error = RPCError{}, (*RPCError)(nil)
|
||||
|
||||
// Error returns a string describing the RPC error. This satisifies the
|
||||
// Error returns a string describing the RPC error. This satisfies the
|
||||
// builtin error interface.
|
||||
func (e RPCError) Error() string {
|
||||
return fmt.Sprintf("%d: %s", e.Code, e.Message)
|
||||
|
||||
1
vendor/github.com/btcsuite/btcd/btcjson/jsonrpcerr.go
generated
vendored
1
vendor/github.com/btcsuite/btcd/btcjson/jsonrpcerr.go
generated
vendored
@@ -39,6 +39,7 @@ const (
|
||||
ErrRPCDatabase RPCErrorCode = -20
|
||||
ErrRPCDeserialization RPCErrorCode = -22
|
||||
ErrRPCVerify RPCErrorCode = -25
|
||||
ErrRPCInWarmup RPCErrorCode = -28
|
||||
)
|
||||
|
||||
// Peer-to-peer client errors.
|
||||
|
||||
2
vendor/github.com/btcsuite/btcd/btcjson/register.go
generated
vendored
2
vendor/github.com/btcsuite/btcd/btcjson/register.go
generated
vendored
@@ -287,6 +287,6 @@ func RegisteredCmdMethods() []string {
|
||||
methods = append(methods, k)
|
||||
}
|
||||
|
||||
sort.Sort(sort.StringSlice(methods))
|
||||
sort.Strings(methods)
|
||||
return methods
|
||||
}
|
||||
|
||||
35
vendor/github.com/btcsuite/btcd/btcjson/walletsvrcmds.go
generated
vendored
35
vendor/github.com/btcsuite/btcd/btcjson/walletsvrcmds.go
generated
vendored
@@ -81,6 +81,30 @@ func NewEncryptWalletCmd(passphrase string) *EncryptWalletCmd {
|
||||
}
|
||||
}
|
||||
|
||||
// EstimateSmartFeeMode defines the different fee estimation modes available
|
||||
// for the estimatesmartfee JSON-RPC command.
|
||||
type EstimateSmartFeeMode string
|
||||
|
||||
var (
|
||||
EstimateModeUnset EstimateSmartFeeMode = "UNSET"
|
||||
EstimateModeEconomical EstimateSmartFeeMode = "ECONOMICAL"
|
||||
EstimateModeConservative EstimateSmartFeeMode = "CONSERVATIVE"
|
||||
)
|
||||
|
||||
// EstimateSmartFeeCmd defines the estimatesmartfee JSON-RPC command.
|
||||
type EstimateSmartFeeCmd struct {
|
||||
ConfTarget int64
|
||||
EstimateMode *EstimateSmartFeeMode `jsonrpcdefault:"\"CONSERVATIVE\""`
|
||||
}
|
||||
|
||||
// NewEstimateSmartFeeCmd returns a new instance which can be used to issue a
|
||||
// estimatesmartfee JSON-RPC command.
|
||||
func NewEstimateSmartFeeCmd(confTarget int64, mode *EstimateSmartFeeMode) *EstimateSmartFeeCmd {
|
||||
return &EstimateSmartFeeCmd{
|
||||
ConfTarget: confTarget, EstimateMode: mode,
|
||||
}
|
||||
}
|
||||
|
||||
// EstimateFeeCmd defines the estimatefee JSON-RPC command.
|
||||
type EstimateFeeCmd struct {
|
||||
NumBlocks int64
|
||||
@@ -164,6 +188,15 @@ func NewGetBalanceCmd(account *string, minConf *int) *GetBalanceCmd {
|
||||
}
|
||||
}
|
||||
|
||||
// GetBalancesCmd defines the getbalances JSON-RPC command.
|
||||
type GetBalancesCmd struct{}
|
||||
|
||||
// NewGetBalancesCmd returns a new instance which can be used to issue a
|
||||
// getbalances JSON-RPC command.
|
||||
func NewGetBalancesCmd() *GetBalancesCmd {
|
||||
return &GetBalancesCmd{}
|
||||
}
|
||||
|
||||
// GetNewAddressCmd defines the getnewaddress JSON-RPC command.
|
||||
type GetNewAddressCmd struct {
|
||||
Account *string
|
||||
@@ -662,12 +695,14 @@ func init() {
|
||||
MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags)
|
||||
MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags)
|
||||
MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags)
|
||||
MustRegisterCmd("estimatesmartfee", (*EstimateSmartFeeCmd)(nil), flags)
|
||||
MustRegisterCmd("estimatefee", (*EstimateFeeCmd)(nil), flags)
|
||||
MustRegisterCmd("estimatepriority", (*EstimatePriorityCmd)(nil), flags)
|
||||
MustRegisterCmd("getaccount", (*GetAccountCmd)(nil), flags)
|
||||
MustRegisterCmd("getaccountaddress", (*GetAccountAddressCmd)(nil), flags)
|
||||
MustRegisterCmd("getaddressesbyaccount", (*GetAddressesByAccountCmd)(nil), flags)
|
||||
MustRegisterCmd("getbalance", (*GetBalanceCmd)(nil), flags)
|
||||
MustRegisterCmd("getbalances", (*GetBalancesCmd)(nil), flags)
|
||||
MustRegisterCmd("getnewaddress", (*GetNewAddressCmd)(nil), flags)
|
||||
MustRegisterCmd("getrawchangeaddress", (*GetRawChangeAddressCmd)(nil), flags)
|
||||
MustRegisterCmd("getreceivedbyaccount", (*GetReceivedByAccountCmd)(nil), flags)
|
||||
|
||||
14
vendor/github.com/btcsuite/btcd/btcjson/walletsvrresults.go
generated
vendored
14
vendor/github.com/btcsuite/btcd/btcjson/walletsvrresults.go
generated
vendored
@@ -159,3 +159,17 @@ type GetBestBlockResult struct {
|
||||
Hash string `json:"hash"`
|
||||
Height int32 `json:"height"`
|
||||
}
|
||||
|
||||
// BalanceDetailsResult models the details data from the `getbalances` command.
|
||||
type BalanceDetailsResult struct {
|
||||
Trusted float64 `json:"trusted"`
|
||||
UntrustedPending float64 `json:"untrusted_pending"`
|
||||
Immature float64 `json:"immature"`
|
||||
Used *float64 `json:"used"`
|
||||
}
|
||||
|
||||
// GetBalancesResult models the data returned from the getbalances command.
|
||||
type GetBalancesResult struct {
|
||||
Mine BalanceDetailsResult `json:"mine"`
|
||||
WatchOnly *BalanceDetailsResult `json:"watchonly"`
|
||||
}
|
||||
|
||||
2
vendor/github.com/btcsuite/btcd/connmgr/dynamicbanscore.go
generated
vendored
2
vendor/github.com/btcsuite/btcd/connmgr/dynamicbanscore.go
generated
vendored
@@ -71,7 +71,7 @@ type DynamicBanScore struct {
|
||||
func (s *DynamicBanScore) String() string {
|
||||
s.mtx.Lock()
|
||||
r := fmt.Sprintf("persistent %v + transient %v at %v = %v as of now",
|
||||
s.persistent, s.transient, s.lastUnix, s.Int())
|
||||
s.persistent, s.transient, s.lastUnix, s.int(time.Now()))
|
||||
s.mtx.Unlock()
|
||||
return r
|
||||
}
|
||||
|
||||
30
vendor/github.com/btcsuite/btcd/integration/rpctest/README.md
generated
vendored
Normal file
30
vendor/github.com/btcsuite/btcd/integration/rpctest/README.md
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
rpctest
|
||||
=======
|
||||
|
||||
[](https://travis-ci.org/btcsuite/btcd)
|
||||
[](http://copyfree.org)
|
||||
[](http://godoc.org/github.com/btcsuite/btcd/integration/rpctest)
|
||||
|
||||
Package rpctest provides a btcd-specific RPC testing harness crafting and
|
||||
executing integration tests by driving a `btcd` instance via the `RPC`
|
||||
interface. Each instance of an active harness comes equipped with a simple
|
||||
in-memory HD wallet capable of properly syncing to the generated chain,
|
||||
creating new addresses, and crafting fully signed transactions paying to an
|
||||
arbitrary set of outputs.
|
||||
|
||||
This package was designed specifically to act as an RPC testing harness for
|
||||
`btcd`. However, the constructs presented are general enough to be adapted to
|
||||
any project wishing to programmatically drive a `btcd` instance of its
|
||||
systems/integration tests.
|
||||
|
||||
## Installation and Updating
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/btcsuite/btcd/integration/rpctest
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Package rpctest is licensed under the [copyfree](http://copyfree.org) ISC
|
||||
License.
|
||||
|
||||
207
vendor/github.com/btcsuite/btcd/integration/rpctest/blockgen.go
generated
vendored
Normal file
207
vendor/github.com/btcsuite/btcd/integration/rpctest/blockgen.go
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright (c) 2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// solveBlock attempts to find a nonce which makes the passed block header hash
|
||||
// to a value less than the target difficulty. When a successful solution is
|
||||
// found true is returned and the nonce field of the passed header is updated
|
||||
// with the solution. False is returned if no solution exists.
|
||||
func solveBlock(header *wire.BlockHeader, targetDifficulty *big.Int) bool {
|
||||
// sbResult is used by the solver goroutines to send results.
|
||||
type sbResult struct {
|
||||
found bool
|
||||
nonce uint32
|
||||
}
|
||||
|
||||
// solver accepts a block header and a nonce range to test. It is
|
||||
// intended to be run as a goroutine.
|
||||
quit := make(chan bool)
|
||||
results := make(chan sbResult)
|
||||
solver := func(hdr wire.BlockHeader, startNonce, stopNonce uint32) {
|
||||
// We need to modify the nonce field of the header, so make sure
|
||||
// we work with a copy of the original header.
|
||||
for i := startNonce; i >= startNonce && i <= stopNonce; i++ {
|
||||
select {
|
||||
case <-quit:
|
||||
return
|
||||
default:
|
||||
hdr.Nonce = i
|
||||
hash := hdr.BlockHash()
|
||||
if blockchain.HashToBig(&hash).Cmp(targetDifficulty) <= 0 {
|
||||
select {
|
||||
case results <- sbResult{true, i}:
|
||||
return
|
||||
case <-quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
select {
|
||||
case results <- sbResult{false, 0}:
|
||||
case <-quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
startNonce := uint32(0)
|
||||
stopNonce := uint32(math.MaxUint32)
|
||||
numCores := uint32(runtime.NumCPU())
|
||||
noncesPerCore := (stopNonce - startNonce) / numCores
|
||||
for i := uint32(0); i < numCores; i++ {
|
||||
rangeStart := startNonce + (noncesPerCore * i)
|
||||
rangeStop := startNonce + (noncesPerCore * (i + 1)) - 1
|
||||
if i == numCores-1 {
|
||||
rangeStop = stopNonce
|
||||
}
|
||||
go solver(*header, rangeStart, rangeStop)
|
||||
}
|
||||
for i := uint32(0); i < numCores; i++ {
|
||||
result := <-results
|
||||
if result.found {
|
||||
close(quit)
|
||||
header.Nonce = result.nonce
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// standardCoinbaseScript returns a standard script suitable for use as the
|
||||
// signature script of the coinbase transaction of a new block. In particular,
|
||||
// it starts with the block height that is required by version 2 blocks.
|
||||
func standardCoinbaseScript(nextBlockHeight int32, extraNonce uint64) ([]byte, error) {
|
||||
return txscript.NewScriptBuilder().AddInt64(int64(nextBlockHeight)).
|
||||
AddInt64(int64(extraNonce)).Script()
|
||||
}
|
||||
|
||||
// createCoinbaseTx returns a coinbase transaction paying an appropriate
|
||||
// subsidy based on the passed block height to the provided address.
|
||||
func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32,
|
||||
addr btcutil.Address, mineTo []wire.TxOut,
|
||||
net *chaincfg.Params) (*btcutil.Tx, error) {
|
||||
|
||||
// Create the script to pay to the provided payment address.
|
||||
pkScript, err := txscript.PayToAddrScript(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx := wire.NewMsgTx(wire.TxVersion)
|
||||
tx.AddTxIn(&wire.TxIn{
|
||||
// Coinbase transactions have no inputs, so previous outpoint is
|
||||
// zero hash and max index.
|
||||
PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{},
|
||||
wire.MaxPrevOutIndex),
|
||||
SignatureScript: coinbaseScript,
|
||||
Sequence: wire.MaxTxInSequenceNum,
|
||||
})
|
||||
if len(mineTo) == 0 {
|
||||
tx.AddTxOut(&wire.TxOut{
|
||||
Value: blockchain.CalcBlockSubsidy(nextBlockHeight, net),
|
||||
PkScript: pkScript,
|
||||
})
|
||||
} else {
|
||||
for i := range mineTo {
|
||||
tx.AddTxOut(&mineTo[i])
|
||||
}
|
||||
}
|
||||
return btcutil.NewTx(tx), nil
|
||||
}
|
||||
|
||||
// CreateBlock creates a new block building from the previous block with a
|
||||
// specified blockversion and timestamp. If the timestamp passed is zero (not
|
||||
// initialized), then the timestamp of the previous block will be used plus 1
|
||||
// second is used. Passing nil for the previous block results in a block that
|
||||
// builds off of the genesis block for the specified chain.
|
||||
func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx,
|
||||
blockVersion int32, blockTime time.Time, miningAddr btcutil.Address,
|
||||
mineTo []wire.TxOut, net *chaincfg.Params) (*btcutil.Block, error) {
|
||||
|
||||
var (
|
||||
prevHash *chainhash.Hash
|
||||
blockHeight int32
|
||||
prevBlockTime time.Time
|
||||
)
|
||||
|
||||
// If the previous block isn't specified, then we'll construct a block
|
||||
// that builds off of the genesis block for the chain.
|
||||
if prevBlock == nil {
|
||||
prevHash = net.GenesisHash
|
||||
blockHeight = 1
|
||||
prevBlockTime = net.GenesisBlock.Header.Timestamp.Add(time.Minute)
|
||||
} else {
|
||||
prevHash = prevBlock.Hash()
|
||||
blockHeight = prevBlock.Height() + 1
|
||||
prevBlockTime = prevBlock.MsgBlock().Header.Timestamp
|
||||
}
|
||||
|
||||
// If a target block time was specified, then use that as the header's
|
||||
// timestamp. Otherwise, add one second to the previous block unless
|
||||
// it's the genesis block in which case use the current time.
|
||||
var ts time.Time
|
||||
switch {
|
||||
case !blockTime.IsZero():
|
||||
ts = blockTime
|
||||
default:
|
||||
ts = prevBlockTime.Add(time.Second)
|
||||
}
|
||||
|
||||
extraNonce := uint64(0)
|
||||
coinbaseScript, err := standardCoinbaseScript(blockHeight, extraNonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
coinbaseTx, err := createCoinbaseTx(coinbaseScript, blockHeight,
|
||||
miningAddr, mineTo, net)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a new block ready to be solved.
|
||||
blockTxns := []*btcutil.Tx{coinbaseTx}
|
||||
if inclusionTxs != nil {
|
||||
blockTxns = append(blockTxns, inclusionTxs...)
|
||||
}
|
||||
merkles := blockchain.BuildMerkleTreeStore(blockTxns, false)
|
||||
var block wire.MsgBlock
|
||||
block.Header = wire.BlockHeader{
|
||||
Version: blockVersion,
|
||||
PrevBlock: *prevHash,
|
||||
MerkleRoot: *merkles[len(merkles)-1],
|
||||
Timestamp: ts,
|
||||
Bits: net.PowLimitBits,
|
||||
}
|
||||
for _, tx := range blockTxns {
|
||||
if err := block.AddTransaction(tx.MsgTx()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
found := solveBlock(&block.Header, net.PowLimit)
|
||||
if !found {
|
||||
return nil, errors.New("Unable to solve block")
|
||||
}
|
||||
|
||||
utilBlock := btcutil.NewBlock(&block)
|
||||
utilBlock.SetHeight(blockHeight)
|
||||
return utilBlock, nil
|
||||
}
|
||||
62
vendor/github.com/btcsuite/btcd/integration/rpctest/btcd.go
generated
vendored
Normal file
62
vendor/github.com/btcsuite/btcd/integration/rpctest/btcd.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// compileMtx guards access to the executable path so that the project is
|
||||
// only compiled once.
|
||||
compileMtx sync.Mutex
|
||||
|
||||
// executablePath is the path to the compiled executable. This is the empty
|
||||
// string until btcd is compiled. This should not be accessed directly;
|
||||
// instead use the function btcdExecutablePath().
|
||||
executablePath string
|
||||
)
|
||||
|
||||
// btcdExecutablePath returns a path to the btcd executable to be used by
|
||||
// rpctests. To ensure the code tests against the most up-to-date version of
|
||||
// btcd, this method compiles btcd the first time it is called. After that, the
|
||||
// generated binary is used for subsequent test harnesses. The executable file
|
||||
// is not cleaned up, but since it lives at a static path in a temp directory,
|
||||
// it is not a big deal.
|
||||
func btcdExecutablePath() (string, error) {
|
||||
compileMtx.Lock()
|
||||
defer compileMtx.Unlock()
|
||||
|
||||
// If btcd has already been compiled, just use that.
|
||||
if len(executablePath) != 0 {
|
||||
return executablePath, nil
|
||||
}
|
||||
|
||||
testDir, err := baseDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Build btcd and output an executable in a static temp path.
|
||||
outputPath := filepath.Join(testDir, "btcd")
|
||||
if runtime.GOOS == "windows" {
|
||||
outputPath += ".exe"
|
||||
}
|
||||
cmd := exec.Command(
|
||||
"go", "build", "-o", outputPath, "github.com/btcsuite/btcd",
|
||||
)
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to build btcd: %v", err)
|
||||
}
|
||||
|
||||
// Save executable path so future calls do not recompile.
|
||||
executablePath = outputPath
|
||||
return executablePath, nil
|
||||
}
|
||||
12
vendor/github.com/btcsuite/btcd/integration/rpctest/doc.go
generated
vendored
Normal file
12
vendor/github.com/btcsuite/btcd/integration/rpctest/doc.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// Package rpctest provides a btcd-specific RPC testing harness crafting and
|
||||
// executing integration tests by driving a `btcd` instance via the `RPC`
|
||||
// interface. Each instance of an active harness comes equipped with a simple
|
||||
// in-memory HD wallet capable of properly syncing to the generated chain,
|
||||
// creating new addresses, and crafting fully signed transactions paying to an
|
||||
// arbitrary set of outputs.
|
||||
//
|
||||
// This package was designed specifically to act as an RPC testing harness for
|
||||
// `btcd`. However, the constructs presented are general enough to be adapted to
|
||||
// any project wishing to programmatically drive a `btcd` instance of its
|
||||
// systems/integration tests.
|
||||
package rpctest
|
||||
591
vendor/github.com/btcsuite/btcd/integration/rpctest/memwallet.go
generated
vendored
Normal file
591
vendor/github.com/btcsuite/btcd/integration/rpctest/memwallet.go
generated
vendored
Normal file
@@ -0,0 +1,591 @@
|
||||
// Copyright (c) 2016-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
||||
var (
|
||||
// hdSeed is the BIP 32 seed used by the memWallet to initialize it's
|
||||
// HD root key. This value is hard coded in order to ensure
|
||||
// deterministic behavior across test runs.
|
||||
hdSeed = [chainhash.HashSize]byte{
|
||||
0x79, 0xa6, 0x1a, 0xdb, 0xc6, 0xe5, 0xa2, 0xe1,
|
||||
0x39, 0xd2, 0x71, 0x3a, 0x54, 0x6e, 0xc7, 0xc8,
|
||||
0x75, 0x63, 0x2e, 0x75, 0xf1, 0xdf, 0x9c, 0x3f,
|
||||
0xa6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
)
|
||||
|
||||
// utxo represents an unspent output spendable by the memWallet. The maturity
|
||||
// height of the transaction is recorded in order to properly observe the
|
||||
// maturity period of direct coinbase outputs.
|
||||
type utxo struct {
|
||||
pkScript []byte
|
||||
value btcutil.Amount
|
||||
keyIndex uint32
|
||||
maturityHeight int32
|
||||
isLocked bool
|
||||
}
|
||||
|
||||
// isMature returns true if the target utxo is considered "mature" at the
|
||||
// passed block height. Otherwise, false is returned.
|
||||
func (u *utxo) isMature(height int32) bool {
|
||||
return height >= u.maturityHeight
|
||||
}
|
||||
|
||||
// chainUpdate encapsulates an update to the current main chain. This struct is
|
||||
// used to sync up the memWallet each time a new block is connected to the main
|
||||
// chain.
|
||||
type chainUpdate struct {
|
||||
blockHeight int32
|
||||
filteredTxns []*btcutil.Tx
|
||||
isConnect bool // True if connect, false if disconnect
|
||||
}
|
||||
|
||||
// undoEntry is functionally the opposite of a chainUpdate. An undoEntry is
|
||||
// created for each new block received, then stored in a log in order to
|
||||
// properly handle block re-orgs.
|
||||
type undoEntry struct {
|
||||
utxosDestroyed map[wire.OutPoint]*utxo
|
||||
utxosCreated []wire.OutPoint
|
||||
}
|
||||
|
||||
// memWallet is a simple in-memory wallet whose purpose is to provide basic
|
||||
// wallet functionality to the harness. The wallet uses a hard-coded HD key
|
||||
// hierarchy which promotes reproducibility between harness test runs.
|
||||
type memWallet struct {
|
||||
coinbaseKey *btcec.PrivateKey
|
||||
coinbaseAddr btcutil.Address
|
||||
|
||||
// hdRoot is the root master private key for the wallet.
|
||||
hdRoot *hdkeychain.ExtendedKey
|
||||
|
||||
// hdIndex is the next available key index offset from the hdRoot.
|
||||
hdIndex uint32
|
||||
|
||||
// currentHeight is the latest height the wallet is known to be synced
|
||||
// to.
|
||||
currentHeight int32
|
||||
|
||||
// addrs tracks all addresses belonging to the wallet. The addresses
|
||||
// are indexed by their keypath from the hdRoot.
|
||||
addrs map[uint32]btcutil.Address
|
||||
|
||||
// utxos is the set of utxos spendable by the wallet.
|
||||
utxos map[wire.OutPoint]*utxo
|
||||
|
||||
// reorgJournal is a map storing an undo entry for each new block
|
||||
// received. Once a block is disconnected, the undo entry for the
|
||||
// particular height is evaluated, thereby rewinding the effect of the
|
||||
// disconnected block on the wallet's set of spendable utxos.
|
||||
reorgJournal map[int32]*undoEntry
|
||||
|
||||
chainUpdates []*chainUpdate
|
||||
chainUpdateSignal chan struct{}
|
||||
chainMtx sync.Mutex
|
||||
|
||||
net *chaincfg.Params
|
||||
|
||||
rpc *rpcclient.Client
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// newMemWallet creates and returns a fully initialized instance of the
|
||||
// memWallet given a particular blockchain's parameters.
|
||||
func newMemWallet(net *chaincfg.Params, harnessID uint32) (*memWallet, error) {
|
||||
// The wallet's final HD seed is: hdSeed || harnessID. This method
|
||||
// ensures that each harness instance uses a deterministic root seed
|
||||
// based on its harness ID.
|
||||
var harnessHDSeed [chainhash.HashSize + 4]byte
|
||||
copy(harnessHDSeed[:], hdSeed[:])
|
||||
binary.BigEndian.PutUint32(harnessHDSeed[:chainhash.HashSize], harnessID)
|
||||
|
||||
hdRoot, err := hdkeychain.NewMaster(harnessHDSeed[:], net)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// The first child key from the hd root is reserved as the coinbase
|
||||
// generation address.
|
||||
coinbaseChild, err := hdRoot.Child(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
coinbaseKey, err := coinbaseChild.ECPrivKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
coinbaseAddr, err := keyToAddr(coinbaseKey, net)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Track the coinbase generation address to ensure we properly track
|
||||
// newly generated bitcoin we can spend.
|
||||
addrs := make(map[uint32]btcutil.Address)
|
||||
addrs[0] = coinbaseAddr
|
||||
|
||||
return &memWallet{
|
||||
net: net,
|
||||
coinbaseKey: coinbaseKey,
|
||||
coinbaseAddr: coinbaseAddr,
|
||||
hdIndex: 1,
|
||||
hdRoot: hdRoot,
|
||||
addrs: addrs,
|
||||
utxos: make(map[wire.OutPoint]*utxo),
|
||||
chainUpdateSignal: make(chan struct{}),
|
||||
reorgJournal: make(map[int32]*undoEntry),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start launches all goroutines required for the wallet to function properly.
|
||||
func (m *memWallet) Start() {
|
||||
go m.chainSyncer()
|
||||
}
|
||||
|
||||
// SyncedHeight returns the height the wallet is known to be synced to.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *memWallet) SyncedHeight() int32 {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
return m.currentHeight
|
||||
}
|
||||
|
||||
// SetRPCClient saves the passed rpc connection to btcd as the wallet's
|
||||
// personal rpc connection.
|
||||
func (m *memWallet) SetRPCClient(rpcClient *rpcclient.Client) {
|
||||
m.rpc = rpcClient
|
||||
}
|
||||
|
||||
// IngestBlock is a call-back which is to be triggered each time a new block is
|
||||
// connected to the main chain. It queues the update for the chain syncer,
|
||||
// calling the private version in sequential order.
|
||||
func (m *memWallet) IngestBlock(height int32, header *wire.BlockHeader, filteredTxns []*btcutil.Tx) {
|
||||
// Append this new chain update to the end of the queue of new chain
|
||||
// updates.
|
||||
m.chainMtx.Lock()
|
||||
m.chainUpdates = append(m.chainUpdates, &chainUpdate{height,
|
||||
filteredTxns, true})
|
||||
m.chainMtx.Unlock()
|
||||
|
||||
// Launch a goroutine to signal the chainSyncer that a new update is
|
||||
// available. We do this in a new goroutine in order to avoid blocking
|
||||
// the main loop of the rpc client.
|
||||
go func() {
|
||||
m.chainUpdateSignal <- struct{}{}
|
||||
}()
|
||||
}
|
||||
|
||||
// ingestBlock updates the wallet's internal utxo state based on the outputs
|
||||
// created and destroyed within each block.
|
||||
func (m *memWallet) ingestBlock(update *chainUpdate) {
|
||||
// Update the latest synced height, then process each filtered
|
||||
// transaction in the block creating and destroying utxos within
|
||||
// the wallet as a result.
|
||||
m.currentHeight = update.blockHeight
|
||||
undo := &undoEntry{
|
||||
utxosDestroyed: make(map[wire.OutPoint]*utxo),
|
||||
}
|
||||
for _, tx := range update.filteredTxns {
|
||||
mtx := tx.MsgTx()
|
||||
isCoinbase := blockchain.IsCoinBaseTx(mtx)
|
||||
txHash := mtx.TxHash()
|
||||
m.evalOutputs(mtx.TxOut, &txHash, isCoinbase, undo)
|
||||
m.evalInputs(mtx.TxIn, undo)
|
||||
}
|
||||
|
||||
// Finally, record the undo entry for this block so we can
|
||||
// properly update our internal state in response to the block
|
||||
// being re-org'd from the main chain.
|
||||
m.reorgJournal[update.blockHeight] = undo
|
||||
}
|
||||
|
||||
// chainSyncer is a goroutine dedicated to processing new blocks in order to
|
||||
// keep the wallet's utxo state up to date.
|
||||
//
|
||||
// NOTE: This MUST be run as a goroutine.
|
||||
func (m *memWallet) chainSyncer() {
|
||||
var update *chainUpdate
|
||||
|
||||
for range m.chainUpdateSignal {
|
||||
// A new update is available, so pop the new chain update from
|
||||
// the front of the update queue.
|
||||
m.chainMtx.Lock()
|
||||
update = m.chainUpdates[0]
|
||||
m.chainUpdates[0] = nil // Set to nil to prevent GC leak.
|
||||
m.chainUpdates = m.chainUpdates[1:]
|
||||
m.chainMtx.Unlock()
|
||||
|
||||
m.Lock()
|
||||
if update.isConnect {
|
||||
m.ingestBlock(update)
|
||||
} else {
|
||||
m.unwindBlock(update)
|
||||
}
|
||||
m.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// evalOutputs evaluates each of the passed outputs, creating a new matching
|
||||
// utxo within the wallet if we're able to spend the output.
|
||||
func (m *memWallet) evalOutputs(outputs []*wire.TxOut, txHash *chainhash.Hash,
|
||||
isCoinbase bool, undo *undoEntry) {
|
||||
|
||||
for i, output := range outputs {
|
||||
pkScript := output.PkScript
|
||||
|
||||
// Scan all the addresses we currently control to see if the
|
||||
// output is paying to us.
|
||||
for keyIndex, addr := range m.addrs {
|
||||
pkHash := addr.ScriptAddress()
|
||||
if !bytes.Contains(pkScript, pkHash) {
|
||||
continue
|
||||
}
|
||||
|
||||
// If this is a coinbase output, then we mark the
|
||||
// maturity height at the proper block height in the
|
||||
// future.
|
||||
var maturityHeight int32
|
||||
if isCoinbase {
|
||||
maturityHeight = m.currentHeight + int32(m.net.CoinbaseMaturity)
|
||||
}
|
||||
|
||||
op := wire.OutPoint{Hash: *txHash, Index: uint32(i)}
|
||||
m.utxos[op] = &utxo{
|
||||
value: btcutil.Amount(output.Value),
|
||||
keyIndex: keyIndex,
|
||||
maturityHeight: maturityHeight,
|
||||
pkScript: pkScript,
|
||||
}
|
||||
undo.utxosCreated = append(undo.utxosCreated, op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// evalInputs scans all the passed inputs, destroying any utxos within the
|
||||
// wallet which are spent by an input.
|
||||
func (m *memWallet) evalInputs(inputs []*wire.TxIn, undo *undoEntry) {
|
||||
for _, txIn := range inputs {
|
||||
op := txIn.PreviousOutPoint
|
||||
oldUtxo, ok := m.utxos[op]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
undo.utxosDestroyed[op] = oldUtxo
|
||||
delete(m.utxos, op)
|
||||
}
|
||||
}
|
||||
|
||||
// UnwindBlock is a call-back which is to be executed each time a block is
|
||||
// disconnected from the main chain. It queues the update for the chain syncer,
|
||||
// calling the private version in sequential order.
|
||||
func (m *memWallet) UnwindBlock(height int32, header *wire.BlockHeader) {
|
||||
// Append this new chain update to the end of the queue of new chain
|
||||
// updates.
|
||||
m.chainMtx.Lock()
|
||||
m.chainUpdates = append(m.chainUpdates, &chainUpdate{height,
|
||||
nil, false})
|
||||
m.chainMtx.Unlock()
|
||||
|
||||
// Launch a goroutine to signal the chainSyncer that a new update is
|
||||
// available. We do this in a new goroutine in order to avoid blocking
|
||||
// the main loop of the rpc client.
|
||||
go func() {
|
||||
m.chainUpdateSignal <- struct{}{}
|
||||
}()
|
||||
}
|
||||
|
||||
// unwindBlock undoes the effect that a particular block had on the wallet's
|
||||
// internal utxo state.
|
||||
func (m *memWallet) unwindBlock(update *chainUpdate) {
|
||||
undo := m.reorgJournal[update.blockHeight]
|
||||
|
||||
for _, utxo := range undo.utxosCreated {
|
||||
delete(m.utxos, utxo)
|
||||
}
|
||||
|
||||
for outPoint, utxo := range undo.utxosDestroyed {
|
||||
m.utxos[outPoint] = utxo
|
||||
}
|
||||
|
||||
delete(m.reorgJournal, update.blockHeight)
|
||||
}
|
||||
|
||||
// newAddress returns a new address from the wallet's hd key chain. It also
|
||||
// loads the address into the RPC client's transaction filter to ensure any
|
||||
// transactions that involve it are delivered via the notifications.
|
||||
func (m *memWallet) newAddress() (btcutil.Address, error) {
|
||||
index := m.hdIndex
|
||||
|
||||
childKey, err := m.hdRoot.Child(index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
privKey, err := childKey.ECPrivKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := keyToAddr(privKey, m.net)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = m.rpc.LoadTxFilter(false, []btcutil.Address{addr}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.addrs[index] = addr
|
||||
|
||||
m.hdIndex++
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// NewAddress returns a fresh address spendable by the wallet.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *memWallet) NewAddress() (btcutil.Address, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
return m.newAddress()
|
||||
}
|
||||
|
||||
// fundTx attempts to fund a transaction sending amt bitcoin. The coins are
|
||||
// selected such that the final amount spent pays enough fees as dictated by the
|
||||
// passed fee rate. The passed fee rate should be expressed in
|
||||
// satoshis-per-byte. The transaction being funded can optionally include a
|
||||
// change output indicated by the change boolean.
|
||||
//
|
||||
// NOTE: The memWallet's mutex must be held when this function is called.
|
||||
func (m *memWallet) fundTx(tx *wire.MsgTx, amt btcutil.Amount,
|
||||
feeRate btcutil.Amount, change bool) error {
|
||||
|
||||
const (
|
||||
// spendSize is the largest number of bytes of a sigScript
|
||||
// which spends a p2pkh output: OP_DATA_73 <sig> OP_DATA_33 <pubkey>
|
||||
spendSize = 1 + 73 + 1 + 33
|
||||
)
|
||||
|
||||
var (
|
||||
amtSelected btcutil.Amount
|
||||
txSize int
|
||||
)
|
||||
|
||||
for outPoint, utxo := range m.utxos {
|
||||
// Skip any outputs that are still currently immature or are
|
||||
// currently locked.
|
||||
if !utxo.isMature(m.currentHeight) || utxo.isLocked {
|
||||
continue
|
||||
}
|
||||
|
||||
amtSelected += utxo.value
|
||||
|
||||
// Add the selected output to the transaction, updating the
|
||||
// current tx size while accounting for the size of the future
|
||||
// sigScript.
|
||||
tx.AddTxIn(wire.NewTxIn(&outPoint, nil, nil))
|
||||
txSize = tx.SerializeSize() + spendSize*len(tx.TxIn)
|
||||
|
||||
// Calculate the fee required for the txn at this point
|
||||
// observing the specified fee rate. If we don't have enough
|
||||
// coins from he current amount selected to pay the fee, then
|
||||
// continue to grab more coins.
|
||||
reqFee := btcutil.Amount(txSize * int(feeRate))
|
||||
if amtSelected-reqFee < amt {
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have any change left over and we should create a change
|
||||
// output, then add an additional output to the transaction
|
||||
// reserved for it.
|
||||
changeVal := amtSelected - amt - reqFee
|
||||
if changeVal > 0 && change {
|
||||
addr, err := m.newAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pkScript, err := txscript.PayToAddrScript(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
changeOutput := &wire.TxOut{
|
||||
Value: int64(changeVal),
|
||||
PkScript: pkScript,
|
||||
}
|
||||
tx.AddTxOut(changeOutput)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we've reached this point, then coin selection failed due to an
|
||||
// insufficient amount of coins.
|
||||
return fmt.Errorf("not enough funds for coin selection")
|
||||
}
|
||||
|
||||
// SendOutputs creates, then sends a transaction paying to the specified output
|
||||
// while observing the passed fee rate. The passed fee rate should be expressed
|
||||
// in satoshis-per-byte.
|
||||
func (m *memWallet) SendOutputs(outputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount) (*chainhash.Hash, error) {
|
||||
|
||||
tx, err := m.CreateTransaction(outputs, feeRate, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m.rpc.SendRawTransaction(tx, true)
|
||||
}
|
||||
|
||||
// SendOutputsWithoutChange creates and sends a transaction that pays to the
|
||||
// specified outputs while observing the passed fee rate and ignoring a change
|
||||
// output. The passed fee rate should be expressed in sat/b.
|
||||
func (m *memWallet) SendOutputsWithoutChange(outputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount) (*chainhash.Hash, error) {
|
||||
|
||||
tx, err := m.CreateTransaction(outputs, feeRate, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m.rpc.SendRawTransaction(tx, true)
|
||||
}
|
||||
|
||||
// CreateTransaction returns a fully signed transaction paying to the specified
|
||||
// outputs while observing the desired fee rate. The passed fee rate should be
|
||||
// expressed in satoshis-per-byte. The transaction being created can optionally
|
||||
// include a change output indicated by the change boolean.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *memWallet) CreateTransaction(outputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount, change bool) (*wire.MsgTx, error) {
|
||||
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
tx := wire.NewMsgTx(wire.TxVersion)
|
||||
|
||||
// Tally up the total amount to be sent in order to perform coin
|
||||
// selection shortly below.
|
||||
var outputAmt btcutil.Amount
|
||||
for _, output := range outputs {
|
||||
outputAmt += btcutil.Amount(output.Value)
|
||||
tx.AddTxOut(output)
|
||||
}
|
||||
|
||||
// Attempt to fund the transaction with spendable utxos.
|
||||
if err := m.fundTx(tx, outputAmt, feeRate, change); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Populate all the selected inputs with valid sigScript for spending.
|
||||
// Along the way record all outputs being spent in order to avoid a
|
||||
// potential double spend.
|
||||
spentOutputs := make([]*utxo, 0, len(tx.TxIn))
|
||||
for i, txIn := range tx.TxIn {
|
||||
outPoint := txIn.PreviousOutPoint
|
||||
utxo := m.utxos[outPoint]
|
||||
|
||||
extendedKey, err := m.hdRoot.Child(utxo.keyIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privKey, err := extendedKey.ECPrivKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigScript, err := txscript.SignatureScript(tx, i, utxo.pkScript,
|
||||
txscript.SigHashAll, privKey, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txIn.SignatureScript = sigScript
|
||||
|
||||
spentOutputs = append(spentOutputs, utxo)
|
||||
}
|
||||
|
||||
// As these outputs are now being spent by this newly created
|
||||
// transaction, mark the outputs are "locked". This action ensures
|
||||
// these outputs won't be double spent by any subsequent transactions.
|
||||
// These locked outputs can be freed via a call to UnlockOutputs.
|
||||
for _, utxo := range spentOutputs {
|
||||
utxo.isLocked = true
|
||||
}
|
||||
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// UnlockOutputs unlocks any outputs which were previously locked due to
|
||||
// being selected to fund a transaction via the CreateTransaction method.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *memWallet) UnlockOutputs(inputs []*wire.TxIn) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
for _, input := range inputs {
|
||||
utxo, ok := m.utxos[input.PreviousOutPoint]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
utxo.isLocked = false
|
||||
}
|
||||
}
|
||||
|
||||
// ConfirmedBalance returns the confirmed balance of the wallet.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *memWallet) ConfirmedBalance() btcutil.Amount {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
|
||||
var balance btcutil.Amount
|
||||
for _, utxo := range m.utxos {
|
||||
// Prevent any immature or locked outputs from contributing to
|
||||
// the wallet's total confirmed balance.
|
||||
if !utxo.isMature(m.currentHeight) || utxo.isLocked {
|
||||
continue
|
||||
}
|
||||
|
||||
balance += utxo.value
|
||||
}
|
||||
|
||||
return balance
|
||||
}
|
||||
|
||||
// keyToAddr maps the passed private to corresponding p2pkh address.
|
||||
func keyToAddr(key *btcec.PrivateKey, net *chaincfg.Params) (btcutil.Address, error) {
|
||||
serializedKey := key.PubKey().SerializeCompressed()
|
||||
pubKeyAddr, err := btcutil.NewAddressPubKey(serializedKey, net)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pubKeyAddr.AddressPubKeyHash(), nil
|
||||
}
|
||||
287
vendor/github.com/btcsuite/btcd/integration/rpctest/node.go
generated
vendored
Normal file
287
vendor/github.com/btcsuite/btcd/integration/rpctest/node.go
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
// Copyright (c) 2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
rpc "github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// nodeConfig contains all the args, and data required to launch a btcd process
|
||||
// and connect the rpc client to it.
|
||||
type nodeConfig struct {
|
||||
rpcUser string
|
||||
rpcPass string
|
||||
listen string
|
||||
rpcListen string
|
||||
rpcConnect string
|
||||
dataDir string
|
||||
logDir string
|
||||
profile string
|
||||
debugLevel string
|
||||
extra []string
|
||||
prefix string
|
||||
|
||||
exe string
|
||||
endpoint string
|
||||
certFile string
|
||||
keyFile string
|
||||
certificates []byte
|
||||
}
|
||||
|
||||
// newConfig returns a newConfig with all default values.
|
||||
func newConfig(prefix, certFile, keyFile string, extra []string) (*nodeConfig, error) {
|
||||
btcdPath, err := btcdExecutablePath()
|
||||
if err != nil {
|
||||
btcdPath = "btcd"
|
||||
}
|
||||
|
||||
a := &nodeConfig{
|
||||
listen: "127.0.0.1:18555",
|
||||
rpcListen: "127.0.0.1:18556",
|
||||
rpcUser: "user",
|
||||
rpcPass: "pass",
|
||||
extra: extra,
|
||||
prefix: prefix,
|
||||
exe: btcdPath,
|
||||
endpoint: "ws",
|
||||
certFile: certFile,
|
||||
keyFile: keyFile,
|
||||
}
|
||||
if err := a.setDefaults(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// setDefaults sets the default values of the config. It also creates the
|
||||
// temporary data, and log directories which must be cleaned up with a call to
|
||||
// cleanup().
|
||||
func (n *nodeConfig) setDefaults() error {
|
||||
datadir, err := ioutil.TempDir("", n.prefix+"-data")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.dataDir = datadir
|
||||
logdir, err := ioutil.TempDir("", n.prefix+"-logs")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.logDir = logdir
|
||||
cert, err := ioutil.ReadFile(n.certFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.certificates = cert
|
||||
return nil
|
||||
}
|
||||
|
||||
// arguments returns an array of arguments that be used to launch the btcd
|
||||
// process.
|
||||
func (n *nodeConfig) arguments() []string {
|
||||
args := []string{}
|
||||
if n.rpcUser != "" {
|
||||
// --rpcuser
|
||||
args = append(args, fmt.Sprintf("--rpcuser=%s", n.rpcUser))
|
||||
}
|
||||
if n.rpcPass != "" {
|
||||
// --rpcpass
|
||||
args = append(args, fmt.Sprintf("--rpcpass=%s", n.rpcPass))
|
||||
}
|
||||
if n.listen != "" {
|
||||
// --listen
|
||||
args = append(args, fmt.Sprintf("--listen=%s", n.listen))
|
||||
}
|
||||
if n.rpcListen != "" {
|
||||
// --rpclisten
|
||||
args = append(args, fmt.Sprintf("--rpclisten=%s", n.rpcListen))
|
||||
}
|
||||
if n.rpcConnect != "" {
|
||||
// --rpcconnect
|
||||
args = append(args, fmt.Sprintf("--rpcconnect=%s", n.rpcConnect))
|
||||
}
|
||||
// --rpccert
|
||||
args = append(args, fmt.Sprintf("--rpccert=%s", n.certFile))
|
||||
// --rpckey
|
||||
args = append(args, fmt.Sprintf("--rpckey=%s", n.keyFile))
|
||||
if n.dataDir != "" {
|
||||
// --datadir
|
||||
args = append(args, fmt.Sprintf("--datadir=%s", n.dataDir))
|
||||
}
|
||||
if n.logDir != "" {
|
||||
// --logdir
|
||||
args = append(args, fmt.Sprintf("--logdir=%s", n.logDir))
|
||||
}
|
||||
if n.profile != "" {
|
||||
// --profile
|
||||
args = append(args, fmt.Sprintf("--profile=%s", n.profile))
|
||||
}
|
||||
if n.debugLevel != "" {
|
||||
// --debuglevel
|
||||
args = append(args, fmt.Sprintf("--debuglevel=%s", n.debugLevel))
|
||||
}
|
||||
args = append(args, n.extra...)
|
||||
return args
|
||||
}
|
||||
|
||||
// command returns the exec.Cmd which will be used to start the btcd process.
|
||||
func (n *nodeConfig) command() *exec.Cmd {
|
||||
return exec.Command(n.exe, n.arguments()...)
|
||||
}
|
||||
|
||||
// rpcConnConfig returns the rpc connection config that can be used to connect
|
||||
// to the btcd process that is launched via Start().
|
||||
func (n *nodeConfig) rpcConnConfig() rpc.ConnConfig {
|
||||
return rpc.ConnConfig{
|
||||
Host: n.rpcListen,
|
||||
Endpoint: n.endpoint,
|
||||
User: n.rpcUser,
|
||||
Pass: n.rpcPass,
|
||||
Certificates: n.certificates,
|
||||
DisableAutoReconnect: true,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the string representation of this nodeConfig.
|
||||
func (n *nodeConfig) String() string {
|
||||
return n.prefix
|
||||
}
|
||||
|
||||
// cleanup removes the tmp data and log directories.
|
||||
func (n *nodeConfig) cleanup() error {
|
||||
dirs := []string{
|
||||
n.logDir,
|
||||
n.dataDir,
|
||||
}
|
||||
var err error
|
||||
for _, dir := range dirs {
|
||||
if err = os.RemoveAll(dir); err != nil {
|
||||
log.Printf("Cannot remove dir %s: %v", dir, err)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// node houses the necessary state required to configure, launch, and manage a
|
||||
// btcd process.
|
||||
type node struct {
|
||||
config *nodeConfig
|
||||
|
||||
cmd *exec.Cmd
|
||||
pidFile string
|
||||
|
||||
dataDir string
|
||||
}
|
||||
|
||||
// newNode creates a new node instance according to the passed config. dataDir
|
||||
// will be used to hold a file recording the pid of the launched process, and
|
||||
// as the base for the log and data directories for btcd.
|
||||
func newNode(config *nodeConfig, dataDir string) (*node, error) {
|
||||
return &node{
|
||||
config: config,
|
||||
dataDir: dataDir,
|
||||
cmd: config.command(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// start creates a new btcd process, and writes its pid in a file reserved for
|
||||
// recording the pid of the launched process. This file can be used to
|
||||
// terminate the process in case of a hang, or panic. In the case of a failing
|
||||
// test case, or panic, it is important that the process be stopped via stop(),
|
||||
// otherwise, it will persist unless explicitly killed.
|
||||
func (n *node) start() error {
|
||||
if err := n.cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pid, err := os.Create(filepath.Join(n.dataDir,
|
||||
fmt.Sprintf("%s.pid", n.config)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.pidFile = pid.Name()
|
||||
if _, err = fmt.Fprintf(pid, "%d\n", n.cmd.Process.Pid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := pid.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// stop interrupts the running btcd process process, and waits until it exits
|
||||
// properly. On windows, interrupt is not supported, so a kill signal is used
|
||||
// instead
|
||||
func (n *node) stop() error {
|
||||
if n.cmd == nil || n.cmd.Process == nil {
|
||||
// return if not properly initialized
|
||||
// or error starting the process
|
||||
return nil
|
||||
}
|
||||
defer n.cmd.Wait()
|
||||
if runtime.GOOS == "windows" {
|
||||
return n.cmd.Process.Signal(os.Kill)
|
||||
}
|
||||
return n.cmd.Process.Signal(os.Interrupt)
|
||||
}
|
||||
|
||||
// cleanup cleanups process and args files. The file housing the pid of the
|
||||
// created process will be deleted, as well as any directories created by the
|
||||
// process.
|
||||
func (n *node) cleanup() error {
|
||||
if n.pidFile != "" {
|
||||
if err := os.Remove(n.pidFile); err != nil {
|
||||
log.Printf("unable to remove file %s: %v", n.pidFile,
|
||||
err)
|
||||
}
|
||||
}
|
||||
|
||||
return n.config.cleanup()
|
||||
}
|
||||
|
||||
// shutdown terminates the running btcd process, and cleans up all
|
||||
// file/directories created by node.
|
||||
func (n *node) shutdown() error {
|
||||
if err := n.stop(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.cleanup(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// genCertPair generates a key/cert pair to the paths provided.
|
||||
func genCertPair(certFile, keyFile string) error {
|
||||
org := "rpctest autogenerated cert"
|
||||
validUntil := time.Now().Add(10 * 365 * 24 * time.Hour)
|
||||
cert, key, err := btcutil.NewTLSCertPair(org, validUntil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write cert and key files.
|
||||
if err = ioutil.WriteFile(certFile, cert, 0666); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ioutil.WriteFile(keyFile, key, 0600); err != nil {
|
||||
os.Remove(certFile)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
500
vendor/github.com/btcsuite/btcd/integration/rpctest/rpc_harness.go
generated
vendored
Normal file
500
vendor/github.com/btcsuite/btcd/integration/rpctest/rpc_harness.go
generated
vendored
Normal file
@@ -0,0 +1,500 @@
|
||||
// Copyright (c) 2016-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// These constants define the minimum and maximum p2p and rpc port
|
||||
// numbers used by a test harness. The min port is inclusive while the
|
||||
// max port is exclusive.
|
||||
minPeerPort = 10000
|
||||
maxPeerPort = 35000
|
||||
minRPCPort = maxPeerPort
|
||||
maxRPCPort = 60000
|
||||
|
||||
// BlockVersion is the default block version used when generating
|
||||
// blocks.
|
||||
BlockVersion = 4
|
||||
)
|
||||
|
||||
var (
|
||||
// current number of active test nodes.
|
||||
numTestInstances = 0
|
||||
|
||||
// processID is the process ID of the current running process. It is
|
||||
// used to calculate ports based upon it when launching an rpc
|
||||
// harnesses. The intent is to allow multiple process to run in
|
||||
// parallel without port collisions.
|
||||
//
|
||||
// It should be noted however that there is still some small probability
|
||||
// that there will be port collisions either due to other processes
|
||||
// running or simply due to the stars aligning on the process IDs.
|
||||
processID = os.Getpid()
|
||||
|
||||
// testInstances is a private package-level slice used to keep track of
|
||||
// all active test harnesses. This global can be used to perform
|
||||
// various "joins", shutdown several active harnesses after a test,
|
||||
// etc.
|
||||
testInstances = make(map[string]*Harness)
|
||||
|
||||
// Used to protest concurrent access to above declared variables.
|
||||
harnessStateMtx sync.RWMutex
|
||||
)
|
||||
|
||||
// HarnessTestCase represents a test-case which utilizes an instance of the
|
||||
// Harness to exercise functionality.
|
||||
type HarnessTestCase func(r *Harness, t *testing.T)
|
||||
|
||||
// Harness fully encapsulates an active btcd process to provide a unified
|
||||
// platform for creating rpc driven integration tests involving btcd. The
|
||||
// active btcd node will typically be run in simnet mode in order to allow for
|
||||
// easy generation of test blockchains. The active btcd process is fully
|
||||
// managed by Harness, which handles the necessary initialization, and teardown
|
||||
// of the process along with any temporary directories created as a result.
|
||||
// Multiple Harness instances may be run concurrently, in order to allow for
|
||||
// testing complex scenarios involving multiple nodes. The harness also
|
||||
// includes an in-memory wallet to streamline various classes of tests.
|
||||
type Harness struct {
|
||||
// ActiveNet is the parameters of the blockchain the Harness belongs
|
||||
// to.
|
||||
ActiveNet *chaincfg.Params
|
||||
|
||||
Node *rpcclient.Client
|
||||
node *node
|
||||
handlers *rpcclient.NotificationHandlers
|
||||
|
||||
wallet *memWallet
|
||||
|
||||
testNodeDir string
|
||||
maxConnRetries int
|
||||
nodeNum int
|
||||
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// New creates and initializes new instance of the rpc test harness.
|
||||
// Optionally, websocket handlers and a specified configuration may be passed.
|
||||
// In the case that a nil config is passed, a default configuration will be
|
||||
// used.
|
||||
//
|
||||
// NOTE: This function is safe for concurrent access.
|
||||
func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers,
|
||||
extraArgs []string) (*Harness, error) {
|
||||
|
||||
harnessStateMtx.Lock()
|
||||
defer harnessStateMtx.Unlock()
|
||||
|
||||
// Add a flag for the appropriate network type based on the provided
|
||||
// chain params.
|
||||
switch activeNet.Net {
|
||||
case wire.MainNet:
|
||||
// No extra flags since mainnet is the default
|
||||
case wire.TestNet3:
|
||||
extraArgs = append(extraArgs, "--testnet")
|
||||
case wire.TestNet:
|
||||
extraArgs = append(extraArgs, "--regtest")
|
||||
case wire.SimNet:
|
||||
extraArgs = append(extraArgs, "--simnet")
|
||||
default:
|
||||
return nil, fmt.Errorf("rpctest.New must be called with one " +
|
||||
"of the supported chain networks")
|
||||
}
|
||||
|
||||
testDir, err := baseDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
harnessID := strconv.Itoa(numTestInstances)
|
||||
nodeTestData, err := ioutil.TempDir(testDir, "harness-"+harnessID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
certFile := filepath.Join(nodeTestData, "rpc.cert")
|
||||
keyFile := filepath.Join(nodeTestData, "rpc.key")
|
||||
if err := genCertPair(certFile, keyFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wallet, err := newMemWallet(activeNet, uint32(numTestInstances))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
miningAddr := fmt.Sprintf("--miningaddr=%s", wallet.coinbaseAddr)
|
||||
extraArgs = append(extraArgs, miningAddr)
|
||||
|
||||
config, err := newConfig("rpctest", certFile, keyFile, extraArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate p2p+rpc listening addresses.
|
||||
config.listen, config.rpcListen = generateListeningAddresses()
|
||||
|
||||
// Create the testing node bounded to the simnet.
|
||||
node, err := newNode(config, nodeTestData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeNum := numTestInstances
|
||||
numTestInstances++
|
||||
|
||||
if handlers == nil {
|
||||
handlers = &rpcclient.NotificationHandlers{}
|
||||
}
|
||||
|
||||
// If a handler for the OnFilteredBlock{Connected,Disconnected} callback
|
||||
// callback has already been set, then create a wrapper callback which
|
||||
// executes both the currently registered callback and the mem wallet's
|
||||
// callback.
|
||||
if handlers.OnFilteredBlockConnected != nil {
|
||||
obc := handlers.OnFilteredBlockConnected
|
||||
handlers.OnFilteredBlockConnected = func(height int32, header *wire.BlockHeader, filteredTxns []*btcutil.Tx) {
|
||||
wallet.IngestBlock(height, header, filteredTxns)
|
||||
obc(height, header, filteredTxns)
|
||||
}
|
||||
} else {
|
||||
// Otherwise, we can claim the callback ourselves.
|
||||
handlers.OnFilteredBlockConnected = wallet.IngestBlock
|
||||
}
|
||||
if handlers.OnFilteredBlockDisconnected != nil {
|
||||
obd := handlers.OnFilteredBlockDisconnected
|
||||
handlers.OnFilteredBlockDisconnected = func(height int32, header *wire.BlockHeader) {
|
||||
wallet.UnwindBlock(height, header)
|
||||
obd(height, header)
|
||||
}
|
||||
} else {
|
||||
handlers.OnFilteredBlockDisconnected = wallet.UnwindBlock
|
||||
}
|
||||
|
||||
h := &Harness{
|
||||
handlers: handlers,
|
||||
node: node,
|
||||
maxConnRetries: 20,
|
||||
testNodeDir: nodeTestData,
|
||||
ActiveNet: activeNet,
|
||||
nodeNum: nodeNum,
|
||||
wallet: wallet,
|
||||
}
|
||||
|
||||
// Track this newly created test instance within the package level
|
||||
// global map of all active test instances.
|
||||
testInstances[h.testNodeDir] = h
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// SetUp initializes the rpc test state. Initialization includes: starting up a
|
||||
// simnet node, creating a websockets client and connecting to the started
|
||||
// node, and finally: optionally generating and submitting a testchain with a
|
||||
// configurable number of mature coinbase outputs coinbase outputs.
|
||||
//
|
||||
// NOTE: This method and TearDown should always be called from the same
|
||||
// goroutine as they are not concurrent safe.
|
||||
func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error {
|
||||
// Start the btcd node itself. This spawns a new process which will be
|
||||
// managed
|
||||
if err := h.node.start(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.connectRPCClient(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.wallet.Start()
|
||||
|
||||
// Filter transactions that pay to the coinbase associated with the
|
||||
// wallet.
|
||||
filterAddrs := []btcutil.Address{h.wallet.coinbaseAddr}
|
||||
if err := h.Node.LoadTxFilter(true, filterAddrs, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure btcd properly dispatches our registered call-back for each new
|
||||
// block. Otherwise, the memWallet won't function properly.
|
||||
if err := h.Node.NotifyBlocks(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a test chain with the desired number of mature coinbase
|
||||
// outputs.
|
||||
if createTestChain && numMatureOutputs != 0 {
|
||||
numToGenerate := (uint32(h.ActiveNet.CoinbaseMaturity) +
|
||||
numMatureOutputs)
|
||||
_, err := h.Node.Generate(numToGenerate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Block until the wallet has fully synced up to the tip of the main
|
||||
// chain.
|
||||
_, height, err := h.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ticker := time.NewTicker(time.Millisecond * 100)
|
||||
for range ticker.C {
|
||||
walletHeight := h.wallet.SyncedHeight()
|
||||
if walletHeight == height {
|
||||
break
|
||||
}
|
||||
}
|
||||
ticker.Stop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// tearDown stops the running rpc test instance. All created processes are
|
||||
// killed, and temporary directories removed.
|
||||
//
|
||||
// This function MUST be called with the harness state mutex held (for writes).
|
||||
func (h *Harness) tearDown() error {
|
||||
if h.Node != nil {
|
||||
h.Node.Shutdown()
|
||||
}
|
||||
|
||||
if err := h.node.shutdown(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(h.testNodeDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delete(testInstances, h.testNodeDir)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TearDown stops the running rpc test instance. All created processes are
|
||||
// killed, and temporary directories removed.
|
||||
//
|
||||
// NOTE: This method and SetUp should always be called from the same goroutine
|
||||
// as they are not concurrent safe.
|
||||
func (h *Harness) TearDown() error {
|
||||
harnessStateMtx.Lock()
|
||||
defer harnessStateMtx.Unlock()
|
||||
|
||||
return h.tearDown()
|
||||
}
|
||||
|
||||
// connectRPCClient attempts to establish an RPC connection to the created btcd
|
||||
// process belonging to this Harness instance. If the initial connection
|
||||
// attempt fails, this function will retry h.maxConnRetries times, backing off
|
||||
// the time between subsequent attempts. If after h.maxConnRetries attempts,
|
||||
// we're not able to establish a connection, this function returns with an
|
||||
// error.
|
||||
func (h *Harness) connectRPCClient() error {
|
||||
var client *rpcclient.Client
|
||||
var err error
|
||||
|
||||
rpcConf := h.node.config.rpcConnConfig()
|
||||
for i := 0; i < h.maxConnRetries; i++ {
|
||||
if client, err = rpcclient.New(&rpcConf, h.handlers); err != nil {
|
||||
time.Sleep(time.Duration(i) * 50 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if client == nil {
|
||||
return fmt.Errorf("connection timeout")
|
||||
}
|
||||
|
||||
h.Node = client
|
||||
h.wallet.SetRPCClient(client)
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewAddress returns a fresh address spendable by the Harness' internal
|
||||
// wallet.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) NewAddress() (btcutil.Address, error) {
|
||||
return h.wallet.NewAddress()
|
||||
}
|
||||
|
||||
// ConfirmedBalance returns the confirmed balance of the Harness' internal
|
||||
// wallet.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) ConfirmedBalance() btcutil.Amount {
|
||||
return h.wallet.ConfirmedBalance()
|
||||
}
|
||||
|
||||
// SendOutputs creates, signs, and finally broadcasts a transaction spending
|
||||
// the harness' available mature coinbase outputs creating new outputs
|
||||
// according to targetOutputs.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) SendOutputs(targetOutputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount) (*chainhash.Hash, error) {
|
||||
|
||||
return h.wallet.SendOutputs(targetOutputs, feeRate)
|
||||
}
|
||||
|
||||
// SendOutputsWithoutChange creates and sends a transaction that pays to the
|
||||
// specified outputs while observing the passed fee rate and ignoring a change
|
||||
// output. The passed fee rate should be expressed in sat/b.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) SendOutputsWithoutChange(targetOutputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount) (*chainhash.Hash, error) {
|
||||
|
||||
return h.wallet.SendOutputsWithoutChange(targetOutputs, feeRate)
|
||||
}
|
||||
|
||||
// CreateTransaction returns a fully signed transaction paying to the specified
|
||||
// outputs while observing the desired fee rate. The passed fee rate should be
|
||||
// expressed in satoshis-per-byte. The transaction being created can optionally
|
||||
// include a change output indicated by the change boolean. Any unspent outputs
|
||||
// selected as inputs for the crafted transaction are marked as unspendable in
|
||||
// order to avoid potential double-spends by future calls to this method. If the
|
||||
// created transaction is cancelled for any reason then the selected inputs MUST
|
||||
// be freed via a call to UnlockOutputs. Otherwise, the locked inputs won't be
|
||||
// returned to the pool of spendable outputs.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) CreateTransaction(targetOutputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount, change bool) (*wire.MsgTx, error) {
|
||||
|
||||
return h.wallet.CreateTransaction(targetOutputs, feeRate, change)
|
||||
}
|
||||
|
||||
// UnlockOutputs unlocks any outputs which were previously marked as
|
||||
// unspendabe due to being selected to fund a transaction via the
|
||||
// CreateTransaction method.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) UnlockOutputs(inputs []*wire.TxIn) {
|
||||
h.wallet.UnlockOutputs(inputs)
|
||||
}
|
||||
|
||||
// RPCConfig returns the harnesses current rpc configuration. This allows other
|
||||
// potential RPC clients created within tests to connect to a given test
|
||||
// harness instance.
|
||||
func (h *Harness) RPCConfig() rpcclient.ConnConfig {
|
||||
return h.node.config.rpcConnConfig()
|
||||
}
|
||||
|
||||
// P2PAddress returns the harness' P2P listening address. This allows potential
|
||||
// peers (such as SPV peers) created within tests to connect to a given test
|
||||
// harness instance.
|
||||
func (h *Harness) P2PAddress() string {
|
||||
return h.node.config.listen
|
||||
}
|
||||
|
||||
// GenerateAndSubmitBlock creates a block whose contents include the passed
|
||||
// transactions and submits it to the running simnet node. For generating
|
||||
// blocks with only a coinbase tx, callers can simply pass nil instead of
|
||||
// transactions to be mined. Additionally, a custom block version can be set by
|
||||
// the caller. A blockVersion of -1 indicates that the current default block
|
||||
// version should be used. An uninitialized time.Time should be used for the
|
||||
// blockTime parameter if one doesn't wish to set a custom time.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32,
|
||||
blockTime time.Time) (*btcutil.Block, error) {
|
||||
return h.GenerateAndSubmitBlockWithCustomCoinbaseOutputs(txns,
|
||||
blockVersion, blockTime, []wire.TxOut{})
|
||||
}
|
||||
|
||||
// GenerateAndSubmitBlockWithCustomCoinbaseOutputs creates a block whose
|
||||
// contents include the passed coinbase outputs and transactions and submits
|
||||
// it to the running simnet node. For generating blocks with only a coinbase tx,
|
||||
// callers can simply pass nil instead of transactions to be mined.
|
||||
// Additionally, a custom block version can be set by the caller. A blockVersion
|
||||
// of -1 indicates that the current default block version should be used. An
|
||||
// uninitialized time.Time should be used for the blockTime parameter if one
|
||||
// doesn't wish to set a custom time. The mineTo list of outputs will be added
|
||||
// to the coinbase; this is not checked for correctness until the block is
|
||||
// submitted; thus, it is the caller's responsibility to ensure that the outputs
|
||||
// are correct. If the list is empty, the coinbase reward goes to the wallet
|
||||
// managed by the Harness.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs(
|
||||
txns []*btcutil.Tx, blockVersion int32, blockTime time.Time,
|
||||
mineTo []wire.TxOut) (*btcutil.Block, error) {
|
||||
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
|
||||
if blockVersion == -1 {
|
||||
blockVersion = BlockVersion
|
||||
}
|
||||
|
||||
prevBlockHash, prevBlockHeight, err := h.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mBlock, err := h.Node.GetBlock(prevBlockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prevBlock := btcutil.NewBlock(mBlock)
|
||||
prevBlock.SetHeight(prevBlockHeight)
|
||||
|
||||
// Create a new block including the specified transactions
|
||||
newBlock, err := CreateBlock(prevBlock, txns, blockVersion,
|
||||
blockTime, h.wallet.coinbaseAddr, mineTo, h.ActiveNet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Submit the block to the simnet node.
|
||||
if err := h.Node.SubmitBlock(newBlock, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newBlock, nil
|
||||
}
|
||||
|
||||
// generateListeningAddresses returns two strings representing listening
|
||||
// addresses designated for the current rpc test. If there haven't been any
|
||||
// test instances created, the default ports are used. Otherwise, in order to
|
||||
// support multiple test nodes running at once, the p2p and rpc port are
|
||||
// incremented after each initialization.
|
||||
func generateListeningAddresses() (string, string) {
|
||||
localhost := "127.0.0.1"
|
||||
|
||||
portString := func(minPort, maxPort int) string {
|
||||
port := minPort + numTestInstances + ((20 * processID) %
|
||||
(maxPort - minPort))
|
||||
return strconv.Itoa(port)
|
||||
}
|
||||
|
||||
p2p := net.JoinHostPort(localhost, portString(minPeerPort, maxPeerPort))
|
||||
rpc := net.JoinHostPort(localhost, portString(minRPCPort, maxRPCPort))
|
||||
return p2p, rpc
|
||||
}
|
||||
|
||||
// baseDir is the directory path of the temp directory for all rpctest files.
|
||||
func baseDir() (string, error) {
|
||||
dirPath := filepath.Join(os.TempDir(), "btcd", "rpctest")
|
||||
err := os.MkdirAll(dirPath, 0755)
|
||||
return dirPath, err
|
||||
}
|
||||
164
vendor/github.com/btcsuite/btcd/integration/rpctest/utils.go
generated
vendored
Normal file
164
vendor/github.com/btcsuite/btcd/integration/rpctest/utils.go
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
)
|
||||
|
||||
// JoinType is an enum representing a particular type of "node join". A node
|
||||
// join is a synchronization tool used to wait until a subset of nodes have a
|
||||
// consistent state with respect to an attribute.
|
||||
type JoinType uint8
|
||||
|
||||
const (
|
||||
// Blocks is a JoinType which waits until all nodes share the same
|
||||
// block height.
|
||||
Blocks JoinType = iota
|
||||
|
||||
// Mempools is a JoinType which blocks until all nodes have identical
|
||||
// mempool.
|
||||
Mempools
|
||||
)
|
||||
|
||||
// JoinNodes is a synchronization tool used to block until all passed nodes are
|
||||
// fully synced with respect to an attribute. This function will block for a
|
||||
// period of time, finally returning once all nodes are synced according to the
|
||||
// passed JoinType. This function be used to to ensure all active test
|
||||
// harnesses are at a consistent state before proceeding to an assertion or
|
||||
// check within rpc tests.
|
||||
func JoinNodes(nodes []*Harness, joinType JoinType) error {
|
||||
switch joinType {
|
||||
case Blocks:
|
||||
return syncBlocks(nodes)
|
||||
case Mempools:
|
||||
return syncMempools(nodes)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// syncMempools blocks until all nodes have identical mempools.
|
||||
func syncMempools(nodes []*Harness) error {
|
||||
poolsMatch := false
|
||||
|
||||
retry:
|
||||
for !poolsMatch {
|
||||
firstPool, err := nodes[0].Node.GetRawMempool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If all nodes have an identical mempool with respect to the
|
||||
// first node, then we're done. Otherwise, drop back to the top
|
||||
// of the loop and retry after a short wait period.
|
||||
for _, node := range nodes[1:] {
|
||||
nodePool, err := node.Node.GetRawMempool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(firstPool, nodePool) {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue retry
|
||||
}
|
||||
}
|
||||
|
||||
poolsMatch = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// syncBlocks blocks until all nodes report the same best chain.
|
||||
func syncBlocks(nodes []*Harness) error {
|
||||
blocksMatch := false
|
||||
|
||||
retry:
|
||||
for !blocksMatch {
|
||||
var prevHash *chainhash.Hash
|
||||
var prevHeight int32
|
||||
for _, node := range nodes {
|
||||
blockHash, blockHeight, err := node.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if prevHash != nil && (*blockHash != *prevHash ||
|
||||
blockHeight != prevHeight) {
|
||||
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue retry
|
||||
}
|
||||
prevHash, prevHeight = blockHash, blockHeight
|
||||
}
|
||||
|
||||
blocksMatch = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConnectNode establishes a new peer-to-peer connection between the "from"
|
||||
// harness and the "to" harness. The connection made is flagged as persistent,
|
||||
// therefore in the case of disconnects, "from" will attempt to reestablish a
|
||||
// connection to the "to" harness.
|
||||
func ConnectNode(from *Harness, to *Harness) error {
|
||||
peerInfo, err := from.Node.GetPeerInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numPeers := len(peerInfo)
|
||||
|
||||
targetAddr := to.node.config.listen
|
||||
if err := from.Node.AddNode(targetAddr, rpcclient.ANAdd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Block until a new connection has been established.
|
||||
peerInfo, err = from.Node.GetPeerInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for len(peerInfo) <= numPeers {
|
||||
peerInfo, err = from.Node.GetPeerInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TearDownAll tears down all active test harnesses.
|
||||
func TearDownAll() error {
|
||||
harnessStateMtx.Lock()
|
||||
defer harnessStateMtx.Unlock()
|
||||
|
||||
for _, harness := range testInstances {
|
||||
if err := harness.tearDown(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ActiveHarnesses returns a slice of all currently active test harnesses. A
|
||||
// test harness if considered "active" if it has been created, but not yet torn
|
||||
// down.
|
||||
func ActiveHarnesses() []*Harness {
|
||||
harnessStateMtx.RLock()
|
||||
defer harnessStateMtx.RUnlock()
|
||||
|
||||
activeNodes := make([]*Harness, 0, len(testInstances))
|
||||
for _, harness := range testInstances {
|
||||
activeNodes = append(activeNodes, harness)
|
||||
}
|
||||
|
||||
return activeNodes
|
||||
}
|
||||
127
vendor/github.com/btcsuite/btcd/peer/mruinvmap.go
generated
vendored
127
vendor/github.com/btcsuite/btcd/peer/mruinvmap.go
generated
vendored
@@ -1,127 +0,0 @@
|
||||
// Copyright (c) 2013-2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package peer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// mruInventoryMap provides a concurrency safe map that is limited to a maximum
|
||||
// number of items with eviction for the oldest entry when the limit is
|
||||
// exceeded.
|
||||
type mruInventoryMap struct {
|
||||
invMtx sync.Mutex
|
||||
invMap map[wire.InvVect]*list.Element // nearly O(1) lookups
|
||||
invList *list.List // O(1) insert, update, delete
|
||||
limit uint
|
||||
}
|
||||
|
||||
// String returns the map as a human-readable string.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) String() string {
|
||||
m.invMtx.Lock()
|
||||
defer m.invMtx.Unlock()
|
||||
|
||||
lastEntryNum := len(m.invMap) - 1
|
||||
curEntry := 0
|
||||
buf := bytes.NewBufferString("[")
|
||||
for iv := range m.invMap {
|
||||
buf.WriteString(fmt.Sprintf("%v", iv))
|
||||
if curEntry < lastEntryNum {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
curEntry++
|
||||
}
|
||||
buf.WriteString("]")
|
||||
|
||||
return fmt.Sprintf("<%d>%s", m.limit, buf.String())
|
||||
}
|
||||
|
||||
// Exists returns whether or not the passed inventory item is in the map.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) Exists(iv *wire.InvVect) bool {
|
||||
m.invMtx.Lock()
|
||||
_, exists := m.invMap[*iv]
|
||||
m.invMtx.Unlock()
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
// Add adds the passed inventory to the map and handles eviction of the oldest
|
||||
// item if adding the new item would exceed the max limit. Adding an existing
|
||||
// item makes it the most recently used item.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) Add(iv *wire.InvVect) {
|
||||
m.invMtx.Lock()
|
||||
defer m.invMtx.Unlock()
|
||||
|
||||
// When the limit is zero, nothing can be added to the map, so just
|
||||
// return.
|
||||
if m.limit == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// When the entry already exists move it to the front of the list
|
||||
// thereby marking it most recently used.
|
||||
if node, exists := m.invMap[*iv]; exists {
|
||||
m.invList.MoveToFront(node)
|
||||
return
|
||||
}
|
||||
|
||||
// Evict the least recently used entry (back of the list) if the the new
|
||||
// entry would exceed the size limit for the map. Also reuse the list
|
||||
// node so a new one doesn't have to be allocated.
|
||||
if uint(len(m.invMap))+1 > m.limit {
|
||||
node := m.invList.Back()
|
||||
lru := node.Value.(*wire.InvVect)
|
||||
|
||||
// Evict least recently used item.
|
||||
delete(m.invMap, *lru)
|
||||
|
||||
// Reuse the list node of the item that was just evicted for the
|
||||
// new item.
|
||||
node.Value = iv
|
||||
m.invList.MoveToFront(node)
|
||||
m.invMap[*iv] = node
|
||||
return
|
||||
}
|
||||
|
||||
// The limit hasn't been reached yet, so just add the new item.
|
||||
node := m.invList.PushFront(iv)
|
||||
m.invMap[*iv] = node
|
||||
}
|
||||
|
||||
// Delete deletes the passed inventory item from the map (if it exists).
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruInventoryMap) Delete(iv *wire.InvVect) {
|
||||
m.invMtx.Lock()
|
||||
if node, exists := m.invMap[*iv]; exists {
|
||||
m.invList.Remove(node)
|
||||
delete(m.invMap, *iv)
|
||||
}
|
||||
m.invMtx.Unlock()
|
||||
}
|
||||
|
||||
// newMruInventoryMap returns a new inventory map that is limited to the number
|
||||
// of entries specified by limit. When the number of entries exceeds the limit,
|
||||
// the oldest (least recently used) entry will be removed to make room for the
|
||||
// new entry.
|
||||
func newMruInventoryMap(limit uint) *mruInventoryMap {
|
||||
m := mruInventoryMap{
|
||||
invMap: make(map[wire.InvVect]*list.Element),
|
||||
invList: list.New(),
|
||||
limit: limit,
|
||||
}
|
||||
return &m
|
||||
}
|
||||
125
vendor/github.com/btcsuite/btcd/peer/mrunoncemap.go
generated
vendored
125
vendor/github.com/btcsuite/btcd/peer/mrunoncemap.go
generated
vendored
@@ -1,125 +0,0 @@
|
||||
// Copyright (c) 2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package peer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// mruNonceMap provides a concurrency safe map that is limited to a maximum
|
||||
// number of items with eviction for the oldest entry when the limit is
|
||||
// exceeded.
|
||||
type mruNonceMap struct {
|
||||
mtx sync.Mutex
|
||||
nonceMap map[uint64]*list.Element // nearly O(1) lookups
|
||||
nonceList *list.List // O(1) insert, update, delete
|
||||
limit uint
|
||||
}
|
||||
|
||||
// String returns the map as a human-readable string.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) String() string {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
lastEntryNum := len(m.nonceMap) - 1
|
||||
curEntry := 0
|
||||
buf := bytes.NewBufferString("[")
|
||||
for nonce := range m.nonceMap {
|
||||
buf.WriteString(fmt.Sprintf("%d", nonce))
|
||||
if curEntry < lastEntryNum {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
curEntry++
|
||||
}
|
||||
buf.WriteString("]")
|
||||
|
||||
return fmt.Sprintf("<%d>%s", m.limit, buf.String())
|
||||
}
|
||||
|
||||
// Exists returns whether or not the passed nonce is in the map.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) Exists(nonce uint64) bool {
|
||||
m.mtx.Lock()
|
||||
_, exists := m.nonceMap[nonce]
|
||||
m.mtx.Unlock()
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
// Add adds the passed nonce to the map and handles eviction of the oldest item
|
||||
// if adding the new item would exceed the max limit. Adding an existing item
|
||||
// makes it the most recently used item.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) Add(nonce uint64) {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
// When the limit is zero, nothing can be added to the map, so just
|
||||
// return.
|
||||
if m.limit == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// When the entry already exists move it to the front of the list
|
||||
// thereby marking it most recently used.
|
||||
if node, exists := m.nonceMap[nonce]; exists {
|
||||
m.nonceList.MoveToFront(node)
|
||||
return
|
||||
}
|
||||
|
||||
// Evict the least recently used entry (back of the list) if the the new
|
||||
// entry would exceed the size limit for the map. Also reuse the list
|
||||
// node so a new one doesn't have to be allocated.
|
||||
if uint(len(m.nonceMap))+1 > m.limit {
|
||||
node := m.nonceList.Back()
|
||||
lru := node.Value.(uint64)
|
||||
|
||||
// Evict least recently used item.
|
||||
delete(m.nonceMap, lru)
|
||||
|
||||
// Reuse the list node of the item that was just evicted for the
|
||||
// new item.
|
||||
node.Value = nonce
|
||||
m.nonceList.MoveToFront(node)
|
||||
m.nonceMap[nonce] = node
|
||||
return
|
||||
}
|
||||
|
||||
// The limit hasn't been reached yet, so just add the new item.
|
||||
node := m.nonceList.PushFront(nonce)
|
||||
m.nonceMap[nonce] = node
|
||||
}
|
||||
|
||||
// Delete deletes the passed nonce from the map (if it exists).
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (m *mruNonceMap) Delete(nonce uint64) {
|
||||
m.mtx.Lock()
|
||||
if node, exists := m.nonceMap[nonce]; exists {
|
||||
m.nonceList.Remove(node)
|
||||
delete(m.nonceMap, nonce)
|
||||
}
|
||||
m.mtx.Unlock()
|
||||
}
|
||||
|
||||
// newMruNonceMap returns a new nonce map that is limited to the number of
|
||||
// entries specified by limit. When the number of entries exceeds the limit,
|
||||
// the oldest (least recently used) entry will be removed to make room for the
|
||||
// new entry.
|
||||
func newMruNonceMap(limit uint) *mruNonceMap {
|
||||
m := mruNonceMap{
|
||||
nonceMap: make(map[uint64]*list.Element),
|
||||
nonceList: list.New(),
|
||||
limit: limit,
|
||||
}
|
||||
return &m
|
||||
}
|
||||
15
vendor/github.com/btcsuite/btcd/peer/peer.go
generated
vendored
15
vendor/github.com/btcsuite/btcd/peer/peer.go
generated
vendored
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/go-socks/socks"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/decred/dcrd/lru"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -82,7 +83,7 @@ var (
|
||||
|
||||
// sentNonces houses the unique nonces that are generated when pushing
|
||||
// version messages that are used to detect self connections.
|
||||
sentNonces = newMruNonceMap(50)
|
||||
sentNonces = lru.NewCache(50)
|
||||
|
||||
// allowSelfConns is only used to allow the tests to bypass the self
|
||||
// connection detecting and disconnect logic since they intentionally
|
||||
@@ -450,7 +451,7 @@ type Peer struct {
|
||||
|
||||
wireEncoding wire.MessageEncoding
|
||||
|
||||
knownInventory *mruInventoryMap
|
||||
knownInventory lru.Cache
|
||||
prevGetBlocksMtx sync.Mutex
|
||||
prevGetBlocksBegin *chainhash.Hash
|
||||
prevGetBlocksStop *chainhash.Hash
|
||||
@@ -1626,7 +1627,7 @@ out:
|
||||
|
||||
// Don't send inventory that became known after
|
||||
// the initial check.
|
||||
if p.knownInventory.Exists(iv) {
|
||||
if p.knownInventory.Contains(iv) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1832,7 +1833,7 @@ func (p *Peer) QueueMessageWithEncoding(msg wire.Message, doneChan chan<- struct
|
||||
func (p *Peer) QueueInventory(invVect *wire.InvVect) {
|
||||
// Don't add the inventory to the send queue if the peer is already
|
||||
// known to have it.
|
||||
if p.knownInventory.Exists(invVect) {
|
||||
if p.knownInventory.Contains(invVect) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1891,7 +1892,7 @@ func (p *Peer) readRemoteVersionMsg() error {
|
||||
}
|
||||
|
||||
// Detect self connections.
|
||||
if !allowSelfConns && sentNonces.Exists(msg.Nonce) {
|
||||
if !allowSelfConns && sentNonces.Contains(msg.Nonce) {
|
||||
return errors.New("disconnecting peer connected to self")
|
||||
}
|
||||
|
||||
@@ -2097,7 +2098,7 @@ func (p *Peer) negotiateInboundProtocol() error {
|
||||
return p.readRemoteVerAckMsg()
|
||||
}
|
||||
|
||||
// negotiateOutoundProtocol performs the negotiation protocol for an outbound
|
||||
// negotiateOutboundProtocol performs the negotiation protocol for an outbound
|
||||
// peer. The events should occur in the following order, otherwise an error is
|
||||
// returned:
|
||||
//
|
||||
@@ -2224,7 +2225,7 @@ func newPeerBase(origCfg *Config, inbound bool) *Peer {
|
||||
p := Peer{
|
||||
inbound: inbound,
|
||||
wireEncoding: wire.BaseEncoding,
|
||||
knownInventory: newMruInventoryMap(maxKnownInventory),
|
||||
knownInventory: lru.NewCache(maxKnownInventory),
|
||||
stallControl: make(chan stallControlMsg, 1), // nonblocking sync
|
||||
outputQueue: make(chan outMsg, outputBufferSize),
|
||||
sendQueue: make(chan outMsg, 1), // nonblocking sync
|
||||
|
||||
268
vendor/github.com/btcsuite/btcd/rpcclient/chain.go
generated
vendored
268
vendor/github.com/btcsuite/btcd/rpcclient/chain.go
generated
vendored
@@ -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()
|
||||
}
|
||||
|
||||
38
vendor/github.com/btcsuite/btcd/rpcclient/cookiefile.go
generated
vendored
Normal file
38
vendor/github.com/btcsuite/btcd/rpcclient/cookiefile.go
generated
vendored
Normal 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
|
||||
}
|
||||
2
vendor/github.com/btcsuite/btcd/rpcclient/doc.go
generated
vendored
2
vendor/github.com/btcsuite/btcd/rpcclient/doc.go
generated
vendored
@@ -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
|
||||
|
||||
133
vendor/github.com/btcsuite/btcd/rpcclient/infrastructure.go
generated
vendored
133
vendor/github.com/btcsuite/btcd/rpcclient/infrastructure.go
generated
vendored
@@ -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)
|
||||
|
||||
47
vendor/github.com/btcsuite/btcd/rpcclient/mining.go
generated
vendored
47
vendor/github.com/btcsuite/btcd/rpcclient/mining.go
generated
vendored
@@ -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
|
||||
|
||||
34
vendor/github.com/btcsuite/btcd/rpcclient/notify.go
generated
vendored
34
vendor/github.com/btcsuite/btcd/rpcclient/notify.go
generated
vendored
@@ -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 {
|
||||
|
||||
53
vendor/github.com/btcsuite/btcd/rpcclient/rawtransactions.go
generated
vendored
53
vendor/github.com/btcsuite/btcd/rpcclient/rawtransactions.go
generated
vendored
@@ -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) {
|
||||
|
||||
|
||||
166
vendor/github.com/btcsuite/btcd/rpcclient/wallet.go
generated
vendored
166
vendor/github.com/btcsuite/btcd/rpcclient/wallet.go
generated
vendored
@@ -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).
|
||||
|
||||
2
vendor/github.com/btcsuite/btcd/txscript/engine.go
generated
vendored
2
vendor/github.com/btcsuite/btcd/txscript/engine.go
generated
vendored
@@ -586,7 +586,7 @@ func (vm *Engine) checkPubKeyEncoding(pubKey []byte) error {
|
||||
if vm.hasFlag(ScriptVerifyWitnessPubKeyType) &&
|
||||
vm.isWitnessVersionActive(0) && !btcec.IsCompressedPubKey(pubKey) {
|
||||
|
||||
str := "only uncompressed keys are accepted post-segwit"
|
||||
str := "only compressed keys are accepted post-segwit"
|
||||
return scriptError(ErrWitnessPubKeyType, str)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user