Merge pull request #4826 from UdjinM6/de_generate

backport 14468, 14631, 15492
This commit is contained in:
UdjinM6 2022-05-02 22:05:53 +03:00 committed by GitHub
commit a356832882
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 93 additions and 138 deletions

View File

@ -0,0 +1,15 @@
Wallet `generate` RPC method deprecated
---------------------------------------
The wallet's `generate` RPC method has been deprecated and will be fully
removed in v0.19.
`generate` is only used for testing. The RPC call reaches across multiple
subsystems (wallet and mining), so is deprecated to simplify the wallet-node
interface. Projects that are using `generate` for testing purposes should
transition to using the `generatetoaddress` call, which does not require or use
the wallet component. Calling `generatetoaddress` with an address returned by
`getnewaddress` gives the same functionality as the old `generate` method.
To continue using `generate` in v0.18, restart bitcoind with the
`-deprecatedrpc=generate` configuration.

View File

@ -0,0 +1,11 @@
Deprecated or removed RPCs
--------------------------
- The wallet's `generate` RPC method was deprecated in v0.18 and has now
been fully removed. This RPC is only used for
testing, but its implementation reached across multiple subsystems
(wallet and mining), so it has been removed to simplify the
wallet-node interface. Projects that are using `generate` for testing
purposes should transition to using the `generatetoaddress` RPC, which
does not require or use the wallet component. Calling
`generatetoaddress` with an address returned by the `getnewaddress`
RPC gives the same functionality as the old `generate` RPC.

View File

@ -29,8 +29,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "setmocktime", 0, "timestamp" },
{ "mockscheduler", 0, "delta_time" },
#if ENABLE_MINER
{ "generate", 0, "nblocks" },
{ "generate", 1, "maxtries" },
{ "generatetoaddress", 0, "nblocks" },
{ "generatetoaddress", 2, "maxtries" },
{ "generatetodescriptor", 0, "num_blocks" },

View File

@ -263,6 +263,8 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
RPCExamples{
"\nGenerate 11 blocks to myaddress\n"
+ HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
+ "If you are running the Dash Core wallet, you can get a new address to send the newly generated coins to with:\n"
+ HelpExampleCli("getnewaddress", "")
},
}.ToString());

View File

@ -13,7 +13,6 @@
#include <policy/feerate.h>
#include <policy/fees.h>
#include <rpc/blockchain.h>
#include <rpc/mining.h>
#include <rpc/rawtransaction_util.h>
#include <rpc/server.h>
#include <rpc/util.h>
@ -3326,61 +3325,6 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
return SignTransaction(mtx, request.params[1], pwallet, coins, false, request.params[2]);
}
#if ENABLE_MINER
UniValue generate(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
throw std::runtime_error(
RPCHelpMan{"generate",
"\nMine up to nblocks blocks immediately (before the RPC call returns) to an address in the wallet.\n",
{
{"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."},
{"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."},
},
RPCResult{
"[ blockhashes ] (json array) hashes of blocks generated\n"
},
RPCExamples{
"\nGenerate 11 blocks\n"
+ HelpExampleCli("generate", "11")
},
}.ToString());
}
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
int num_generate = request.params[0].get_int();
uint64_t max_tries = 1000000;
if (!request.params[1].isNull()) {
max_tries = request.params[1].get_int();
}
std::shared_ptr<CReserveScript> coinbase_script;
pwallet->GetScriptForMining(coinbase_script);
// If the keypool is exhausted, no script is returned at all. Catch this.
if (!coinbase_script) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
}
//throw an error if no script was provided
if (coinbase_script->reserveScript.empty()) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available");
}
const CTxMemPool& mempool = EnsureMemPool();
return generateBlocks(mempool, coinbase_script, num_generate, max_tries, true);
}
#else
UniValue generate(const JSONRPCRequest& request)
{
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This call is not available because RPC miner isn't compiled");
}
#endif //ENABLE_MINING
static UniValue rescanblockchain(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2) {
@ -3984,11 +3928,6 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
#if ENABLE_MINER
{ "generating", "generate", &generate, {"nblocks","maxtries"} },
#else
{ "hidden", "generate", &generate, {"nblocks","maxtries"} }, // Hidden as it isn't functional, just an error to let people know if miner isn't compiled
#endif //ENABLE_MINER
{ "hidden", "instantsendtoaddress", &instantsendtoaddress, {} },
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options"} },
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },

