diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 832eaf80f1c..b9b41c34913 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -23,7 +23,7 @@ #include #include #include - +#include #include #include @@ -95,12 +95,15 @@ public Q_SLOTS: private: interfaces::Node& m_node; + bool executeConsoleGenerate(const std::vector& parsed_command, const WalletModel* wallet_model, const bool exec_help = false); + void executeConsoleHelpGenerate(); bool executeConsoleHelpConsole(const std::vector& parsed_command, const WalletModel* wallet_model, const bool exec_help = false); bool executeConsoleOnlyCommand(const std::string& command, const WalletModel* wallet_model); // std::map mapping strings to methods member of RPCExecutor class // Keys must be strings with commands and (optionally) parameters in "canonical" form (separated by single space) // Keys should match the beggining of user input commands (user commands can have more parameters than the key) std::map&, const WalletModel*, const bool)> m_method_map{ + {"generate", &RPCExecutor::executeConsoleGenerate}, {"help-console", &RPCExecutor::executeConsoleHelpConsole}}; }; @@ -468,6 +471,73 @@ void RPCExecutor::request(const QString &command, const WalletModel* wallet_mode } } +/** + * @brief Executes the console-only command "generate". + * @param parsed_command A vector of strings with command and parameters, usually generated by RPCExecutor::parseHelper + * @param wallet_model WalletModel to use for the command + * @return True if the command was executed, false otherwise. + */ +bool RPCExecutor::executeConsoleGenerate(const std::vector& parsed_command, const WalletModel* wallet_model, const bool exec_help) +{ + // Initialize default parameters if missing + const std::string nblocks{parsed_command.size() > 1 ? parsed_command[1] : "1"}; + const std::string maxtries{parsed_command.size() > 2 ? parsed_command[2] : "1000000"}; + + // Handle some special cases... + // Default to console help generate if more than 3 parameters or if "help generate" was called + if (parsed_command.size() > 3 || exec_help) { + executeConsoleHelpGenerate(); + return true; + } + // Fail if we are on mainnet, to avoid generating addresses for blocks that will not be generated + if (Params().GetChainType() == ChainType::MAIN) { + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: generate is not available on mainnet")); + return true; + } + // Fail if parameters are not positive integers + const auto nblocks_value{ToIntegral(nblocks)}; + const auto maxtries_value{ToIntegral(maxtries)}; + if (!nblocks_value || !maxtries_value || nblocks_value.value() <= 0 || maxtries_value.value() <= 0) { + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: parameters must be positive integers")); + return true; + } + + // Catch the console-only generate command with 2 or less parameters before RPC call is executed . + std::string blocks; + std::string address; + if (!RPCConsole::RPCExecuteCommandLine(m_node, address, "getnewaddress\n", /*pstrFilteredOut=*/nullptr, wallet_model)) { + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: could not generate new address")); + } else { + if (!RPCConsole::RPCExecuteCommandLine(m_node, blocks, "generatetoaddress " + nblocks + " " + address + " " + maxtries + "\n", /*pstrFilteredOut=*/nullptr, wallet_model)) { + Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: could not generate blocks")); + } else { + UniValue result{UniValue::VOBJ}; + UniValue blocks_object{UniValue::VOBJ}; + blocks_object.read(blocks); + result.pushKV("address", address); + result.pushKV("blocks", blocks_object); + Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString("\n" + result.write(2) + "\n\n")); + } + } + return true; +} + +/** + * @brief Executes the console-only command "help generate". + */ +void RPCExecutor::executeConsoleHelpGenerate() +{ + // Execute the console-only "help generate" command. + Q_EMIT reply(RPCConsole::CMD_REPLY, + QString("\n" + "Generate blocks, equivalent to RPC getnewaddress followed by RPC generatetoaddress.\n" + "Optional positive integer arguments are number of blocks to generate and maximum iterations to try.\n" + "Equivalent to RPC generatetoaddress nblocks and maxtries arguments.\n" + " example: generate\n" + " example: generate 4\n" + " example: generate 3 6000\n\n")); +} + /** * @brief Executes the console-only command "help-console". * @param parsed_command A vector of strings with command and parameters, usually generated by RPCExecutor::parseHelper