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"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/mining"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||
"github.com/roasbeef/btcd/mining"
|
||||
"github.com/roasbeef/btcutil"
|
||||
)
|
||||
|
||||
// TODO incorporate Alex Morcos' modifications to Gavin's initial model
|
||||
|
|
|
@ -8,10 +8,10 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/mining"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||
"github.com/roasbeef/btcd/mining"
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
"github.com/roasbeef/btcutil"
|
||||
)
|
||||
|
||||
// newTestFeeEstimator creates a feeEstimator with some different parameters
|
||||
|
|
|
@ -557,6 +557,43 @@ func (c *Client) GetRawMempoolVerbose() (map[string]btcjson.GetRawMempoolVerbose
|
|||
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
|
||||
// VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync
|
||||
// invocation (or an applicable error).
|
||||
|
|
29
rpcserver.go
29
rpcserver.go
|
@ -132,6 +132,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
|
|||
"debuglevel": handleDebugLevel,
|
||||
"decoderawtransaction": handleDecodeRawTransaction,
|
||||
"decodescript": handleDecodeScript,
|
||||
"estimatefee": handleEstimateFee,
|
||||
"generate": handleGenerate,
|
||||
"getaddednodeinfo": handleGetAddedNodeInfo,
|
||||
"getbestblock": handleGetBestBlock,
|
||||
|
@ -224,7 +225,6 @@ var rpcAskWallet = map[string]struct{}{
|
|||
|
||||
// Commands that are currently unimplemented, but should ultimately be.
|
||||
var rpcUnimplemented = map[string]struct{}{
|
||||
"estimatefee": {},
|
||||
"estimatepriority": {},
|
||||
"getchaintips": {},
|
||||
"getmempoolentry": {},
|
||||
|
@ -254,6 +254,7 @@ var rpcLimited = map[string]struct{}{
|
|||
"createrawtransaction": {},
|
||||
"decoderawtransaction": {},
|
||||
"decodescript": {},
|
||||
"estimatefee": {},
|
||||
"getbestblock": {},
|
||||
"getbestblockhash": {},
|
||||
"getblock": {},
|
||||
|
@ -853,6 +854,28 @@ func handleDecodeScript(s *rpcServer, cmd interface{}, closeChan <-chan struct{}
|
|||
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.
|
||||
func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||
// Respond with an error if there are no addresses to pay the
|
||||
|
@ -4247,6 +4270,10 @@ type rpcserverConfig struct {
|
|||
TxIndex *indexers.TxIndex
|
||||
AddrIndex *indexers.AddrIndex
|
||||
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.
|
||||
|
|
|
@ -115,6 +115,15 @@ var helpDescsEnUS = map[string]string{
|
|||
"decodescript--synopsis": "Returns a JSON object with information about the provided 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
|
||||
"generate--synopsis": "Generates a set number of blocks (simnet or regtest only) and returns a JSON\n" +
|
||||
" array of their hashes.",
|
||||
|
@ -663,6 +672,7 @@ var rpcResultTypes = map[string][]interface{}{
|
|||
"debuglevel": {(*string)(nil), (*string)(nil)},
|
||||
"decoderawtransaction": {(*btcjson.TxRawDecodeResult)(nil)},
|
||||
"decodescript": {(*btcjson.DecodeScriptResult)(nil)},
|
||||
"estimatefee": {(*float64)(nil)},
|
||||
"generate": {(*[]string)(nil)},
|
||||
"getaddednodeinfo": {(*[]string)(nil), (*[]btcjson.GetAddedNodeInfoResult)(nil)},
|
||||
"getbestblock": {(*btcjson.GetBestBlockResult)(nil)},
|
||||
|
|
29
server.go
29
server.go
|
@ -2572,20 +2572,21 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
|||
}
|
||||
|
||||
s.rpcServer, err = newRPCServer(&rpcserverConfig{
|
||||
Listeners: rpcListeners,
|
||||
StartupTime: s.startupTime,
|
||||
ConnMgr: &rpcConnManager{&s},
|
||||
SyncMgr: &rpcSyncMgr{&s, s.syncManager},
|
||||
TimeSource: s.timeSource,
|
||||
Chain: s.chain,
|
||||
ChainParams: chainParams,
|
||||
DB: db,
|
||||
TxMemPool: s.txMemPool,
|
||||
Generator: blockTemplateGenerator,
|
||||
CPUMiner: s.cpuMiner,
|
||||
TxIndex: s.txIndex,
|
||||
AddrIndex: s.addrIndex,
|
||||
CfIndex: s.cfIndex,
|
||||
Listeners: rpcListeners,
|
||||
StartupTime: s.startupTime,
|
||||
ConnMgr: &rpcConnManager{&s},
|
||||
SyncMgr: &rpcSyncMgr{&s, s.syncManager},
|
||||
TimeSource: s.timeSource,
|
||||
Chain: s.chain,
|
||||
ChainParams: chainParams,
|
||||
DB: db,
|
||||
TxMemPool: s.txMemPool,
|
||||
Generator: blockTemplateGenerator,
|
||||
CPUMiner: s.cpuMiner,
|
||||
TxIndex: s.txIndex,
|
||||
AddrIndex: s.addrIndex,
|
||||
CfIndex: s.cfIndex,
|
||||
FeeEstimator: feeEstimator,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in a new issue