Enable estimatefee rpc command.
This commit is contained in:
parent
1333ad7f78
commit
4fd446028f
6 changed files with 97 additions and 22 deletions
|
@ -12,9 +12,9 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/mining"
|
"github.com/roasbeef/btcd/mining"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO incorporate Alex Morcos' modifications to Gavin's initial model
|
// TODO incorporate Alex Morcos' modifications to Gavin's initial model
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/mining"
|
"github.com/roasbeef/btcd/mining"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newTestFeeEstimator creates a feeEstimator with some different parameters
|
// newTestFeeEstimator creates a feeEstimator with some different parameters
|
||||||
|
|
|
@ -557,6 +557,43 @@ func (c *Client) GetRawMempoolVerbose() (map[string]btcjson.GetRawMempoolVerbose
|
||||||
return c.GetRawMempoolVerboseAsync().Receive()
|
return c.GetRawMempoolVerboseAsync().Receive()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FutureEstimateFeeResult is a future promise to deliver the result of a
|
||||||
|
// EstimateFeeAsync RPC invocation (or an applicable error).
|
||||||
|
type FutureEstimateFeeResult chan *response
|
||||||
|
|
||||||
|
// Receive waits for the response promised by the future and returns the info
|
||||||
|
// provided by the server.
|
||||||
|
func (r FutureEstimateFeeResult) Receive() (float64, error) {
|
||||||
|
res, err := receiveFuture(r)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal result as a getinfo result object.
|
||||||
|
var fee float64
|
||||||
|
err = json.Unmarshal(res, &fee)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fee, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateFeeAsync returns an instance of a type that can be used to get the result
|
||||||
|
// of the RPC at some future time by invoking the Receive function on the
|
||||||
|
// returned instance.
|
||||||
|
//
|
||||||
|
// See EstimateFee for the blocking version and more details.
|
||||||
|
func (c *Client) EstimateFeeAsync(numBlocks int64) FutureEstimateFeeResult {
|
||||||
|
cmd := btcjson.NewEstimateFeeCmd(numBlocks)
|
||||||
|
return c.sendCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateFee provides an estimated fee in bitcoins per kilobyte.
|
||||||
|
func (c *Client) EstimateFee(numBlocks int64) (float64, error) {
|
||||||
|
return c.EstimateFeeAsync(numBlocks).Receive()
|
||||||
|
}
|
||||||
|
|
||||||
// FutureVerifyChainResult is a future promise to deliver the result of a
|
// FutureVerifyChainResult is a future promise to deliver the result of a
|
||||||
// VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync
|
// VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync
|
||||||
// invocation (or an applicable error).
|
// invocation (or an applicable error).
|
||||||
|
|
29
rpcserver.go
29
rpcserver.go
|
@ -132,6 +132,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
|
||||||
"debuglevel": handleDebugLevel,
|
"debuglevel": handleDebugLevel,
|
||||||
"decoderawtransaction": handleDecodeRawTransaction,
|
"decoderawtransaction": handleDecodeRawTransaction,
|
||||||
"decodescript": handleDecodeScript,
|
"decodescript": handleDecodeScript,
|
||||||
|
"estimatefee": handleEstimateFee,
|
||||||
"generate": handleGenerate,
|
"generate": handleGenerate,
|
||||||
"getaddednodeinfo": handleGetAddedNodeInfo,
|
"getaddednodeinfo": handleGetAddedNodeInfo,
|
||||||
"getbestblock": handleGetBestBlock,
|
"getbestblock": handleGetBestBlock,
|
||||||
|
@ -224,7 +225,6 @@ var rpcAskWallet = map[string]struct{}{
|
||||||
|
|
||||||
// Commands that are currently unimplemented, but should ultimately be.
|
// Commands that are currently unimplemented, but should ultimately be.
|
||||||
var rpcUnimplemented = map[string]struct{}{
|
var rpcUnimplemented = map[string]struct{}{
|
||||||
"estimatefee": {},
|
|
||||||
"estimatepriority": {},
|
"estimatepriority": {},
|
||||||
"getchaintips": {},
|
"getchaintips": {},
|
||||||
"getmempoolentry": {},
|
"getmempoolentry": {},
|
||||||
|
@ -254,6 +254,7 @@ var rpcLimited = map[string]struct{}{
|
||||||
"createrawtransaction": {},
|
"createrawtransaction": {},
|
||||||
"decoderawtransaction": {},
|
"decoderawtransaction": {},
|
||||||
"decodescript": {},
|
"decodescript": {},
|
||||||
|
"estimatefee": {},
|
||||||
"getbestblock": {},
|
"getbestblock": {},
|
||||||
"getbestblockhash": {},
|
"getbestblockhash": {},
|
||||||
"getblock": {},
|
"getblock": {},
|
||||||
|
@ -853,6 +854,28 @@ func handleDecodeScript(s *rpcServer, cmd interface{}, closeChan <-chan struct{}
|
||||||
return reply, nil
|
return reply, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleEstimateFee handles estimatefee commands.
|
||||||
|
func handleEstimateFee(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||||
|
c := cmd.(*btcjson.EstimateFeeCmd)
|
||||||
|
|
||||||
|
if s.cfg.FeeEstimator == nil {
|
||||||
|
return nil, errors.New("Fee estimation disabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.NumBlocks <= 0 {
|
||||||
|
return -1.0, errors.New("Parameter NumBlocks must be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
feeRate, err := s.cfg.FeeEstimator.EstimateFee(uint32(c.NumBlocks))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return -1.0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to satoshis per kb.
|
||||||
|
return float64(feeRate.ToSatoshiPerKb()), nil
|
||||||
|
}
|
||||||
|
|
||||||
// handleGenerate handles generate commands.
|
// handleGenerate handles generate commands.
|
||||||
func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||||
// Respond with an error if there are no addresses to pay the
|
// Respond with an error if there are no addresses to pay the
|
||||||
|
@ -4247,6 +4270,10 @@ type rpcserverConfig struct {
|
||||||
TxIndex *indexers.TxIndex
|
TxIndex *indexers.TxIndex
|
||||||
AddrIndex *indexers.AddrIndex
|
AddrIndex *indexers.AddrIndex
|
||||||
CfIndex *indexers.CfIndex
|
CfIndex *indexers.CfIndex
|
||||||
|
|
||||||
|
// The fee estimator keeps track of how long transactions are left in
|
||||||
|
// the mempool before they are mined into blocks.
|
||||||
|
FeeEstimator *mempool.FeeEstimator
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRPCServer returns a new instance of the rpcServer struct.
|
// newRPCServer returns a new instance of the rpcServer struct.
|
||||||
|
|
|
@ -115,6 +115,15 @@ var helpDescsEnUS = map[string]string{
|
||||||
"decodescript--synopsis": "Returns a JSON object with information about the provided hex-encoded script.",
|
"decodescript--synopsis": "Returns a JSON object with information about the provided hex-encoded script.",
|
||||||
"decodescript-hexscript": "Hex-encoded script",
|
"decodescript-hexscript": "Hex-encoded script",
|
||||||
|
|
||||||
|
// EstimateFeeCmd help.
|
||||||
|
"estimatefee--synopsis": "Estimate the fee per kilobyte in satoshis " +
|
||||||
|
"required for a transaction to be mined before a certain number of " +
|
||||||
|
"blocks have been generated.",
|
||||||
|
"estimatefee-numblocks": "The maximum number of blocks which can be " +
|
||||||
|
"generated before the transaction is mined.",
|
||||||
|
"estimatefee--result0": "Estimated fee per kilobyte in satoshis for a block to " +
|
||||||
|
"be mined in the next NumBlocks blocks.",
|
||||||
|
|
||||||
// GenerateCmd help
|
// GenerateCmd help
|
||||||
"generate--synopsis": "Generates a set number of blocks (simnet or regtest only) and returns a JSON\n" +
|
"generate--synopsis": "Generates a set number of blocks (simnet or regtest only) and returns a JSON\n" +
|
||||||
" array of their hashes.",
|
" array of their hashes.",
|
||||||
|
@ -663,6 +672,7 @@ var rpcResultTypes = map[string][]interface{}{
|
||||||
"debuglevel": {(*string)(nil), (*string)(nil)},
|
"debuglevel": {(*string)(nil), (*string)(nil)},
|
||||||
"decoderawtransaction": {(*btcjson.TxRawDecodeResult)(nil)},
|
"decoderawtransaction": {(*btcjson.TxRawDecodeResult)(nil)},
|
||||||
"decodescript": {(*btcjson.DecodeScriptResult)(nil)},
|
"decodescript": {(*btcjson.DecodeScriptResult)(nil)},
|
||||||
|
"estimatefee": {(*float64)(nil)},
|
||||||
"generate": {(*[]string)(nil)},
|
"generate": {(*[]string)(nil)},
|
||||||
"getaddednodeinfo": {(*[]string)(nil), (*[]btcjson.GetAddedNodeInfoResult)(nil)},
|
"getaddednodeinfo": {(*[]string)(nil), (*[]btcjson.GetAddedNodeInfoResult)(nil)},
|
||||||
"getbestblock": {(*btcjson.GetBestBlockResult)(nil)},
|
"getbestblock": {(*btcjson.GetBestBlockResult)(nil)},
|
||||||
|
|
|
@ -2586,6 +2586,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||||
TxIndex: s.txIndex,
|
TxIndex: s.txIndex,
|
||||||
AddrIndex: s.addrIndex,
|
AddrIndex: s.addrIndex,
|
||||||
CfIndex: s.cfIndex,
|
CfIndex: s.cfIndex,
|
||||||
|
FeeEstimator: feeEstimator,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Reference in a new issue