View File

@ -4772,17 +4772,6 @@ void CWallet::MarkReserveKeysAsUsed(int64_t keypool_id)
}
}
void CWallet::GetScriptForMining(std::shared_ptr<CReserveScript> &script)
{
std::shared_ptr<CReserveKey> rKey = std::make_shared<CReserveKey>(this);
CPubKey pubkey;
if (!rKey->GetReservedKey(pubkey, false))
return;
script = rKey;
script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
}
void CWallet::LockCoin(const COutPoint& output)
{
AssertLockHeld(cs_wallet);

View File

@ -1177,8 +1177,6 @@ public:
bool DelAddressBook(const CTxDestination& address);
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
{
AssertLockHeld(cs_wallet);

View File

@ -35,8 +35,8 @@ class AddressIndexTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[0], 2)
connect_nodes(self.nodes[0], 3)
self.sync_all()
self.import_deterministic_coinbase_privkeys()
def run_test(self):
self.log.info("Test that settings can't be changed without -reindex...")

View File

@ -74,6 +74,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
def setup_network(self):
self.add_nodes(self.num_nodes, extra_args=self.extra_args)
self.start_nodes()
self.import_deterministic_coinbase_privkeys()
# Leave them unconnected, we'll use submitblock directly in this test
def restart_node(self, node_index, expected_tip):

View File

@ -35,6 +35,7 @@ class DIP3Test(BitcoinTestFramework):
self.disable_mocktime()
self.add_nodes(1)
self.start_controller_node()
self.import_deterministic_coinbase_privkeys()
def start_controller_node(self):
self.log.info("starting controller node")

View File

@ -147,6 +147,9 @@ class EstimateFeeTest(BitcoinTestFramework):
# (17k is room enough for 110 or so transactions)
# Node2 is a stingy miner, that
# produces too small blocks (room for only 55 or so transactions)
self.start_nodes()
self.import_deterministic_coinbase_privkeys()
self.stop_nodes()
def transact_and_mine(self, numblocks, mining_node):
min_fee = Decimal("0.0001")
@ -174,11 +177,6 @@ class EstimateFeeTest(BitcoinTestFramework):
newmem.append(utx)
self.memutxo = newmem
def import_deterministic_coinbase_privkeys(self):
self.start_nodes()
super().import_deterministic_coinbase_privkeys()
self.stop_nodes()
def run_test(self):
self.log.info("This test is time consuming, please be patient")
self.log.info("Splitting inputs so we can generate tx's")

View File

@ -105,6 +105,8 @@ class PruneTest(BitcoinTestFramework):
def setup_nodes(self):
self.add_nodes(self.num_nodes, self.extra_args)
self.start_nodes()
for n in self.nodes:
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase', rescan=False)
def create_big_chain(self):
# Start by creating some coinbases we can spend later

View File

@ -37,8 +37,8 @@ class SpentIndexTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[0], 2)
connect_nodes(self.nodes[0], 3)
self.sync_all()
self.import_deterministic_coinbase_privkeys()
def run_test(self):
self.log.info("Test that settings can't be changed without -reindex...")

View File

@ -35,8 +35,8 @@ class TxIndexTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[0], 2)
connect_nodes(self.nodes[0], 3)
self.sync_all()
self.import_deterministic_coinbase_privkeys()
def run_test(self):
self.log.info("Mining blocks...")

View File

@ -73,6 +73,7 @@ class ZMQTest (BitcoinTestFramework):
]
self.add_nodes(self.num_nodes, self.extra_args)
self.start_nodes()
self.import_deterministic_coinbase_privkeys()
def run_test(self):
try:

