Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generatetoaddress and estimatesmartfee RPC calls #1500

Merged
merged 1 commit into from
Mar 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions btcjson/btcdextcmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions btcjson/btcdextcmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,24 @@ func TestBtcdExtCmds(t *testing.T) {
NumBlocks: 1,
},
},
{
name: "generatetoaddress",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("generatetoaddress", 1, "1Address")
},
staticCmd: func() interface{} {
return btcjson.NewGenerateToAddressCmd(1, "1Address", nil)
},
marshalled: `{"jsonrpc":"1.0","method":"generatetoaddress","params":[1,"1Address"],"id":1}`,
unmarshalled: &btcjson.GenerateToAddressCmd{
NumBlocks: 1,
Address: "1Address",
MaxTries: func() *int64 {
var i int64 = 1000000
return &i
}(),
},
},
{
name: "getbestblock",
newCmd: func() (interface{}, error) {
Expand Down
8 changes: 8 additions & 0 deletions btcjson/chainsvrresults.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,3 +624,11 @@ 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"`
}
25 changes: 25 additions & 0 deletions btcjson/walletsvrcmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -662,6 +686,7 @@ 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)
Expand Down
28 changes: 28 additions & 0 deletions btcjson/walletsvrcmds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,34 @@ func TestWalletSvrCmds(t *testing.T) {
NumBlocks: 6,
},
},
{
name: "estimatesmartfee - no mode",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("estimatesmartfee", 6)
},
staticCmd: func() interface{} {
return btcjson.NewEstimateSmartFeeCmd(6, nil)
},
marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6],"id":1}`,
unmarshalled: &btcjson.EstimateSmartFeeCmd{
ConfTarget: 6,
EstimateMode: &btcjson.EstimateModeConservative,
},
},
{
name: "estimatesmartfee - economical mode",
newCmd: func() (interface{}, error) {
return btcjson.NewCmd("estimatesmartfee", 6, btcjson.EstimateModeEconomical)
},
staticCmd: func() interface{} {
return btcjson.NewEstimateSmartFeeCmd(6, &btcjson.EstimateModeEconomical)
},
marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6,"ECONOMICAL"],"id":1}`,
unmarshalled: &btcjson.EstimateSmartFeeCmd{
ConfTarget: 6,
EstimateMode: &btcjson.EstimateModeEconomical,
},
},
{
name: "estimatepriority",
newCmd: func() (interface{}, error) {
Expand Down
35 changes: 35 additions & 0 deletions rpcclient/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,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).
Expand Down
47 changes: 47 additions & 0 deletions rpcclient/mining.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down