diff --git a/src/cpp/daemon/py_monero_daemon.cpp b/src/cpp/daemon/py_monero_daemon.cpp index c8f8cf5..1acd9fb 100644 --- a/src/cpp/daemon/py_monero_daemon.cpp +++ b/src/cpp/daemon/py_monero_daemon.cpp @@ -712,15 +712,6 @@ void PyMoneroDaemonRpc::stop() { check_response_status(response); } -void PyMoneroDaemonRpc::stop_process() { - if (m_child_process && m_child_process->running()) { - m_child_process->terminate(); - } - if (m_output_thread.joinable()) { - m_output_thread.join(); - } -} - std::shared_ptr PyMoneroDaemonRpc::wait_for_next_block_header() { // use mutex and condition variable to wait for block boost::mutex temp; @@ -798,89 +789,5 @@ void PyMoneroDaemonRpc::check_response_status(std::shared_ptr& cmd) { - if (cmd.empty()) throw PyMoneroError("Must provide at least a path to monerod"); - boost::process::environment env = boost::this_process::environment(); - env["LANG"] = "en_US.UTF-8"; - - m_child_process = std::make_unique( - boost::process::exe = cmd[0], - boost::process::args = std::vector(cmd.begin() + 1, cmd.end()), - boost::process::std_out > m_out_pipe, - boost::process::std_err > m_err_pipe, - env - ); - - std::istream& out_stream = m_out_pipe; - std::istream& err_straem = m_err_pipe; - std::ostringstream captured_output; - std::string line; - std::string uri_; - std::string username_; - std::string password_; - std::string zmq_uri_; - bool started = false; - - while (std::getline(out_stream, line)) { - std::cerr << "[monero-rpc] " << line << std::endl; - captured_output << line << "\n"; - - std::string uri; - std::regex re("Binding on ([0-9.]+).*:(\\d+)"); - std::smatch match; - if (std::regex_search(line, match, re) && match.size() >= 3) { - std::string host = match[1]; - std::string port = match[2]; - bool ssl = false; - - auto it = std::find(cmd.begin(), cmd.end(), "--rpc-ssl"); - if (it != cmd.end() && it + 1 != cmd.end()) { - ssl = (it[1] == "enabled"); - } - - uri_ = (ssl ? "https://" : "http://") + host + ":" + port; - } - - if (line.find("Starting p2p net loop") != std::string::npos) { - m_output_thread = std::thread([this]() { - std::istream& out_stream_bg = m_out_pipe; - std::string line_bg; - while (std::getline(out_stream_bg, line_bg)) { - std::cerr << "[monero-rpc] " << line_bg << std::endl; - } - }); - started = true; - break; - } - } - - if (!started) { - if (std::getline(err_straem, line)) { - captured_output << line << "\n"; - } - - throw PyMoneroError("Failed to start monerod:\n" + captured_output.str()); - } - - auto it = std::find(cmd.begin(), cmd.end(), "--rpc-login"); - if (it != cmd.end() && it + 1 != cmd.end()) { - std::string login = *(it + 1); - auto sep = login.find(':'); - if (sep != std::string::npos) { - username_ = login.substr(0, sep); - password_ = login.substr(sep + 1); - } - } - - it = std::find(cmd.begin(), cmd.end(), "--zmq-pub"); - if (it != cmd.end() && it + 1 != cmd.end()) { - zmq_uri_ = *(it + 1); - } - - m_rpc = std::make_shared(uri_, username_, password_, zmq_uri_); - if (!m_rpc->m_uri->empty()) m_rpc->check_connection(); -} - PyMoneroDaemonRpc::~PyMoneroDaemonRpc() { - stop_process(); } diff --git a/src/cpp/daemon/py_monero_daemon.h b/src/cpp/daemon/py_monero_daemon.h index 210d0b9..3e277ab 100644 --- a/src/cpp/daemon/py_monero_daemon.h +++ b/src/cpp/daemon/py_monero_daemon.h @@ -173,8 +173,6 @@ class PyMoneroDaemonRpc : public PyMoneroDaemonDefault { if (!uri.empty()) m_rpc->check_connection(); } - PyMoneroDaemonRpc(const std::vector& cmd); - ~PyMoneroDaemonRpc(); std::shared_ptr get_rpc_connection() const; @@ -236,7 +234,6 @@ class PyMoneroDaemonRpc : public PyMoneroDaemonDefault { std::shared_ptr download_update(const std::string& path) override; std::shared_ptr download_update() override; void stop() override; - void stop_process(); std::shared_ptr wait_for_next_block_header(); static void check_response_status(std::shared_ptr response); static void check_response_status(std::shared_ptr response); @@ -244,10 +241,6 @@ class PyMoneroDaemonRpc : public PyMoneroDaemonDefault { protected: std::shared_ptr m_rpc; std::shared_ptr m_poller; - std::unique_ptr m_child_process; - boost::process::ipstream m_out_pipe; - boost::process::ipstream m_err_pipe; - std::thread m_output_thread; std::shared_ptr get_bandwidth_limits(); std::shared_ptr set_bandwidth_limits(int up, int down); diff --git a/src/cpp/daemon/py_monero_daemon_model.h b/src/cpp/daemon/py_monero_daemon_model.h index 2da75d5..6a63abd 100644 --- a/src/cpp/daemon/py_monero_daemon_model.h +++ b/src/cpp/daemon/py_monero_daemon_model.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -980,10 +979,10 @@ class PyMoneroConnectionManagerListener : public monero_connection_manager_liste public: void on_connection_changed(std::shared_ptr &connection) override { PYBIND11_OVERRIDE_PURE( - void, // Return type - monero_connection_manager_listener, // C++ base class - on_connection_changed, // Method name - connection // Arguments + void, + monero_connection_manager_listener, + on_connection_changed, + connection ); } }; diff --git a/src/cpp/py_monero.cpp b/src/cpp/py_monero.cpp index 8a9a097..9593229 100644 --- a/src/cpp/py_monero.cpp +++ b/src/cpp/py_monero.cpp @@ -1417,7 +1417,6 @@ PYBIND11_MODULE(monero, m) { // monero_daemon_rpc py_monero_daemon_rpc .def(py::init<>()) - .def(py::init&>(), py::arg("cmd")) .def(py::init>(), py::arg("rpc")) .def(py::init(), py::arg("uri"), py::arg("username") = "", py::arg("password") = "") .def("get_rpc_connection", [](const PyMoneroDaemonRpc& self) { @@ -1425,9 +1424,6 @@ PYBIND11_MODULE(monero, m) { }) .def("is_connected", [](PyMoneroDaemonRpc& self) { MONERO_CATCH_AND_RETHROW(self.is_connected()); - }) - .def("stop_process", [](PyMoneroDaemonRpc& self) { - MONERO_CATCH_AND_RETHROW(self.stop_process()); }); // monero_wallet @@ -2024,12 +2020,8 @@ PYBIND11_MODULE(monero, m) { // monero_wallet_rpc py_monero_wallet_rpc - .def(py::init&>(), py::arg("cmd")) .def(py::init>(), py::arg("rpc_connection")) .def(py::init(), py::arg("uri") = "", py::arg("username") = "", py::arg("password") = "") - .def("stop_process", [](PyMoneroWalletRpc& self) { - MONERO_CATCH_AND_RETHROW(self.stop_process()); - }) .def("create_wallet", [](PyMoneroWalletRpc& self, const std::shared_ptr config) { try { self.create_wallet(config); diff --git a/src/cpp/wallet/py_monero_wallet.cpp b/src/cpp/wallet/py_monero_wallet.cpp index e2e428b..0bb5c2e 100644 --- a/src/cpp/wallet/py_monero_wallet.cpp +++ b/src/cpp/wallet/py_monero_wallet.cpp @@ -338,92 +338,7 @@ bool PyMoneroWalletPoller::check_for_changed_balances() { return false; } -PyMoneroWalletRpc::PyMoneroWalletRpc(const std::vector& cmd) { - if (cmd.empty()) throw std::runtime_error("Must provide at least a path to monerod"); - boost::process::environment env = boost::this_process::environment(); - env["LANG"] = "en_US.UTF-8"; - - m_child_process = std::make_unique( - boost::process::exe = cmd[0], - boost::process::args = std::vector(cmd.begin() + 1, cmd.end()), - boost::process::std_out > m_out_pipe, - boost::process::std_err > m_err_pipe, - env - ); - - std::istream& out_stream = m_out_pipe; - std::istream& err_straem = m_err_pipe; - std::ostringstream captured_output; - std::string line; - std::string uri_; - std::string username_; - std::string password_; - std::string zmq_uri_; - bool started = false; - - while (std::getline(out_stream, line)) { - std::cerr << "[wallet-rpc] " << line << std::endl; - captured_output << line << "\n"; - - std::string uri; - std::regex re("Binding on ([0-9.]+).*:(\\d+)"); - std::smatch match; - if (std::regex_search(line, match, re) && match.size() >= 3) { - std::string host = match[1]; - std::string port = match[2]; - bool ssl = false; - - auto it = std::find(cmd.begin(), cmd.end(), "--rpc-ssl"); - if (it != cmd.end() && it + 1 != cmd.end()) { - ssl = (it[1] == "enabled"); - } - - uri_ = (ssl ? "https://" : "http://") + host + ":" + port; - } - - if (line.find("Starting wallet RPC server") != std::string::npos) { - m_output_thread = std::thread([this]() { - std::istream& out_stream_bg = m_out_pipe; - std::string line_bg; - while (std::getline(out_stream_bg, line_bg)) { - std::cerr << "[wallet-rpc] " << line_bg << std::endl; - } - }); - started = true; - break; - } - } - - if (!started) { - if (std::getline(err_straem, line)) { - captured_output << line << "\n"; - } - - throw PyMoneroError("Failed to start monero-wallet-rpc:\n" + captured_output.str()); - } - - auto it = std::find(cmd.begin(), cmd.end(), "--rpc-login"); - if (it != cmd.end() && it + 1 != cmd.end()) { - std::string login = *(it + 1); - auto sep = login.find(':'); - if (sep != std::string::npos) { - username_ = login.substr(0, sep); - password_ = login.substr(sep + 1); - } - } - - it = std::find(cmd.begin(), cmd.end(), "--zmq-pub"); - if (it != cmd.end() && it + 1 != cmd.end()) { - zmq_uri_ = *(it + 1); - } - - // Init addressCache, ecc. - m_rpc = std::make_shared(uri_, username_, password_, zmq_uri_); - if (!m_rpc->m_uri->empty()) m_rpc->check_connection(); -} - PyMoneroWalletRpc::~PyMoneroWalletRpc() { - stop_process(); } boost::optional PyMoneroWalletRpc::get_rpc_connection() const { @@ -516,15 +431,6 @@ void PyMoneroWalletRpc::stop() { std::shared_ptr response = m_rpc->send_json_request(request); } -void PyMoneroWalletRpc::stop_process() { - if (m_child_process && m_child_process->running()) { - m_child_process->terminate(); - } - if (m_output_thread.joinable()) { - m_output_thread.join(); - } -} - bool PyMoneroWalletRpc::is_view_only() const { try { std::string key = "mnemonic"; diff --git a/src/cpp/wallet/py_monero_wallet.h b/src/cpp/wallet/py_monero_wallet.h index 6275c3c..15b7271 100644 --- a/src/cpp/wallet/py_monero_wallet.h +++ b/src/cpp/wallet/py_monero_wallet.h @@ -635,8 +635,6 @@ class PyMoneroWalletRpc : public PyMoneroWallet { if (!m_rpc->m_uri->empty()) m_rpc->check_connection(); } - PyMoneroWalletRpc(const std::vector& cmd); - ~PyMoneroWalletRpc(); PyMoneroWalletRpc* open_wallet(const std::shared_ptr &config); @@ -645,7 +643,6 @@ class PyMoneroWalletRpc : public PyMoneroWallet { boost::optional get_rpc_connection() const; std::vector get_seed_languages() const; void stop(); - void stop_process(); bool is_view_only() const override; boost::optional get_daemon_connection() const override; void set_daemon_connection(const boost::optional& connection, bool is_trusted, const boost::optional> ssl_options); @@ -752,10 +749,6 @@ class PyMoneroWalletRpc : public PyMoneroWallet { protected: inline static const uint64_t DEFAULT_SYNC_PERIOD_IN_MS = 20000; boost::optional m_sync_period_in_ms; - std::unique_ptr m_child_process; - boost::process::ipstream m_out_pipe; - boost::process::ipstream m_err_pipe; - std::thread m_output_thread; std::string m_path = ""; std::shared_ptr m_rpc; std::shared_ptr m_daemon_connection; diff --git a/src/python/monero_daemon_rpc.pyi b/src/python/monero_daemon_rpc.pyi index d3ea307..4fdb0e2 100644 --- a/src/python/monero_daemon_rpc.pyi +++ b/src/python/monero_daemon_rpc.pyi @@ -30,14 +30,6 @@ class MoneroDaemonRpc(MoneroDaemonDefault): :param str password: Authentication password for daemon RPC. """ ... - @typing.overload - def __init__(self, cmd: list[str]) -> None: - """ - Initialize a Monero daemon RPC process. - - :param list[str] cmd: command. - """ - ... def get_rpc_connection(self) -> MoneroRpcConnection: """ Get the daemon's RPC connection. @@ -51,9 +43,4 @@ class MoneroDaemonRpc(MoneroDaemonDefault): :return bool: true if the client is connected to the daemon, false otherwise """ - ... - def stop_process(self) -> None: - """ - Stop Monero daemon RPC process. - """ ... \ No newline at end of file diff --git a/src/python/monero_wallet_rpc.pyi b/src/python/monero_wallet_rpc.pyi index 7298bcd..18ead55 100644 --- a/src/python/monero_wallet_rpc.pyi +++ b/src/python/monero_wallet_rpc.pyi @@ -28,14 +28,6 @@ class MoneroWalletRpc(MoneroWallet): :param str password: Authentication connection password. """ ... - @typing.overload - def __init__(self, cmd: list[str]) -> None: - """ - Initialize a Monero wallet RPC process. - - :param list[str]: Command list - """ - ... def create_wallet(self, config: MoneroWalletConfig) -> MoneroWalletRpc: """ Create and open a wallet on the monero-wallet-rpc server. @@ -81,11 +73,6 @@ class MoneroWalletRpc(MoneroWallet): :return MoneroWalletRpc: this wallet client """ ... - def stop_process(self) -> None: - """ - Stop wallet RPC process. - """ - ... def stop(self) -> None: """ Save and close the current wallet and stop the RPC server. diff --git a/tests/test_monero_connection_manager.py b/tests/test_monero_connection_manager.py index 077c957..35b5204 100644 --- a/tests/test_monero_connection_manager.py +++ b/tests/test_monero_connection_manager.py @@ -2,7 +2,7 @@ from typing import Optional from monero import ( - MoneroWalletRpc, MoneroConnectionManager, MoneroRpcConnection, MoneroConnectionPollType + MoneroWallet, MoneroConnectionManager, MoneroRpcConnection, MoneroConnectionPollType ) from utils import ConnectionChangeCollector, MoneroTestUtils as Utils @@ -12,16 +12,11 @@ class TestMoneroConnectionManager: def test_connection_manager(self): - wallet_rpcs: list[MoneroWalletRpc] = [] + wallet_rpcs: list[MoneroWallet] = Utils.get_wallets("rpc") connection_manager: Optional[MoneroConnectionManager] = None try: i: int = 0 - while i < 5: - wallet_rpcs.append(Utils.start_wallet_rpc_process()) - i += 1 - # start monero-wallet-rpc instances as test server connections (can also use monerod servers) - # create connection manager connection_manager = MoneroConnectionManager() @@ -122,33 +117,6 @@ def test_connection_manager(self): for orderedConnection in ordered_connections: Utils.assert_is_none(orderedConnection.is_online()) - # shut down prioritized servers - Utils.stop_wallet_rpc_process(wallet_rpcs[2]) - Utils.stop_wallet_rpc_process(wallet_rpcs[3]) - Utils.stop_wallet_rpc_process(wallet_rpcs[4]) - Utils.wait_for(Utils.SYNC_PERIOD_IN_MS + 100) # allow time to poll - Utils.assert_false(connection_manager.is_connected()) - connection = connection_manager.get_connection() - assert connection is not None - Utils.assert_false(connection.is_online()) - Utils.assert_is_none(connection.is_authenticated()) - num_expected_changes += 1 - Utils.assert_equals(num_expected_changes, listener.changed_connections.size()) - Utils.assert_equals( - listener.changed_connections.get(listener.changed_connections.size() - 1), - connection_manager.get_connection() - ) - - # test connection order - ordered_connections = connection_manager.get_connections() - Utils.assert_true(ordered_connections[0] == wallet_rpcs[4].get_daemon_connection()) - Utils.assert_true(ordered_connections[1] == wallet_rpcs[0].get_daemon_connection()) - connection = wallet_rpcs[1].get_daemon_connection() - assert connection is not None - Utils.assert_equals(ordered_connections[2].uri, connection.uri) - Utils.assert_true(ordered_connections[3] == wallet_rpcs[2].get_daemon_connection()) - Utils.assert_true(ordered_connections[4] == wallet_rpcs[3].get_daemon_connection()) - # check all connections connection_manager.check_connections() @@ -322,8 +290,6 @@ def test_connection_manager(self): # shut down all connections connection = connection_manager.get_connection() assert connection is not None - for wallet_rpc in wallet_rpcs: - Utils.stop_wallet_rpc_process(wallet_rpc) Utils.wait_for(Utils.SYNC_PERIOD_IN_MS + 100) Utils.assert_false(connection.is_online()) @@ -341,9 +307,3 @@ def test_connection_manager(self): if connection_manager is not None: connection_manager.reset() - # stop monero-wallet-rpc instances - for wallet_rpc in wallet_rpcs: - try: - Utils.stop_wallet_rpc_process(wallet_rpc) - except Exception as e2: - print(f"[!] {str(e2)}") diff --git a/tests/utils/monero_test_utils.py b/tests/utils/monero_test_utils.py index 5211409..83db3bf 100644 --- a/tests/utils/monero_test_utils.py +++ b/tests/utils/monero_test_utils.py @@ -163,48 +163,8 @@ def get_random_string(cls, n: int = 25) -> str: return ''.join(choices(cls.BASE58_ALPHABET, k=n)) @classmethod - def start_wallet_rpc_process(cls, offline: bool = False) -> MoneroWalletRpc: - # get next available offset of ports to bind to - port_offset: int = 1 - while port_offset in cls.WALLET_PORT_OFFSETS.values(): - port_offset += 1 - - # create command to start client with internal monero-wallet-rpc process - cmd: list[str] = [ - cls.WALLET_RPC_LOCAL_PATH, - "--" + cls.get_network_type(), - "--rpc-bind-port", f"{cls.WALLET_RPC_PORT_START + port_offset}", - "--rpc-login", cls.WALLET_RPC_USERNAME + ":" + cls.WALLET_RPC_PASSWORD, - "--wallet-dir", cls.WALLET_RPC_LOCAL_WALLET_DIR, - "--rpc-access-control-origins", cls.WALLET_RPC_ACCESS_CONTROL_ORIGINS - ] - if offline: - cmd.append("--offline") - else: - cmd.extend(["--daemon-address", cls.DAEMON_RPC_URI]) - if cls.DAEMON_RPC_USERNAME != "": - cmd.extend(["--daemon-login", cls.DAEMON_RPC_USERNAME + ":" + cls.DAEMON_RPC_PASSWORD]) - - # start with zmq if enabled - if cls.WALLET_RPC_ZMQ_ENABLED: - cmd.extend(["--zmq-rpc-bind-port", f"{cls.WALLET_RPC_ZMQ_BIND_PORT_START + port_offset}"]) - cmd.extend(["--zmq-pub", "tcp://" + cls.WALLET_RPC_ZMQ_DOMAIN + ":" + f"{cls.WALLET_RPC_ZMQ_PORT_START + port_offset}"]) - else: - #cmd.add("--no-zmq") # TODO: enable this when zmq supported in monero-wallet-rpc - pass - - # register wallet with port offset - try: - wallet = MoneroWalletRpc(cmd) - cls.WALLET_PORT_OFFSETS[wallet] = port_offset - return wallet - except Exception as e: - raise e - - @classmethod - def stop_wallet_rpc_process(cls, wallet: MoneroWalletRpc): - del cls.WALLET_PORT_OFFSETS[wallet] - wallet.stop_process() + def get_wallets(cls, type: str) -> list[MoneroWallet]: + raise NotImplementedError() @classmethod def wait_for(cls, milliseconds: int):