View File

@ -43,8 +43,8 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
disconnect_nodes(self.nodes[1], 2)
def setup_network(self):
super(NodeNetworkLimitedTest, self).setup_network()
self.disconnect_all()
self.add_nodes(self.num_nodes, self.extra_args)
self.start_nodes()
def run_test(self):
node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())

View File

@ -4,21 +4,26 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test deprecation of RPC calls."""
from test_framework.test_framework import BitcoinTestFramework
# from test_framework.util import assert_raises_rpc_error
class DeprecatedRpcTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
self.extra_args = [[], ["-deprecatedrpc=validateaddress"]]
self.extra_args = [[], []]
def run_test(self):
# This test should be used to verify correct behaviour of deprecated
# RPC methods with and without the -deprecatedrpc flags. For example:
#
# self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses")
# assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()])
# self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
pass
# In set_test_params:
# self.extra_args = [[], ["-deprecatedrpc=generate"]]
#
# In run_test:
# self.log.info("Test generate RPC")
# assert_raises_rpc_error(-32, 'The wallet generate rpc method is deprecated', self.nodes[0].rpc.generate, 1)
# self.nodes[1].generate(1)
self.log.info("No tested deprecated RPC methods")
if __name__ == '__main__':
DeprecatedRpcTest().main()

View File

@ -230,7 +230,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.skip_test_if_missing_module()
self.setup_chain()
self.setup_network()
self.import_deterministic_coinbase_privkeys()
self.run_test()
success = TestStatus.PASSED
except JSONRPCException:
@ -353,11 +352,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
extra_args = self.extra_args
self.add_nodes(self.num_nodes, extra_args)
self.start_nodes()
self.import_deterministic_coinbase_privkeys()
def import_deterministic_coinbase_privkeys(self):
if self.setup_clean_chain:
return
for n in self.nodes:
try:
n.getwalletinfo()
@ -365,7 +362,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
assert str(e).startswith('Method not found')
continue
n.importprivkey(n.get_deterministic_priv_key().key)
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase')
def run_test(self):
"""Tests must override this method to define test logic"""
@ -925,6 +922,7 @@ class DashTestFramework(BitcoinTestFramework):
self.log.info("Creating and starting controller node")
self.add_nodes(1, extra_args=[self.extra_args[0]])
self.start_node(0)
self.import_deterministic_coinbase_privkeys()
required_balance = MASTERNODE_COLLATERAL * self.mn_count + 1
self.log.info("Generating %d coins" % required_balance)
while self.nodes[0].getbalance() < required_balance:
@ -945,6 +943,7 @@ class DashTestFramework(BitcoinTestFramework):
self.prepare_masternodes()
self.prepare_datadirs()
self.start_masternodes()
self.import_deterministic_coinbase_privkeys()
# non-masternodes where disconnected from the control node during prepare_datadirs,
# let's reconnect them back to make sure they receive updates

View File

@ -264,6 +264,10 @@ class TestNode():
time.sleep(1.0 / poll_per_s)
self._raise_assertion_error("Unable to connect to dashd")
def generate(self, nblocks, maxtries=1000000):
self.log.debug("TestNode.generate() dispatches `generate` call to `generatetoaddress`")
return self.generatetoaddress(nblocks=nblocks, address=self.get_deterministic_priv_key().address, maxtries=maxtries)
def get_wallet_rpc(self, wallet_name):
if self.use_cli:
return self.cli("-rpcwallet={}".format(wallet_name))

View File

@ -99,7 +99,7 @@ class ToolWalletTest(BitcoinTestFramework):
HD (hd seed available): no
Keypool Size: 1
Transactions: 0
Address Book: 0
Address Book: 1
''')
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
@ -114,7 +114,7 @@ class ToolWalletTest(BitcoinTestFramework):
HD (hd seed available): yes
Keypool Size: 2
Transactions: 0
Address Book: 0
Address Book: 1
''')
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
timestamp_after = self.wallet_timestamp()
@ -151,9 +151,9 @@ class ToolWalletTest(BitcoinTestFramework):
===========
Encrypted: no
HD (hd seed available): yes
Keypool Size: 1
Keypool Size: 2
Transactions: 1
Address Book: 0
Address Book: 1
''')
self.assert_tool_output(out, '-wallet=wallet.dat', 'info')
shasum_after = self.wallet_shasum()

View File

@ -31,10 +31,9 @@ class WalletTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def setup_network(self):
self.add_nodes(4, self.extra_args)
self.start_node(0)
self.start_node(1)
self.start_node(2)
self.setup_nodes()
# Only need nodes 0-2 running at start of test
self.stop_node(3)
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 2)
connect_nodes(self.nodes[0], 2)

View File

@ -22,6 +22,7 @@ class WalletHDTest(BitcoinTestFramework):
def setup_network(self):
self.add_nodes(self.num_nodes, self.extra_args)
self.start_nodes()
self.import_deterministic_coinbase_privkeys()
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

View File

@ -135,16 +135,14 @@ class ImportRescanTest(BitcoinTestFramework):
# Import keys with pruning disabled
self.start_nodes(extra_args=[[]] * self.num_nodes)
super().import_deterministic_coinbase_privkeys()
for n in self.nodes:
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase')
self.stop_nodes()
self.start_nodes()
for i in range(1, self.num_nodes):
connect_nodes(self.nodes[i], 0)
def import_deterministic_coinbase_privkeys(self):
pass
def run_test(self):
# Create one transaction on node 0 with a unique amount for
# each possible type of wallet import RPC.

View File

@ -49,11 +49,10 @@ class KeyPoolTest(BitcoinTestFramework):
time.sleep(1.1)
assert_equal(nodes[0].getwalletinfo()["unlocked_until"], 0)
# drain them by mining
nodes[0].generate(1)
nodes[0].generate(1)
nodes[0].generate(1)
assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].generate, 1)
# drain the keypool
for _ in range(3):
nodes[0].getnewaddress()
assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].getnewaddress)
if __name__ == '__main__':
KeyPoolTest().main()

View File

@ -11,7 +11,7 @@ import time
from test_framework.authproxy import JSONRPCException
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
from test_framework.util import assert_equal, assert_raises_rpc_error
class KeyPoolTest(BitcoinTestFramework):
@ -90,15 +90,10 @@ class KeyPoolTest(BitcoinTestFramework):
time.sleep(1.1)
assert_equal(nodes[0].getwalletinfo()["unlocked_until"], 0)
# drain them by mining
nodes[0].generate(1)
nodes[0].generate(1)
nodes[0].generate(1)
try:
nodes[0].generate(1)
raise AssertionError('Keypool should be exhausted after three addesses')
except JSONRPCException as e:
assert e.error['code']==-12
# drain the keypool
for _ in range(3):
nodes[0].getnewaddress()
assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].getnewaddress)
nodes[0].walletpassphrase('test', 100)
nodes[0].keypoolrefill(100)

View File

@ -29,8 +29,8 @@ class WalletLabelsTest(BitcoinTestFramework):
# Note each time we call generate, all generated coins go into
# the same address, so we call twice to get two addresses w/500 each
node.generate(1)
node.generate(101)
node.generatetoaddress(nblocks=1, address=node.getnewaddress(label='coinbase'))
node.generatetoaddress(nblocks=101, address=node.getnewaddress(label='coinbase'))
assert_equal(node.getbalance(), 1000)
# there should be 2 address groups
@ -42,8 +42,9 @@ class WalletLabelsTest(BitcoinTestFramework):
linked_addresses = set()
for address_group in address_groups:
assert_equal(len(address_group), 1)
assert_equal(len(address_group[0]), 2)
assert_equal(len(address_group[0]), 3)
assert_equal(address_group[0][1], 500)
assert_equal(address_group[0][2], 'coinbase')
linked_addresses.add(address_group[0][0])
# send 500 from each address to a third address not in this wallet
@ -79,7 +80,7 @@ class WalletLabelsTest(BitcoinTestFramework):
label.verify(node)
# Check all labels are returned by listlabels.
assert_equal(node.listlabels(), [label.name for label in labels])
assert_equal(node.listlabels(), sorted(['coinbase'] + [label.name for label in labels]))
# Send a transaction to each label.
for label in labels:

View File

@ -18,11 +18,6 @@ class ReceivedByTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
def import_deterministic_coinbase_privkeys(self):
assert_equal(0, len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True)))
super().import_deterministic_coinbase_privkeys()
self.num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True))
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
self.skip_if_no_cli()
@ -32,6 +27,9 @@ class ReceivedByTest(BitcoinTestFramework):
self.nodes[0].generate(1)
sync_blocks(self.nodes)
# save the number of coinbase reward addresses so far
num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True))
self.log.info("listreceivedbyaddress Test")
# Send from node 0 to 1
@ -77,7 +75,7 @@ class ReceivedByTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, addlocked=True, include_empty=True, include_watchonly=True, address_filter="bamboozling")
# Another address receive money
res = self.nodes[1].listreceivedbyaddress(0, True, True, True)
assert_equal(len(res), 2 + self.num_cb_reward_addresses) # Right now 2 entries
assert_equal(len(res), 2 + num_cb_reward_addresses) # Right now 2 entries
other_addr = self.nodes[1].getnewaddress()
txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1)
self.nodes[0].generate(1)
@ -94,7 +92,7 @@ class ReceivedByTest(BitcoinTestFramework):
assert_equal(len(res), 1)
# Should be two entries though without filter
res = self.nodes[1].listreceivedbyaddress(0, True, True, True)
assert_equal(len(res), 3 + self.num_cb_reward_addresses) # Became 3 entries
assert_equal(len(res), 3 + num_cb_reward_addresses) # Became 3 entries
# Not on random addr
other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr

View File

@ -135,7 +135,7 @@ class MultiWalletTest(BitcoinTestFramework):
self.start_node(0, ['-wallet=w4', '-wallet=w5'])
assert_equal(set(node.listwallets()), {"w4", "w5"})
w5 = wallet("w5")
w5.generate(1)
node.generatetoaddress(nblocks=1, address=w5.getnewaddress())
# now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded
os.rename(wallet_dir2, wallet_dir())
@ -159,7 +159,7 @@ class MultiWalletTest(BitcoinTestFramework):
wallet_bad = wallet("bad")
# check wallet names and balances
wallets[0].generate(1)
node.generatetoaddress(nblocks=1, address=wallets[0].getnewaddress())
for wallet_name, wallet in zip(wallet_names, wallets):
info = wallet.getwalletinfo()
assert_equal(info['immature_balance'], 500 if wallet is wallets[0] else 0)
@ -172,7 +172,7 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo)
w1, w2, w3, w4, *_ = wallets
w1.generate(101)
node.generatetoaddress(nblocks=101, address=w1.getnewaddress())
assert_equal(w1.getbalance(), 1000)
assert_equal(w2.getbalance(), 0)
assert_equal(w3.getbalance(), 0)
@ -181,7 +181,7 @@ class MultiWalletTest(BitcoinTestFramework):
w1.sendtoaddress(w2.getnewaddress(), 1)
w1.sendtoaddress(w3.getnewaddress(), 2)
w1.sendtoaddress(w4.getnewaddress(), 3)
w1.generate(1)
node.generatetoaddress(nblocks=1, address=w1.getnewaddress())
assert_equal(w2.getbalance(), 1)
assert_equal(w3.getbalance(), 2)
assert_equal(w4.getbalance(), 3)

View File

@ -28,6 +28,7 @@ class WalletUpgradeToHDTest(BitcoinTestFramework):
def setup_network(self):
self.add_nodes(self.num_nodes)
self.start_nodes()
self.import_deterministic_coinbase_privkeys()
def recover_non_hd(self):
self.log.info("Recover non-HD wallet to check different upgrade paths")