Skip to content

Commit cab94cc

Browse files
committed
Merge #16943: test: Add generatetodescriptor RPC
fa144e6 rpc: Add generatetodescriptor (MarcoFalke) Pull request description: The existing `generatetoaddress` RPC can only generate to scriptPubKeys that can be represented by an address. However, raw scripts (such as `OP_TRUE`) or P2PK can not be represented by an address, which complicates testing. ACKs for top commit: laanwj: ACK fa144e6 Tree-SHA512: aee934ab7e33f07c81f3b4c8ec23e7b6ddf63a1f4b86051af0bd76b75d8da1f51627cc682e5c6e42582340ca576bbf8ff724bdd43f87128ccecfa91e52d30ae7
2 parents 341e8d3 + fa144e6 commit cab94cc

File tree

4 files changed

+50
-3
lines changed

4 files changed

+50
-3
lines changed

src/rpc/client.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
3030
{ "utxoupdatepsbt", 1, "descriptors" },
3131
{ "generatetoaddress", 0, "nblocks" },
3232
{ "generatetoaddress", 2, "maxtries" },
33+
{ "generatetodescriptor", 0, "num_blocks" },
34+
{ "generatetodescriptor", 2, "maxtries" },
3335
{ "getnetworkhashps", 0, "nblocks" },
3436
{ "getnetworkhashps", 1, "height" },
3537
{ "sendtoaddress", 1, "amount" },

src/rpc/mining.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
#include <rpc/blockchain.h>
2020
#include <rpc/server.h>
2121
#include <rpc/util.h>
22+
#include <script/descriptor.h>
2223
#include <script/script.h>
24+
#include <script/signingprovider.h>
2325
#include <shutdown.h>
2426
#include <txmempool.h>
2527
#include <univalue.h>
@@ -141,6 +143,47 @@ static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, ui
141143
return blockHashes;
142144
}
143145

146+
static UniValue generatetodescriptor(const JSONRPCRequest& request)
147+
{
148+
RPCHelpMan{
149+
"generatetodescriptor",
150+
"\nMine blocks immediately to a specified descriptor (before the RPC call returns)\n",
151+
{
152+
{"num_blocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."},
153+
{"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor to send the newly generated bitcoin to."},
154+
{"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."},
155+
},
156+
RPCResult{
157+
"[ blockhashes ] (array) hashes of blocks generated\n"},
158+
RPCExamples{
159+
"\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
160+
}
161+
.Check(request);
162+
163+
const int num_blocks{request.params[0].get_int()};
164+
const int64_t max_tries{request.params[2].isNull() ? 1000000 : request.params[2].get_int()};
165+
166+
FlatSigningProvider key_provider;
167+
std::string error;
168+
const auto desc = Parse(request.params[1].get_str(), key_provider, error, /* require_checksum = */ false);
169+
if (!desc) {
170+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
171+
}
172+
if (desc->IsRange()) {
173+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?");
174+
}
175+
176+
FlatSigningProvider provider;
177+
std::vector<CScript> coinbase_script;
178+
if (!desc->Expand(0, key_provider, coinbase_script, provider)) {
179+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
180+
}
181+
182+
CHECK_NONFATAL(coinbase_script.size() == 1);
183+
184+
return generateBlocks(coinbase_script.at(0), num_blocks, max_tries);
185+
}
186+
144187
static UniValue generatetoaddress(const JSONRPCRequest& request)
145188
{
146189
RPCHelpMan{"generatetoaddress",
@@ -962,6 +1005,7 @@ static const CRPCCommand commands[] =
9621005

9631006

9641007
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
1008+
{ "generating", "generatetodescriptor", &generatetodescriptor, {"num_blocks","descriptor","maxtries"} },
9651009

9661010
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
9671011

test/functional/rpc_invalidateblock.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"""Test the invalidateblock RPC."""
66

77
from test_framework.test_framework import BitcoinTestFramework
8-
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
8+
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR
99
from test_framework.util import (
1010
assert_equal,
1111
connect_nodes,
@@ -62,7 +62,7 @@ def run_test(self):
6262
wait_until(lambda: self.nodes[1].getblockcount() == 4, timeout=5)
6363

6464
self.log.info("Verify that we reconsider all ancestors as well")
65-
blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE)
65+
blocks = self.nodes[1].generatetodescriptor(10, ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR)
6666
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
6767
# Invalidate the two blocks at the tip
6868
self.nodes[1].invalidateblock(blocks[-1])
@@ -74,7 +74,7 @@ def run_test(self):
7474
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
7575

7676
self.log.info("Verify that we reconsider all descendants")
77-
blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE)
77+
blocks = self.nodes[1].generatetodescriptor(10, ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR)
7878
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
7979
# Invalidate the two blocks at the tip
8080
self.nodes[1].invalidateblock(blocks[-2])

test/functional/test_framework/address.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from . import segwit_addr
1313

1414
ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
15+
ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97'
1516

1617

1718
class AddressType(enum.Enum):

0 commit comments

Comments
 (0)