rpc: Handle keypool exhaustion separately in `generate` RPC

A prior commit moved the `IsValidMinerAddress()` call before the keypool
exhaustion check, but `IsValidMinerAddress()` internally handles keypool
exhaustion. We now check it explicitly first to retain the prior error
behaviour (as checked in the `keypool` RPC test).
This commit is contained in:
Jack Grigg 2022-03-03 21:10:44 +00:00
parent 613534bbb3
commit 8b90d32972
1 changed files with 12 additions and 7 deletions

View File

@ -190,17 +190,22 @@ UniValue generate(const UniValue& params, bool fHelp)
GetMainSignals().AddressForMining(maybeMinerAddress);
// Throw an error if no address valid for mining was provided.
if (!(maybeMinerAddress.has_value() && std::visit(IsValidMinerAddress(), maybeMinerAddress.value()))) {
if (!maybeMinerAddress.has_value()) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "No miner address available (mining requires a wallet or -mineraddress)");
} else {
// Detect and handle keypool exhaustion separately from IsValidMinerAddress().
auto resv = std::get_if<boost::shared_ptr<CReserveScript>>(&maybeMinerAddress.value());
if (resv && !resv->get()) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
}
// Catch any other invalid miner address issues.
if (!std::visit(IsValidMinerAddress(), maybeMinerAddress.value())) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Miner address is invalid");
}
}
auto minerAddress = maybeMinerAddress.value();
// If the keypool is exhausted, no script is returned at all. Catch this.
auto resv = std::get_if<boost::shared_ptr<CReserveScript>>(&minerAddress);
if (resv && !resv->get()) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
}
{ // Don't keep cs_main locked
LOCK(cs_main);
nHeightStart = chainActive.Height();