diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2017-01-07 19:23:57 +0000 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2017-01-16 08:59:15 +0000 |
commit | 693c1908815d8574a1125288f0400eab5f5085a7 (patch) | |
tree | 1a93cdf9aaa7cddfcb5241214db82c6c4a1f92c0 /src/wallet/node_rpc_proxy.cpp | |
parent | wallet2: reuse fake outs when adjusting fee on transfer (diff) | |
download | monero-693c1908815d8574a1125288f0400eab5f5085a7.tar.xz |
wallet: add a node RPC cache layer for simple RPC calls
Mostly getinfo and get_hard_fork_info, which are called
pretty often. This speeds up transfers as a bonus.
Diffstat (limited to '')
-rw-r--r-- | src/wallet/node_rpc_proxy.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp new file mode 100644 index 000000000..d7f755e36 --- /dev/null +++ b/src/wallet/node_rpc_proxy.cpp @@ -0,0 +1,134 @@ +// Copyright (c) 2017, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "node_rpc_proxy.h" +#include "rpc/core_rpc_server_commands_defs.h" +#include "common/json_util.h" +#include "storages/http_abstract_invoke.h" + +using namespace epee; + +namespace tools +{ + +void NodeRPCProxy::init(const std::string &daemon_address) +{ + m_daemon_address = daemon_address; + + m_height = 0; + m_height_time = 0; + for (auto &slot: m_earliest_height) + slot = 0; + m_dynamic_per_kb_fee_estimate = 0; + m_dynamic_per_kb_fee_estimate_cached_height = 0; + m_dynamic_per_kb_fee_estimate_grace_blocks = 0; +} + +boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height) +{ + const time_t now = time(NULL); + if (m_height == 0 || now >= m_height_time + 30) // re-cache every 30 seconds + { + cryptonote::COMMAND_RPC_GET_HEIGHT::request req = AUTO_VAL_INIT(req); + cryptonote::COMMAND_RPC_GET_HEIGHT::response res = AUTO_VAL_INIT(res); + + m_daemon_rpc_mutex.lock(); + bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client); + m_daemon_rpc_mutex.unlock(); + CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(res.status != CORE_RPC_STATUS_BUSY, res.status, "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(res.status == CORE_RPC_STATUS_OK, res.status, "Failed to get current blockchain height"); + m_height = res.height; + m_height_time = now; + } + height = m_height; + return boost::optional<std::string>(); +} + +void NodeRPCProxy::set_height(uint64_t h) +{ + m_height = h; +} + +boost::optional<std::string> NodeRPCProxy::get_earliest_height(uint8_t version, uint64_t &earliest_height) +{ + if (m_earliest_height[version] == 0) + { + epee::json_rpc::request<cryptonote::COMMAND_RPC_HARD_FORK_INFO::request> req_t = AUTO_VAL_INIT(req_t); + epee::json_rpc::response<cryptonote::COMMAND_RPC_HARD_FORK_INFO::response, std::string> resp_t = AUTO_VAL_INIT(resp_t); + + m_daemon_rpc_mutex.lock(); + req_t.jsonrpc = "2.0"; + req_t.id = epee::serialization::storage_entry(0); + req_t.method = "hard_fork_info"; + req_t.params.version = version; + bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + m_daemon_rpc_mutex.unlock(); + CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(resp_t.result.status == CORE_RPC_STATUS_OK, resp_t.result.status, "Failed to get hard fork status"); + m_earliest_height[version] = resp_t.result.earliest_height; + } + + earliest_height = m_earliest_height[version]; + return boost::optional<std::string>(); +} + +boost::optional<std::string> NodeRPCProxy::get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks, uint64_t &fee) +{ + uint64_t height; + + boost::optional<std::string> result = get_height(height); + if (result) + return result; + + if (m_dynamic_per_kb_fee_estimate_cached_height != height || m_dynamic_per_kb_fee_estimate_grace_blocks != grace_blocks) + { + epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::request> req_t = AUTO_VAL_INIT(req_t); + epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::response, std::string> resp_t = AUTO_VAL_INIT(resp_t); + + m_daemon_rpc_mutex.lock(); + req_t.jsonrpc = "2.0"; + req_t.id = epee::serialization::storage_entry(0); + req_t.method = "get_fee_estimate"; + req_t.params.grace_blocks = grace_blocks; + bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client); + m_daemon_rpc_mutex.unlock(); + CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon"); + CHECK_AND_ASSERT_MES(resp_t.result.status == CORE_RPC_STATUS_OK, resp_t.result.status, "Failed to get fee estimate"); + m_dynamic_per_kb_fee_estimate = resp_t.result.fee; + m_dynamic_per_kb_fee_estimate_cached_height = height; + m_dynamic_per_kb_fee_estimate_grace_blocks = grace_blocks; + } + + fee = m_dynamic_per_kb_fee_estimate; + return boost::optional<std::string>(); +} + +} |